Hi all,
I’m working on an app where I have a simplified set up like this:
–
create_table :tasks do |t|
t.column :subject, :string
t.column :description, :string
t.column :requester, :integer
t.column :assignee, :integer
end
create_table :users do |t|
t.column :name, :string
end
–
class User < ActiveRecord:Base
end
class Task < ActiveRecord::Base
composed_of :requester, :class_name => ‘User’, :mapping => [ [
:requester, :id ] ]
composed_of :assignee, :class_name => ‘User’, :mapping => [ [
:assignee, :id ] ]
end
–
This is a common pattern we use through many of our apps to track users
and the roles they fill. Each role is guaranteed to have only one user
fit it at any one time, but any user may fit a role in multiple Tasks.
I was hoping that composed_of was the magic bullet, but it doesn’t seem
to be. Given the following little script:
user1 = User.create( :name => “John D.” )
user2 = User.create( :name => “Jane Doe” )
task = Task.create( :subject => “Paint the house”, :description => “How
about a nice shade of yellow?”, :assignee => user1, :requester => user2
)
fromdb = Task.find task.id
puts fromdb.assignee
But the output looks like this:
=> #<User:0x26b9b88 @attributes={“name”=>“John D.”, “id”=>1},
@new_record=false, @errors=#<ActiveRecord::Errors:0x26b73d8 @errors={},
@base=#<User:0x26b9b88 …>>>
user2=User.create( :name => “Jane Doe” )
=> #<User:0x26a190c @attributes={“name”=>“Jane Doe”, “id”=>2},
@new_record=false, @errors=#<ActiveRecord::Errors:0x26a0df4 @errors={},
@base=#<User:0x26a190c …>>>task=Task.create( :subject => “Paint the house”, :description => “How about a nice shade of yellow?”, :assignee => user1, :requester => user2 )
=> #<Task:0x2679240 @assignee=#<User:0x26b9b88
@attributes={“name”=>“John D.”, “id”=>1}, @new_record=false,
@errors=#<ActiveRecord::Errors:0x26b73d8 @errors={},
@base=#<User:0x26b9b88 …>>>, @attributes={“id”=>1, “subject”=>“Paint
the house”, “description”=>“How about a nice shade of yellow?”,
“assignee”=>1, “requester”=>2}, @requester=#<User:0x26a190c
@attributes={“name”=>“Jane Doe”, “id”=>2}, @new_record=false,
@errors=#<ActiveRecord::Errors:0x26a0df4 @errors={},
@base=#<User:0x26a190c …>>>, @new_record=false,
@errors=#<ActiveRecord::Errors:0x266c6e4 @errors={},
@base=#<Task:0x2679240 …>>>fromdb=Task.find task.id
=> #<Task:0x26510ec @attributes={“subject”=>“Paint the house”,
“id”=>“1”, “description”=>“How about a nice shade of yellow?”,
“assignee”=>“1”, “requester”=>“2”}>puts fromdb.assignee
TypeError: can’t dup Fixnum
from
/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/base.rb:1505:in
dup' from /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/base.rb:1505:in
attributes=’
from
/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/base.rb:1354:in
initialize_without_callbacks' from /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/callbacks.rb:236:in
initialize’
from (eval):3:innew' from (eval):3:in
assignee’
from (irb):7
At first glance, it seems clear I have done something completely wrong,
and that composed_of isn’t for me in this instance. I’m hoping I just
have a typo, but I don’t think I do…
So I was hoping someone could point me in the direction of the
“correct” way of doing this? I use this particular pattern in many
places, and I’m wondering if I really have to implement this style of
accessor/mutator everywhere I do (assuming I renamed the two db columns
to requester/assignee_user_id):
def requester
return User.find( @requester_user_id )
end
def requester=(requester)
user = User.find( requester.id )
if user
@requester_user_id = user.id
end
end
def assignee
return User.find( @assignee_user_id )
end
def assignee=(assignee)
user = User.find( assignee.id )
if user
@assignee_user_id = user.id
end
end
Any help would be much appreciated. Thanks!
– mark