I have a relationship were a person can have 1 item, and this item is either a A || B || C. Rails supports the belongs_to polymorphic, but I don''t see how can a Model have one of several models as opposed to belong_to one of several models. Can anyone tell me how to map this relationship ? -- 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Is this a one-to-one, or one-to-many relationship? Which class should has the foreign key? Do your A, B, and C classes have a foreign key to person, or do you want person to have a foreign key to one of the other 3 models? -- 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Yes I''d like person to have the foreign key to have a foreign key to one of the other 3 models. On Nov 1, 8:59 am, Tim Shaffer <timshaf...-BUHhN+a2lJ4@public.gmane.org> wrote:> Is this a one-to-one, or one-to-many relationship? > > Which class should has the foreign key? Do your A, B, and C classes > have a foreign key to person, or do you want person to have a foreign > key to one of the other 3 models?-- 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@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?hl=en.
dpal wrote in post #958489:> I have a relationship were a person can have 1 item, and this item is > either a A || B || C. > Rails supports the belongs_to polymorphic, but I don''t see how can a > Model have one of several models as opposed to belong_to one of > several models. > Can anyone tell me how to map this relationship ?You want Person belongs_to Item. Remember, belongs_to is used for the table that contains the foreign key field. Best, -- Marnen Laibow-Koser http://www.marnen.org marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org -- Posted via http://www.ruby-forum.com/. -- 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Yup, then like Marnen said, Person should belong to Item: belongs_to :item, :polymorphic => true In your migration, you can use: t.references :item, :polymorphic => true Which will create item_type and item_id columns. Then each class A, B, and C can have one person: has_one :person, :as => :item -- 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Awesome thank you so much, I had come to that conclusion although it didn''t seem natural. This is what my spec looks like, I think its correct: Database Associations What we want: There are users, construction companies, real state companies and natural persons. A user controls one of the 3 entities(construction companie, real state company or natural person). And each of this entities has listings, and in the case of construction company also projects. The relationships are as followed: 1. user has_one :construction_company or :real_state_company or :natural_person 2. construction_company has_many ---> :projects which has_many ---> : listings 3. real_state company has_many ----> :listing 4. natural_person has_one----> :listings How this looks in code: We need to use polymorphic associations to be able to express this relationships, because for example listings belongs to all 3 type of entities, thus listings has to be polimorphic. :listings belongs to-> projects, real_state_company, natural_person We start by looking at what this 3 entities have in common, mainly that they are the sellers, so we will add to the databes a foreign key that lists the seller identification(seller_id) and which type of seller he is(construction company or real state company etc). In rails this is accomplished by: $rails generate model Listing …. seller_id:integer seller_type:string This will ad a seller_id and seller_type to the migrations. Rails has a way of simplifying this by replacing the 2 keys with: t.references :seller, :polymorphic => true which will create both keys for use. After, inside the listing model then we can say that the listing belongs to a seller instead of explicitly saying which seller(company....) this is expressed using the following code class Listing < ActiveRecord::Base belongs_to :seller, :polymorphic => true end Then we can add the relationship to each one of the entities using :as class Real_State_Company < ActiveRecord::Base has_many :listings, :as => :seller end Until here we have taken care of the relationship were a listing belongs to any 3 entities(projects, real_state_company and natural_person). Now we need to look at the case were the construction company, real state company or natural user belongs to a User. Since this is the reverse, we start looking what does the user has, he has_one of the 3 things(company, real state company or natural_person), we''ll call this entities, thus in rails we can say: class User < ActiveRecord::Base has_one :entity, :polymorphic => :true end And then each of the entities will have: class Real_State_Company < ActiveRecord::Base belongs_to :user, :as => :entity end We need to modify the user model with entity_id and entity_type, or: t.references :entity, :polymorphic => true Unfortunatelly has_one polymorphic is not supported, therefore we need to think in reverse. class User < ActiveRecord::Base belongs_to :ownable, :polymorphic => :true end And then each of the entities will have: class Real_State_Company < ActiveRecord::Base has_one :user, :as => :ownable end We need to modify the user model with entity_id and entity_type, or: t.references :entity, :polymorphic => true Then to get if the user owns a company or natural person do @user.ownable, similary to see which user owns a company @company.user. On Nov 1, 1:15 pm, Tim Shaffer <timshaf...-BUHhN+a2lJ4@public.gmane.org> wrote:> Yup, then like Marnen said, Person should belong to Item: > > belongs_to :item, :polymorphic => true > > In your migration, you can use: > > t.references :item, :polymorphic => true > > Which will create item_type and item_id columns. > > Then each class A, B, and C can have one person: > > has_one :person, :as => :item-- 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@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?hl=en.
On Nov 1, 2:18 pm, dpal <dan...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Unfortunatelly has_one polymorphic is not supported, therefore we need > to think in reverse.That''s because if the "belongs_to" is on the company models, it''s no longer a polymorphic relationship. At that point it''s just a regular one-to-one relationship, like the following example. Each of the companies has a foreign key to Person. class RealStateCompany belongs_to :user end class ConstructionCompany belongs_to :user end class NaturalPerson belongs_to :user end class User has_one :real_state_company has_one :construction_company has_one :natural_person end This works. Reversing the relationship also works. Just depends on how you want to design it and where you want the foreign keys. -- 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@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?hl=en.
Now there is also the fact that user has to know what they own. If I go with the belongs_to :ownable, polymorphic => true. From user then user.ownable will either return company, real_state_company or natural user. I would have to do user.ownable_type to see which one and use a string comparisson. If I go the other route: has_one :real_state_company has_one :construction_company has_one :natural_person I can say, if(user.construction_company != nil) { company = user.company redirect_to company } else if (user.real_state_company) { .... } etc. Which one is cleaner, better design ? Thanks -dan On Nov 1, 1:46 pm, Tim Shaffer <timshaf...-BUHhN+a2lJ4@public.gmane.org> wrote:> On Nov 1, 2:18 pm, dpal <dan...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > Unfortunatelly has_one polymorphic is not supported, therefore we need > > to think in reverse. > > That''s because if the "belongs_to" is on the company models, it''s no > longer a polymorphic relationship. At that point it''s just a regular > one-to-one relationship, like the following example. Each of the > companies has a foreign key to Person. > > class RealStateCompany > belongs_to :user > end > > class ConstructionCompany > belongs_to :user > end > > class NaturalPerson > belongs_to :user > end > > class User > has_one :real_state_company > has_one :construction_company > has_one :natural_person > end > > This works. Reversing the relationship also works. Just depends on how > you want to design it and where you want the foreign keys.-- 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@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?hl=en.
dpal wrote in post #958568:> Now there is also the fact that user has to know what they own. > If I go with the > > belongs_to :ownable, polymorphic => true. > > From user then user.ownable will either return company, > real_state_company or natural user.(I think you mean "real estate", not "real state".)> I would have to do user.ownable_type to see which one and use a string > comparisson.Or user.ownable.class and use a class comparison. Or better yet, do neither and use object polymorphism to automatically dispatch. Remember, one of the nice things about OO development is that objects know how to respond to messages -- you often don''t need conditionals.> > If I go the other route: > > has_one :real_state_company > has_one :construction_company > has_one :natural_person > > I can say, > > if(user.construction_company != nil) > { > company = user.company > redirect_to company > } > else if (user.real_state_company) > { > .... > }This isn''t Java. Lose the braces, parens, and "!= nil" and use "elsif" instead of "else if".> etc. > > Which one is cleaner, better design ?The polymorphic design. It allows you to actually harness the object model to your advantage.> > Thanks > -danBest, -- Marnen Laibow-Koser http://www.marnen.org marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org -- Posted via http://www.ruby-forum.com/. -- 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Awesome help, thanks everyone. Just finished implementing the polymorphic way, and the code looks really clean. Thanks -dan On Nov 1, 2:41 pm, Marnen Laibow-Koser <li...-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> dpal wrote in post #958568: > > > Now there is also the fact that user has to know what they own. > > If I go with the > > > belongs_to :ownable, polymorphic => true. > > > From user then user.ownable will either return company, > > real_state_company or natural user. > > (I think you mean "real estate", not "real state".) > > > I would have to do user.ownable_type to see which one and use a string > > comparisson. > > Or user.ownable.class and use a class comparison. > > Or better yet, do neither and use object polymorphism to automatically > dispatch. Remember, one of the nice things about OO development is that > objects know how to respond to messages -- you often don''t need > conditionals. > > > > > > > > > > > > > If I go the other route: > > > has_one :real_state_company > > has_one :construction_company > > has_one :natural_person > > > I can say, > > > if(user.construction_company != nil) > > { > > company = user.company > > redirect_to company > > } > > else if (user.real_state_company) > > { > > .... > > } > > This isn''t Java. Lose the braces, parens, and "!= nil" and use "elsif" > instead of "else if". > > > etc. > > > Which one is cleaner, better design ? > > The polymorphic design. It allows you to actually harness the object > model to your advantage. > > > > > Thanks > > -dan > > Best, > -- > Marnen Laibow-Koserhttp://www.marnen.org > mar...-sbuyVjPbboAdnm+yROfE0A@public.gmane.org > > -- > Posted viahttp://www.ruby-forum.com/.-- 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@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?hl=en.