调用关联之前的回调

时间:2013-01-14 19:45:23

标签: ruby-on-rails rails-activerecord

我必须设置关联模型(limesurvey)的表名,因为表名是动态的,取决于模型(任务)的属性(survey_id)。

我的当前实现在初始化任务时设置表名:

class task < ActiveRecord::Base
  after_initialize :setTablename
  has_one :limesurvey

  def setTablename
    Limesurvey.table_name = "lime_survey_#{self.survey_id}"
  end
end

这种实现有效,但它的缺点是,每个任务都会调用setTablename-method,尽管不需要。

如何在加载关联limesurvey之前执行setTablename?

2 个答案:

答案 0 :(得分:2)

警告:我同意你正如评论者所提到的那样,你正在遭受麻烦。此外,这可能会更糟,因为在为每个任务调用setTablename之前。

class Task < ActiveRecord::Base
  has_one :limesurvey

  def lime_survey
    @table_name || = (Limesurvey.table_name = "lime_survey_#{self.survey_id}")

    limesurvey
  end
end

这定义了一个带有下划线的limesurvey版本,但首先检查表名是否已设置。打电话给lime_survey而不是limesurvey,你会得到你要求的效果。

类似于Andy建议的方法。但是,虽然关联只是一种方法,但我不确定你可以重新定义它并调用super,因为它不是父类(或模块)中的方法。

答案 1 :(得分:0)

关联只是模型中包含的模块中定义的方法,因此您可以像其他方法一样覆盖它们

class Task < ActiveRecord::Base
  has_one :limesurvey

  def limesurvey
    # do something here...

    super
  end
end

然而,正如人们在关于这个问题的评论中提到的那样,你所做的是一个非常糟糕的主意。如果您一次有两个任务可用,并试图访问它们上的limesurvey,会发生什么?

t1 = Task.first
t2 = Task.last

l1 = t1.limesurvey
l2 = t2.limesurvey

l1.update_attributes(foo: "bar")
# Oops... saves into the wrong table...

即使您设法避免在整个应用中的任何位置明确地执行此操作,如果您有两个并发请求,则可能会意外发生!