2

我必须设置关联模型(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 方法,尽管它不是必需的。

如何仅在加载关联石灰调查之前执行 setTablename?

4

2 回答 2

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,你就会得到你想要的效果。

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

于 2013-01-14T20:38:39.347 回答
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...

即使您设法避免在整个应用程序的任何地方显式执行此操作,如果您有两个并发请求,它也可能会意外发生!

于 2013-01-14T20:26:39.390 回答