Reputation: 344
Say I have a User
model, a Task
model that belongs_to :user
, :has_one :event
, has a completed
boolean attribute, and an Event
model that is created when a task is completed, and also belongs_to :event
.
In the TaskObserver
I've noticed that instead of
# 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
I could write
task.create_event(:user_id=>task.user.id)
or even
task.create_event(:user_id=>task.user_id)
While the first way seems the most correct, are there benefits to using either of the latter variations?
Upvotes: 3
Views: 67
Reputation: 344
In this specific case I went with task.create_event(:user_id=>task.user_id)
. By running:
$ 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
you can see that Rails will actually load the User
from the database. Even if it was cached, I don't see why I should handle the actual objects if I'm just copying a reference.
So in general, I think it's preferred to use objects when you've used them before, and IDs when you didn't and don't plan to.
Upvotes: 1
Reputation: 2538
As Beerlington said - there is no "right" or "wrong" here - perhaps a performance consideration to be had however...
In the task.user.id case, if the user isn't eager-loaded, you're making a round trip to the database; in the task.user_id case, you're not making that round trip....
Upvotes: 2
Reputation: 51697
In Rails, associations can be assigned either way, neither is "right" or "wrong" and it's just the nature of the framework. The models has setter methods for both user_id
and user
, which is why you can use either without any noticeable difference.
The way you are creating events seems a little strange to me though. It seems really odd that a task would belong_to an event, but the event is only created when the task is complete. Is that really how it works?
Upvotes: 2