RailsCasts Pro episodes are now free!

Learn more or hide this

Recent Comments

Avatar

The hidden plan_id field is actually set because of the call to plan.subscriptions.build method. Without that call, :plan_id hidden field within the form would be nil.

You're using the build method to set that value within the form. That way, when you call the Subscription.new method using the params hash, it will know which plan the subscription is associated with.

Avatar

Got it. But in the create action, isn't he already setting this association when passing in the params hash into Subscription.new()? Doesn't the params hash contain the plan id since the form has a hidden field for the plan id (f.hidden_field :plan_id)? In other words, is he setting the association twice?

Avatar

When switching to spork I encountered a string of errors like this:

Break on __THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY___YOU_MUST_EXEC__() to debug.
/Users/username/.rvm/gems/ruby-1.8.7-p334/gems/rb-appscript-0.6.1/lib/_aem/connect.rb:86: [BUG] Segmentation fault
ruby 1.8.7 (2011-02-18 patchlevel 334) [i686-darwin10.7.0]

This happened when using the gem 'growl_notify'. Switching my Gemfile over to just use gem 'growl' fixed this error.

Avatar

I haven't used either, but based on their prices i would recommend Stripe

Avatar

Great work, i've been using active merchant fork supporting PPR for express checkout, and this does seem like a much lighter solution.

Very nicely done :)

Avatar

Is something like this what was used for the railscasts pro? I thought my statement showed something other than paypal..

(may we ask what was used for this sites payments?)

Avatar

really like the coffee script stuff in this, I learned a lot

Avatar

In case someone's still looking for an easy answer to searching in multiple attributes, you can set it up like the where params in scopes:

def self.search(search)
 if search
  find(:all, :conditions => ['first_name LIKE ? || last_name LIKE ? || company_name LIKE ?', "%#{search}%", "%#{search}%", "%#{search}%"])
 else
  find(:all)
 end
end
Avatar

Excellent and just in time. I've been stuck trying to choose between Spreedly, Chargify, Recurly etc. but they're so expensive by the time you factor in internet merchant accounts and payment gateways etc. I really want to hear more about Paypal recurring payments!

I'd love to see a future episode on advanced subjects such as failed payments, canceled subscriptions and importantly upgrades/downgrades between packages and the associated pro-rata calculations. Usually very complex stuff (in terms of business logic) but I'm sure it's a subject you can cover with relative ease given your style! :)

Thanks for a great screencast!

Avatar

Since jQuery 1.6 you should use prop() method to set boolean attributes: $('input[type=submit]').prop('disabled', true)

Avatar

Thanks.

A couple of questions about your implementation of save_with_subscription:

1) you use save! in your implementation. Would it be better to either return the result of save, or change the name of the function to save_with_subscription!, in order to better follow conventions?

2) I noticed that you don't handle failures to save. In the real world, we would need to handle that failure by manually rolling back the subscription creation. Or is there a better way to handle this with Stripe?

Avatar

I would also like to see an episode on insufficient funds and subscription cancellations. I would also like to see how you create tests for external web services like paypal, stripe or whatever.

Avatar

There is no PayPal yet in my work, but it was interesting to watch this episode. One thing that bothers me though is that you skip testing part which is crucial in billing and payments. I know, the episode would be two times longer if you covered this as well but it was very scary to see you just quickly testing the stuff in a browser.

Avatar

Hmm... Personally I think I would have added the erb-preprocessor to the coffeescript-file and referenced the constant through an erb block:

jQuery ->
  Stripe.setPublishableKey('<%= STRIPE_PUBLIC_KEY %>')
Avatar

Sign up here

https://stripe.com/help/global

Maybe it will encourage them to speed things along :)

Avatar

Thanks for accommodating us non-US users with this cast. Hopefully Stripe will do too soon.

Avatar
  1. Also means you could re-use the same JS file with another project. For example if you build a merchant hosting site where each of your users can create their own merchant site hosted by you, you could change easily who the payment is going to while using the same JS file for everyone.

  2. Some peculiarities of Ruby's parser (nothing to do with Rails). Without self, it would think you are trying to assign a local stripe_customer_token variable instead of using the implicitly defined self.stripe_customer_token= attribute writer.

Avatar

That would likely trigger a Stripe::InvalidRequestError when trying to Stripe::Customer.create( card: stripe_card_token) with your faked stripe_card_token, and thus prevent saving the subscription record.

Avatar

Hey guys. Delighted there's now more Railscasts loveliness each week. Yay.

I'm a little confused about what to do with application wide presenters. For example, I want to show either a "Sign In" link or a "Log Out" link depending on whether the user's logged in. This is somewhere I would normally include some logic in the view, probably the app layout and it'd be great to move it to a presenter. But which one?

I'm playing with Sorcery following your recent episode, so I have a current_user object I can inspect to determine whether anybody's logged in. But it's not referenced through a model so I don't know how to move it to a decorator. I could decorate the user model but creating an @user instance in every view feels, well, odd.

Any guidance would be gratefully received.

Avatar

Am I correct in thinking that I could bypass the credit card payment altogether by manually setting a value to the hidden token field (using javascript console or similar before submitting)?

Avatar

Unfortunately many of us have no option to use stripe. So this is a great resources for people outside the US.

Thanks ryan.

Avatar

Thank you for releasing this screencast about PayPal recurring billing.

I am also interested in a follow-up episode re handling insufficient funds, changing the plan or canceling the subscription.

Avatar

Thank you! Looking forward to the episode about handling insufficient funds, end of subscription and possibly the case when a user changes his plan.

Avatar

@1: Because this makes it easily configurable from, for example yml file.
@3: plan.subscriptions.build is equivalent of Subscription.new(plan: plan)

Avatar

Which is better to use? Braintree or stripe?

Avatar

Regarding question 3...

It has to do with the model associations.

When you say:

@subscription = plan.subscriptions.build

you are really saying something like:
@subscription = Subscription.new(plan_id: id)

You are wanting an object that already has the association (to a particular Plan, in this case) set. This object is passed to the form with the association set -- so it knows how this particular Subscription object relates to a specific Plan object.

see: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

Avatar

meltzerj,

Regarding question 2...

You can see that Ryan adds a stripe_customer_token to the subscription model:

rails g migration add_stripe_to_subscriptions stripe_customer_token:string

self.stripe_customer_token = customer.id sets that in the current subscription object (taken from the object returned by Stripe::Customer.create() method).

Hope that helps!

Avatar

Hi Ryan,
Thanks for this amazing cast.
I was wondering if you can do another cast regarding Ebay complex database categories. Is Ancestry gem enough or should we go deeper.

Thanks anyway!

Avatar

Thanks!

A couple of questions:

  1. Why do you pass the API key into the meta tag and grab it in the javascript instead of just hard coding it into the javascript?

  2. In the "save_with_payment" instance method, why do you reference "self" when assigning the customer id to an attribute of the instance.

  3. In the new action of the subscriptions controller, why do you need "@subscription = plan.subscriptions.build"?

Avatar

Great video on a great service. For those outside the US, know that Stripe is working on it. :)

Stripe on HackerNews

Avatar

I cannot believe how easy Stripe has made ecomm for developers! Thanks for the intro to this killer offering.

Avatar

Very nice recommendation! I hadn't seen stripe before and have been grudgingly testing other payment processors. This looks fantastic and very reasonable

Avatar

Just what I was about to use! Always on the ball.

Avatar

TL;DR Use Stripe :)

Actually I really appreciate the effort you took to put this together Ryan, even if it came out a bit longer than expected. It's certainly not one of the easier pieces of rails integration and is a great choice for a pro episode. Many websites will still require this so it's a valuable addition!

Avatar

Thank you, Ryan Bates ... beauty, even in work, speaks for itself.

I have actually viewed and coded every single episode
... yes, play+pause+type, repeat ... the ASCIIcasts really help doing this.
It kind of helps to take the 'Monday' out of Mondays.

Will there be a script or something like ASCIIcasts for the pro versions ?

This is just a thought, not a criticism, but I was wondering if it might
be possible to purchase individual pro episodes ?

I mean a pricing scheme similar to renting movies/games at one of
those redbox kiosks ... a $1 is a great price. In this area they have
really caught on at grocery stores and 7-11's ... I almost expect to
see one on my porch one day. I think a recurring payment might be
a barrier to some, especially during these troubled times ... just a thought.

Thank you again.

Avatar

Why should it? HAML is just templating language so you would just use same methods in HAML syntax from the view.

Avatar

i like the idea, but if i start refactoring with a decorator i come across one big problem.

if i wanna wrap a small method to a decorator like user.full_name i would have to make tons of decorators to wrap all my associations, like note.user.full_name, project.owner.full_name etc. well maybe its just realy for big view stuff. but i would love to use it also for the small parts.

+ cancan not liking it :)

Avatar

Very nice. I've been wanting to get rid of helpers in our application for a quite a while and this looks like a very clean and elegant solution.

Avatar

Any suggestions on how to write a presenter for a collection of object, like for an index view?

Avatar

Tried to upgrade my blog from 3.0.9 to 3.0.10 and 3.1.0 like you did in the tutorial but I got the most stupid error ever with no proper message, so I have no idea whatsoever of what's going on:

Started GET "/admin" for 127.0.0.1 at 2011-10-10 12:28:33 +0300

ArgumentError (wrong number of arguments (3 for 2)):

Rendered c:/Ruby192/lib/ruby/gems/1.9.1/gems/actionpack-3.1.0/lib/action_dispatch/middleware/templates/rescues/_trace.erb (1.0ms)
Rendered c:/Ruby192/lib/ruby/gems/1.9.1/gems/actionpack-3.1.0/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (1.0ms)
Rendered c:/Ruby192/lib/ruby/gems/1.9.1/gems/actionpack-3.1.0/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (10.0ms)

Help?

Avatar

Why not use the presence method to make the avatar_name method a 1-liner?

ruby
def avatar_name
  model.avatar_image_name.presence || 'default.png'
end
Avatar

Try running it like this:

ruby
bundle exec spork
Avatar

Try replacing it with the following:

ruby
# user.username_attribute_name = :email
user.username_attribute_names = [:email]    
Avatar

This could be b'cos to_json returns values within { } and the token inputs js looks for [{ ...}] format, this is my guess. Thanks for posting this , wasted 3 hrs on this :)

Avatar

Done,
but doesn't seem to work anyway.

My last working gems matrix is :

bson (1.4.0)
bson_ext (1.4.0)
mongo (1.4.0)
mongoid (2.1.1)
mongoid-rspec (1.4.4)
mongoid_taggable_with_context (0.7.2)

as soon as I upgrade to mongoid 2.1.2,
kaminari '0.12.4' First/Previous/Next/Last in the view don't show up anymore ...

Avatar

I followed this blog entry to load custom validators from lib/validators. I also named the EmailFormatValidator to EmailValidator. It makes more sense to me. :email => true. Great screencast as always, just needs the little update about loading validators. :)

Here's the snippet:

ruby
mkdir lib/validators

config/application.rb

ruby
config.autoload_paths += Dir["#{config.root}/lib/**/"]