UPDATE: See Using Spreedly with Merb via HTTParty instead.
This article is not yet completed.
Spreedly is great. So clever. Nathaniel Tablott, you are awesome. I really have enjoyed trying it out, but it required me to learn some new skills – namely hooking up to restful web services – I had never done that before. This was also the first time I had ever worked with ‘payment processing’ so to speak – spreedly actually does all the processing.
Watch this video by the creator of Spreedly to see how to do this.
Also, here’s the guide.
Your create action is where things happen so let’s redirect the user after they create their account/site. *If you are dealing with multiple plans you should replace the Merb::Config[:spreedly_plan_one_id] with a passed in value of the user’s chosen plan
1 def create(site, user) 2 @site = Site.new(site) 3 @user = @site.users.build(user) 4 5 if @site.save && @user.valid? 6 # encodes message for merb's message[:notice] to redisplay. 7 notice = encoded_notice(:message => {:notice => 'Site was successfully created'}) 8 9 redirect "#{Merb::Config[:spreedly_url]}/subscribers/#{@site.id}/subscribe/#{Merb::Config[:spreedly_plan_one_id]}/#{@site.subdomain}?return_url=http://#{@site.subdomain}.#{Merb::Config[:site_url]}?_message=#{notice}" 10 11 else 12 @site.destroy 13 message[:error] = "Site failed to be created" 14 render :new 15 end 16 end
The rest all happens on spreedly, and then the user gets redirected via the return_url. That’s how easy it is to accept payment.
Also, here’s the encoded notice helper. Put this in your global helpers.
1 def encoded_notice(opts = {}) 2 # from /home/merb/merb-docs/current/gems/gems/merb-core-1.0.8.1/lib/merb-core/controller/mixins/controller.rb, line 132. this is something that could definitely end up needing fixing 3 default_redirect_options = { :message => nil, :permanent => false } 4 opts = default_redirect_options.merge(opts) 5 if opts[:message] 6 "#{Merb::Parse.escape([Marshal.dump(opts[:message])].pack('m'))}" 7 end 8 end
1 def encoded_notice(opts = {})
2 # from /home/merb/merb-docs/current/gems/gems/merb-core-1.0.8.1/lib/merb-core/controller/mixins/controller.rb, line 132. this is something that could definitely end up needing fixing
3 default_redirect_options = { :message => nil, :permanent => false }
4 opts = default_redirect_options.merge(opts)
5 if opts[:message]
6 "#{Merb::Parse.escape([Marshal.dump(opts[:message])].pack(‘m’))}"
7 end
8 end
Getting subscriber info from Spreedly
We will use ActiveResource to create a Subscriber model that queries the Spreedly api.
1 $ merb-gen model Subscriber1 # models/subscriber.rb 2 class Subscriber < ActiveResource::Base 3 self.site = "https://2fc4873fb65e3652eb36438be7422a424fa810e:X@spreedly.com/api/v4/test-investobot" 4 endAdd active resource to your merb dependencies.rb file.
1 dependency "activeresource", "2.3.0"
1 dependency "activeresource", "2.3.0"
Bundle it up.
1 $ thor merb:gem:install
1 $ thor merb:gem:install
No you can run commands like this in merb -i
1 merb -i 2 > Subscriber.create(:customer_id => "1", :screen_name => 'mottemen') 3 > Subscriber.find(:all) 4 # see https://spreedly.com/manual/integration-reference/api-access-using-rails/ for more details
1 merb -i
2 > Subscriber.create(:customer_id => "1", :screen_name => ‘mottemen’)
3 > Subscriber.find(:all)
4 # see https://spreedly.com/manual/integration-reference/api-access-using-rails/ for more details
You can now use your model to pull down subscriber info and post it on the user’s account page. Cool, huh.
Instead of storing all this information in the user, account, or sites table we are letting Spreedly store it, and using our Subscriber model as a go between to display it for us in our views. *You’ll probably want to cache this Subscriber info – otherwise, you will slow your application down by waiting on Spreedly.
Example:
1 @subscriber = Subscriber.find(:first) 2 <p>Active: <%= @subscriber.active # returns true or false %></p> 3 <p>Full Name: <%= @subscriber.billing_first_name %> <%= @subscriber.billing_last_name %></p>
1 @subscriber = Subscriber.find(:first)
2 <p>Active: <%= @subscriber.active # returns true or false ></p>
3 <p>Full Name: <= @subscriber.billing_first_name > <= @subscriber.billing_last_name %></p>
Listen for changes from Spreedly
Since Spreedly is keeping track of everything, we need to listen for changes whenever they happen. For example in our app, we might have a before filter that checks if the current site is active.
In sites.rb for datamapper you property schema would have the following along with the rest of your schema like subdomain, domain, folder, timestamps, etc.
1 property :active, Boolean, :default => false 2 property :spreedly_token, String
1 property :active, Boolean, :default => false
2 property :spreedly_token, String
Then in application.rb we could do something like:
1 class Application < Merb::Controller 2 3 before :get_site 4 def get_site 5 if request.first_subdomain != nil 6 @current_site = Site.first(:subdomain => request.first_subdomain) 7 if @current_site.active == false 8 # redirect somewhere or raise an exception 9 end 10 end 11 end 12 13 end
1 class Application < Merb::Controller
2
3 before :get_site
4 def get_site
5 if request.first_subdomain != nil
6current_site</span> = <span class="co">Site</span>.first(<span class="sy">:subdomain</span> => request.first_subdomain) <span class="no"> 7</span> <span class="r">if</span> <span class="iv">current_site.active == false
8 # redirect somewhere or raise an exception
9 end
10 end
11 end
12
13 end
But what happens if a subscriber on Spreedly stops paying for their site? We need a way to keep track of that. We could use Subscriber.find(subscriber_id).active. This will now be equal to false, but we don’t want to have to manually check these all the time. We could run a cron job to check spreedly, but Spreedly makes it easier than that.
Each time one of your subscribers change Spreedly sends a restful post to the url of your choosing one minute later. All we need to do is create this restful post route and then tell Spreedly about it in the settings. Let’s do it.
This is gleaned from here.
1 # router.rb 2 resources :sites, :collection => { :changed_on_spreedly => :post }1 # sites.rb controller 2 class Sites < Application 3 # provides :xml, :yaml, :js 4 5 def changed_on_spreedly(subscriber_ids) 6 subscriber_ids = subscriber_ids.split(",") 7 subscriber_ids.each do | subscriber_id | 8 site = Site.get(subscriber_id) 9 site.refresh_from_spreedly if site 10 end 11 end 12 13 ..As you can see it takes the subscriber_ids that spreedly sends us, parses them up, and then refreshes the site from spreedly with parameters we specify in refresh_from_spreedly. Let’s check that method out.
1 # site.rb model 2 .. 3 4 # Spreedly method from https://spreedly.com/manual/integration-guide/expose-a-change-subscription-link/ 5 # also here http://github.com/duff/crew/commit/e839084b49f8d18feccfb2457e9d0984e1c93a3c 6 def refresh_from_spreedly 7 # Subscriber is using activeresource 8 subscriber = Subscriber.find(self.id) 9 self.update_attributes(:active => subscriber.active, :spreedly_token => subscriber.token) 10 rescue NotFound 11 self.update_attribute(:active, false) 12 endDon’t forget to change your Subscribers Changed Notification URL on Spreedly.com to the one we specified as /sites/changed_on_spreedly
That is as much as I have so far from my forays into Spreedly yesterday evening. I also tried using HTTParty and rest-client, but with no luck so I stuck with activeresource.
Notes:
- I used my merb-auth-slice-multisite for the subdomains.
- I gleaned pretty much all of this from Spreedly Integration Guide
- Pelargir’s spreedly radiant extension was also helpful.
![]()
Spitfire Sky | github | archives | resume