Rails 3中陈旧的ActiveRecord关联问题

时间:2011-03-09 19:02:30

标签: ruby-on-rails activerecord

我有三种模式:网站,订阅,计划:

网站

has_one     :subscription
has_one     :plan, :through => :subscription

订阅

belongs_to  :site
belongs_to  :plan

计划

has_many  :subscriptions

在我的SubscriptionsController中,我通过首先加载相关对象来处理POST:

@site = current_user.site
@subscription = @site.subscription
@plan = @subscription.plan

不幸的是,如果在POST之前修改并保存@ subscription.plan,那么除非我在控制器方法的开头执行@ site.reload,否则该更改不会反映在@site中。

离。

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

有什么想法吗?

更新

下面有两个可行的答案,但是我会暂时不接受其中任何一个,直到我更多地了解了Jesse提到的'触摸'选项(不幸的是,这对我不起作用......) .yet)。

2 个答案:

答案 0 :(得分:1)

您可以通过以下方式获得成功:触摸方式。

一般的想法是,如果我更新评论,帖子的updated_at也会更新。我认为这将转化为内存中的@site记录。

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

当您更新site.subscription.plan时,这将更新订阅和计划。

更多信息:http://ryandaigle.com/articles/2009/4/20/what-s-new-in-edge-rails-touching

答案 1 :(得分:0)

这就是Active Record的设计方式。它试图不经常访问您的数据库,并且更愿意从内存中读取数据库。

最好,您应该修改计划网站,而不是单独修改。基本上,如果你通过@site阅读,你也应该通过@site写作。

如果这不可能或不可取,您可能需要一个小帮助方法检查updated_at列以查看记录是否已更改并重新加载Site(如果有)。如果它听起来很丑陋,那是因为它是。 :)