假设我有User
模型,Task
模型,belongs_to :user
,:has_one :event
,completed
布尔属性,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)
虽然第一种方式看起来最正确,但使用后一种变体是否有好处?
答案 0 :(得分:2)
在Rails中,可以以任何方式分配关联,既不是“正确”也不是“错误”,它只是框架的本质。模型具有user_id
和user
的setter方法,这就是为什么你可以使用任何一个没有任何明显差异的原因。
你创建事件的方式对我来说似乎有点奇怪。一个任务属于一个事件似乎很奇怪,但事件只在任务完成时才创建。它真的是这样的吗?
答案 1 :(得分:2)
正如比尔林顿所说的那样 - 这里没有“正确”或“错误” - 或许可以考虑性能因素......
在task.user.id的情况下,如果用户没有急切加载,那么你正在往返数据库;在task.user_id的情况下,你没有进行往返....
答案 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
。即使 缓存了,如果我只是复制一个引用,我也不明白为什么我应该处理实际的对象。
所以一般情况下,我认为在您之前使用过对象时最好使用对象,而在不使用对象时使用对象。