Reputation: 2208
I have three models: Site, Subscription, Plan:
Site
has_one :subscription
has_one :plan, :through => :subscription
Subscription
belongs_to :site
belongs_to :plan
Plan
has_many :subscriptions
In my SubscriptionsController I'm handing a POST by first loading the relevant objects:
@site = current_user.site
@subscription = @site.subscription
@plan = @subscription.plan
Unfortunately, if @subscription.plan is modified and saved before the POST then that change is not reflected in @site unless I perform a @site.reload at the beginning of my controller method.
ex.
eval @subscription
> #<Subscription id: 6115, site_id: 5634, plan_id: 342, ... <== GOOD
eval @site.plan
> #<Plan id: 337, ... <== BAD
eval @subscription.site.plan
> #<Plan id: 342, ... <=== GOOD
eval @site.reload
eval @site.plan
> #<Plan id: 342,... <== GOOD
Any ideas?
UPDATE
There are two viable answers below, but I'm going to hold off on accepting either of them until I learn more about the 'touch' option that Jesse mentioned (which, unfortunately, doesn't work for me....yet).
Upvotes: 0
Views: 1332
Reputation: 40277
You may find success with the :touch method on your relations.
The general idea is that if I update a comment, the posts's updated_at will get updated as well. I think this will translate to your @site record in memory.
class Site
has_one :subscription, :touch=>true
has_one :plan, :through => :subscription, :touch=>true
class Subscription
belongs_to :site, :touch=>true
belongs_to :plan, :touch=>true
When you update your site.subscription.plan, this will update the subscription and the plan.
More information: http://ryandaigle.com/articles/2009/4/20/what-s-new-in-edge-rails-touching
Upvotes: 1
Reputation: 8202
It's just how Active Record is designed. It tries not to hit your database too often and will prefer to read from memory than the database.
Preferably, you should be modifying the Plan through the Site rather than separately from it. Basically, if you're reading by going through the @site, you should be writing through @site, as well.
If that's not possible or desirable, you may want to have a small helper method checking the updated_at column to see if the record has changed and reloading Site if it did. If it sounds hacky, that's because it is. :)
Upvotes: 0