I am trying to get polymorphic relations to work for my app. What I am trying to do is explained by this picture http://iroll.org/code/ I can''t figure out the code for in the controller to create a new phone_number and assign it to a person. I have tried everything I can think of. A) do my models look correct? B) what would the commands look like in the console or a controller action look like to save something to a person? I have been messing with this all afternoon, I got the example in the recipe book working, I just can''t get this working. -- Posted via http://www.ruby-forum.com/.
scott <scottnj@...> writes:> > I am trying to get polymorphic relations to work for my app. What I am > trying to do is explained by this picture > http://iroll.org/code/ > I can''t figure out the code for in the controller to create a new > phone_number and assign it to a person. I have tried everything I can > think of. > > A) do my models look correct? > B) what would the commands look like in the console or a controller > action look like to save something to a person? > > I have been messing with this all afternoon, I got the example in the > recipe book working, I just can''t get this working. >These models will definitely work. I have a *very* similar structure in my app, except that I reuse the same contact-item PK ID in the address/phone/email tables (which was probably more hassle than it was worth). The creation code in controller goes something like this: @person = Person.find(params[:id]) @person.create_phone(params[:phone]) Tough, huh? It all happens in the model: class Person end
Kian <kianwright@...> writes:> > scott <scottnj <at> ...> writes: > > > > > I am trying to get polymorphic relations to work for my app. What I am > > trying to do is explained by this picture > > http://iroll.org/code/ > > I can''t figure out the code for in the controller to create a new > > phone_number and assign it to a person. I have tried everything I can > > think of. > > > > A) do my models look correct? > > B) what would the commands look like in the console or a controller > > action look like to save something to a person? > > > > I have been messing with this all afternoon, I got the example in the > > recipe book working, I just can''t get this working. > > > > These models will definitely work. I have a *very* similar structure in my app, > except that I reuse the same contact-item PK ID in the address/phone/email > tables (which was probably more hassle than it was worth). > > The creation code in controller goes something like this: > > <at> person = Person.find(params[:id]) > <at> person.create_phone(params[:phone]) > > Tough, huh? It all happens in the model: > > class Person > > end >Well that was weird. Guess I accidentally posted the response. Anyway, something like this: class Person def create_contact_item(type) contact_item = ContactItem.new({:person_id => self.id, :addressable_type => type}) contact_item.save && contact_item end def create_phone(params) contact_item = create_contact_item(AddressableType::PHONE) phone = Phone.new(params) phone.id = contact_item.id phone.save && phone end end The trouble with your model is going to be that you need to get a unique ID for the phone/address/email to be the PK, but you also need it to be already present in the contact-item table to satisfy the foreign key. Unless you generate it external to the database (not recommended), I don''t see how you will be able to easily do it. I''d recommend trying to use the same ID for the contact-item and the child tables too. If you''re really ambitious, you can set up a person has many phones and probably override the << method on the person.phones to accept your request parameters and create a new phone and contact item. That''d be cool.
> These models will definitely work. I have a *very* similar structure in > my app, > except that I reuse the same contact-item PK ID in the > address/phone/email > tables (which was probably more hassle than it was worth). > > The creation code in controller goes something like this: > > @person = Person.find(params[:id]) > @person.create_phone(params[:phone]) > > Tough, huh? It all happens in the model: > > class Person > > endThat does not seem to work for me. In the console I type: p = Person.find(:first) p.create_email(:label => "work", :address => "test@example.com) The second line returns: NoMethodError: undefined method ''create_email'' for #<Person:0x37a66e8> What''s different? -- Posted via http://www.ruby-forum.com/.
On 9-May-06, at 7:46 PM, scott wrote:>> These models will definitely work. I have a *very* similar >> structure in >> my app, >> except that I reuse the same contact-item PK ID in the >> address/phone/email >> tables (which was probably more hassle than it was worth). >> >> The creation code in controller goes something like this: >> >> @person = Person.find(params[:id]) >> @person.create_phone(params[:phone]) >> >> Tough, huh? It all happens in the model: >> >> class Person >> >> end > > That does not seem to work for me. > In the console I type: > p = Person.find(:first) > p.create_email(:label => "work", :address => "test@example.com) > > The second line returns: > NoMethodError: undefined method ''create_email'' for #<Person:0x37a66e8> > > What''s different?I too have virtually the same data model, and have the same problem as you Scott. ...which leads me to ask if there''s a way to query all methods for an object, which may help debug such a symptom. Jodi
Kian wrote:> Well that was weird. Guess I accidentally posted the response. Anyway, > something > like this: > class Person > def create_contact_item(type) > contact_item = ContactItem.new({:person_id => self.id, > :addressable_type => > type}) > contact_item.save && contact_item > end > > def create_phone(params) > contact_item = create_contact_item(AddressableType::PHONE) > phone = Phone.new(params) > phone.id = contact_item.id > phone.save && phone > end > end > > The trouble with your model is going to be that you need to get a unique > ID for > the phone/address/email to be the PK, but you also need it to be already > present > in the contact-item table to satisfy the foreign key. Unless you > generate it > external to the database (not recommended), I don''t see how you will be > able to > easily do it. I''d recommend trying to use the same ID for the > contact-item and > the child tables too. > > If you''re really ambitious, you can set up a person has many phones and > probably > override the << method on the person.phones to accept your request > parameters > and create a new phone and contact item. That''d be cool.I think I see what you are doing here, but when I try p = Person.find(:first) p.create_phone(:label => "work") I get NameError: unitialized constant AddressableType How do you get type passed for the polymorphic relations? I also tried putting it in quotes,that stores "AddressableType::PHONE" in the table but addressable_id is still null. -- Posted via http://www.ruby-forum.com/.
scott <scottnj@...> writes:> I think I see what you are doing here, but when I try > p = Person.find(:first) > p.create_phone(:label => "work") > > I get > NameError: unitialized constant AddressableType > > How do you get type passed for the polymorphic relations? I also tried > putting it in quotes,that stores "AddressableType::PHONE" in the table > but addressable_id is still null. >Sorry, I didn''t expand on it in more detail. I assumed that you had a model or class or module that enumerates the addressable-type values. Instead of AddressableType::Phone, put whatever value you use to for your addressable-type field in the database to indicate that the contact-item is a phone. At least that''s what I think that field means. Ignore this comment if that''s not what the field is in your model. Maybe I misunderstand...
scott, you wrote,>I am trying to get polymorphic relations to work for my app. What I am >trying to do is explained by this picture >http://iroll.org/code/ >I can''t figure out the code for in the controller to create a new >phone_number and assign it to a person. I have tried everything I can >think of.You''ve got your polymorph relationships around the wrong way. The people have many contact_items as addressable, ie.: class Person < ActiveRecord::Base has_many :contact_items, :as => :addressable # then your create_phone_number method would look something like this def create_phone_number(params) ci = ContactItem.new(:person_id => id) # this next line *is* the polymorphism ci.addressable = PhoneNumber.create(params) ci.save contact_items << ci end end Note that one of the benefits of polymorphism is that you DON''T need to worry about overlapping PKs in the various address tables, and you DON''T need to worry about doing the addressable_type yourself. Rails handles the type for you, and the fact that there''s a type means that the PKs can (and should) overlap, that''s not a problem because the foreign key is really a multi-column foreign key including the addressable_type. So, just to complete the picture, contact_item.rb was correct, but all your individual address tables need to drop the :as => :addressable, here''s the PhoneNumber one, the rest are the same idea: class PhoneNumber < ActiveRecord::Base has_one :contact_item end To see this in the console: >> p = Person.create( :first_name => "Foo" ) >> p.create_phone_number(:first_numbers => "123", :second_numbers => "456") >> p.contact_items[0].addressable_type >> p.contact_items[0].addressable.first_numbers -- The evil of the world is made possible by nothing but the sanction you give it. -- Ayn Rand