是否应该直接使用协会的ID?

时间:2010-11-27 17:15:47

标签: ruby-on-rails activerecord

假设我有User模型,Task模型,belongs_to :user:has_one :eventcompleted布尔属性,Event完成任务时创建的模型,以及belongs_to :event

TaskObserver我注意到了,而不是

# app/controllers/task_observer.rb
class TaskObserver < ActiveRecord::Observer
def after_update(task)
  def after_update
    task.create_event(:user=>task.user) if task.completed?
  end
end

我可以写

task.create_event(:user_id=>task.user.id)

甚至

task.create_event(:user_id=>task.user_id)

虽然第一种方式看起来最正确,但使用后一种变体是否有好处?

3 个答案:

答案 0 :(得分:2)

在Rails中,可以以任何方式分配关联,既不是“正确”也不是“错误”,它只是框架的本质。模型具有user_iduser的setter方法,这就是为什么你可以使用任何一个没有任何明显差异的原因。

你创建事件的方式对我来说似乎有点奇怪。一个任务属于一个事件似乎很奇怪,但事件只在任务完成时才创建。它真的是这样的吗?

答案 1 :(得分:2)

正如比尔林顿所说的那样 - 这里没有“正确”或“错误” - 或许可以考虑性能因素......

在task.user.id的情况下,如果用户没有急切加载,那么你正在往返数据库;在task.user_id的情况下,你没有进行往返....

  • 注意 - Rails可能足够聪明,可以注意到如果你只是从关联中获取id,它可以只使用task.user_id - 但我还没有竭尽全力来证实这一点。很容易检查development.log ....

答案 2 :(得分:1)

在这个具体案例中,我选择task.create_event(:user_id=>task.user_id)。通过运行:

$ rails c
ruby-1.8.7-p299 > ActiveRecord::Base.logger = Logger.new(STDOUT)
ruby-1.8.7-p299 > Task.where("user_id IS NOT NULL).user.id
...
User Load (1.2ms)  SELECT `users`.* FROM `users` WHERE (`users`.`id` = 103) LIMIT 1
=> 103

你可以看到Rails实际上会从数据库中加载User。即使 缓存了,如果我只是复制一个引用,我也不明白为什么我应该处理实际的对象。

所以一般情况下,我认为在您之前使用过对象时最好使用对象,而在不使用对象时使用对象。