mark j. hughes
2006-Sep-28 01:44 UTC
Mapping external objects locally to arbitrarily named columns
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 Doe" ) 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 Doe", "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 Doe", "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.assigneeTypeError: 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:in `new'' 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 --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
Maxim Kulkin
2006-Sep-28 04:43 UTC
Re: Mapping external objects locally to arbitrarily named columns
mark j. hughes ïèøåò:> 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 >class Task < ActiveRecord::Base belongs_to :requester, :class_name => ''User'', :foreign_key => ''requester'' belongs_to :assignee, :class_name => ''User'', :foreign_key => ''assignee'' end You can RDoc everything else. I also suggest you to rename columns to requester_id and assignee_id. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
mark j. hughes
2006-Sep-28 18:32 UTC
Re: Mapping external objects locally to arbitrarily named columns
Wow. How embarassing... Thanks for your reply, Maxim. Ex post facto, it makes total sense, but it just didn''t appear intuitive that the foreign_key is actually the local key, since belongs_to is defining a backwards relationship from another object/table. Thanks so much! --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---