Pat Maddox
2005-Apr-11 21:15 UTC
Having two instances of same class, how to set up relationship?
I''m trying to write an Order class that will have two addresses in it - a billing address and a shipping address. The addresses are stored in a table called (drum roll) addresses. How do I set up a relationship so that I can reference the billing and shipping addresses from the Order? I''d like to do order.shipping_address = address order.biling_address = bill_address In the IRC, someone suggested making subclasses and using a type field. That seems like a poor way of doing it, since there is no functional difference between a billing address and shipping address. Furthermore, there''s no reason that an address needs to know whether it''s being used as a shipping or billing address. This is a really common setup, I''m sure, so there has to be a way to do it. Can anyone give me some examples or help? Thanks, Pat
Phillip Hutchings
2005-Apr-11 21:19 UTC
Re: Having two instances of same class, how to set up relationship?
On Apr 12, 2005 9:15 AM, Pat Maddox <pergesu-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> I''m trying to write an Order class that will have two addresses in it > - a billing address and a shipping address. The addresses are stored > in a table called (drum roll) addresses. How do I set up a > relationship so that I can reference the billing and shipping > addresses from the Order? I''d like to do > order.shipping_address = address > order.biling_address = bill_addressThis should do it, though I haven''t tested it. has_one :shipping_address, :class_name=>"Address", :foreign_key=>"shipping_address_id" has_one :billing_address, :class_name=>"Address", :foreign_key=>"billing_address_id" -- Phillip Hutchings http://www.sitharus.com/ sitharus-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org / sitharus-QrR4M9swfipWk0Htik3J/w@public.gmane.org
Rick Olson
2005-Apr-11 21:24 UTC
Re: Having two instances of same class, how to set up relationship?
The Rails associations have some properties that you can use to configure the relations. Of course it assumes certain values, but in cases such as yours, you should override them. class Order has_one :shipping_address, :class_name => ''Address'', :foreign_key => ''shipping_address_id'', :dependant => false has_one :billing_address, :class_name => ''Address'', :foreign_key => ''billing_address_id'', :dependant => false So, you should be able to use order.shipping_address and order.billing_address that map to an instance of the Address class, using the shipping_address_id and billing_address_id FKs in the orders table. The all knowing docs have more info: http://rails.rubyonrails.com/classes/ActiveRecord/Associations/ClassMethods.html#M000396 On 4/11/05, Pat Maddox <pergesu-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> I''m trying to write an Order class that will have two addresses in it > - a billing address and a shipping address. The addresses are stored > in a table called (drum roll) addresses. How do I set up a > relationship so that I can reference the billing and shipping > addresses from the Order? I''d like to do > order.shipping_address = address > order.biling_address = bill_address > > In the IRC, someone suggested making subclasses and using a type > field. That seems like a poor way of doing it, since there is no > functional difference between a billing address and shipping address. > Furthermore, there''s no reason that an address needs to know whether > it''s being used as a shipping or billing address. > > This is a really common setup, I''m sure, so there has to be a way to > do it. Can anyone give me some examples or help? > > Thanks, Pat > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- rick http://techno-weenie.net
Florian Groß
2005-Apr-11 21:57 UTC
Re: Having two instances of same class, how to set up relationship?
Pat Maddox wrote:> I''m trying to write an Order class that will have two addresses in it > - a billing address and a shipping address. The addresses are stored > in a table called (drum roll) addresses. How do I set up a > relationship so that I can reference the billing and shipping > addresses from the Order? I''d like to do > order.shipping_address = address > order.biling_address = bill_addressYour main question has been answered already by others, but I wonder why you chose to design it like this: Do you only have payment via invoice and no other options? I''ll be implementing something like this as well, but in my case there is potentially many different payment options of which I think not all need to have a separate billing address. (Think of cash on delivery and so on.) Thanks for your insights into this.
Pat Maddox
2005-Apr-11 22:15 UTC
Re: Having two instances of same class, how to set up relationship?
Alright, I''m working on another part of the app right now. Trying to let users have a shopping cart and a wishlist, which are basically the same (and just like the address example, are from the same class). When a user registers, the shopping cart and wish list should both be created. So my code looks like: @user.cart = Cart.new @user.wishlist = Cart.new if @user.save ... New records are created for them all in the db, but the cart_id and wishlist_id in the users table are both null. Same goes for the user_id for the cart records. Do I need to do anything specific to make sure that all the foreign keys get updated automatically? On Apr 11, 2005 3:19 PM, Phillip Hutchings <sitharus-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> On Apr 12, 2005 9:15 AM, Pat Maddox <pergesu-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > I''m trying to write an Order class that will have two addresses in it > > - a billing address and a shipping address. The addresses are stored > > in a table called (drum roll) addresses. How do I set up a > > relationship so that I can reference the billing and shipping > > addresses from the Order? I''d like to do > > order.shipping_address = address > > order.biling_address = bill_address > > This should do it, though I haven''t tested it. > > has_one :shipping_address, :class_name=>"Address", > :foreign_key=>"shipping_address_id" > has_one :billing_address, :class_name=>"Address", > :foreign_key=>"billing_address_id" > > -- > Phillip Hutchings > http://www.sitharus.com/ > sitharus-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org / sitharus-QrR4M9swfipWk0Htik3J/w@public.gmane.org >
Pat Maddox
2005-Apr-11 22:19 UTC
Re: Re: Having two instances of same class, how to set up relationship?
Often the mailing address will be the same as the billing address, in which case they''ll point to the same ID. When the user places an order, he''ll enter a shipping address, and then there will be a checkbox that says, "Click here to use the same address for the billing address." That''s a pretty standard setup. On Apr 11, 2005 3:57 PM, Florian Groß <florgro-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Pat Maddox wrote: > > > I''m trying to write an Order class that will have two addresses in it > > - a billing address and a shipping address. The addresses are stored > > in a table called (drum roll) addresses. How do I set up a > > relationship so that I can reference the billing and shipping > > addresses from the Order? I''d like to do > > order.shipping_address = address > > order.biling_address = bill_address > > Your main question has been answered already by others, but I wonder why > you chose to design it like this: Do you only have payment via invoice > and no other options? > > I''ll be implementing something like this as well, but in my case there > is potentially many different payment options of which I think not all > need to have a separate billing address. (Think of cash on delivery and > so on.) > > Thanks for your insights into this. > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
Jarkko Laine
2005-Apr-12 08:03 UTC
Re: Having two instances of same class, how to set up relationship?
Rick and Philip, Why do you suggest using has_one instead of belongs_to? Using has_one means that the shipping_address_id and billing_address_id fields are in the addresses table, which I think is definitely wrong. An address shouldn''t know if it''s a billing address or a shipment address, it''s just an address. Besides, it can probably be both of them at the same time. So my take on this would be: class Order belongs_to :shipping_address, :class_name => ''Address'', :foreign_key => ''shipping_address_id'', :dependant => false belongs_to :billing_address, :class_name => ''Address'', :foreign_key => ''billing_address_id'', :dependant => false On 12.4.2005, at 00:24, Rick Olson wrote:> > So, you should be able to use order.shipping_address and > order.billing_address that map to an instance of the Address class, > using the shipping_address_id and billing_address_id FKs in the orders > table.Ah, OK, you probably just mixed up the two association methods. //jarkko -- Jarkko Laine http://jlaine.net http://odesign.fi _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
Florian Groß
2005-Apr-12 12:04 UTC
Re: Having two instances of same class, how to set up relationship?
Pat Maddox wrote:> Often the mailing address will be the same as the billing address, in > which case they''ll point to the same ID. When the user places an > order, he''ll enter a shipping address, and then there will be a > checkbox that says, "Click here to use the same address for the > billing address." That''s a pretty standard setup.Right, but what if the user selected paying via cash on delivery earlier? In that case you don''t really need to ask for a separate payment address. I''m not sure how that would be done with this database setup.
Pat Maddox
2005-Apr-12 16:13 UTC
Re: Re: Having two instances of same class, how to set up relationship?
That''s not a requirement in this application. In any rate, if that were an option, then we just wouldn''t require them to enter/select info for both a shipping and billing address. Just because two are referenced in the db (to easily support all forms of payment) doesn''t mean the user has to enter them both. On Apr 12, 2005 6:04 AM, Florian Groß <florgro-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Pat Maddox wrote: > > > Often the mailing address will be the same as the billing address, in > > which case they''ll point to the same ID. When the user places an > > order, he''ll enter a shipping address, and then there will be a > > checkbox that says, "Click here to use the same address for the > > billing address." That''s a pretty standard setup. > > Right, but what if the user selected paying via cash on delivery > earlier? In that case you don''t really need to ask for a separate > payment address. I''m not sure how that would be done with this database > setup. > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
Pat Maddox
2005-Apr-12 16:17 UTC
Re: Having two instances of same class, how to set up relationship?
I don''t really understand this. An order doesn''t belong to an address...in fact, an address doesn''t even belong to an order. An order just references two different addresses - it has them. So why would I say that an order belongs to an address? On Apr 12, 2005 2:03 AM, Jarkko Laine <jarkko-k1O+Gnc6WpmsTnJN9+BGXg@public.gmane.org> wrote:> Rick and Philip, > > Why do you suggest using has_one instead of belongs_to? Using has_one > means that the shipping_address_id and billing_address_id fields are in > the addresses table, which I think is definitely wrong. An address > shouldn''t know if it''s a billing address or a shipment address, it''s > just an address. Besides, it can probably be both of them at the same > time. > > So my take on this would be: > class Order > belongs_to :shipping_address, :class_name => ''Address'', :foreign_key > => > ''shipping_address_id'', :dependant => false > belongs_to :billing_address, :class_name => ''Address'', :foreign_key => > ''billing_address_id'', :dependant => false > > On 12.4.2005, at 00:24, Rick Olson wrote: > > > > So, you should be able to use order.shipping_address and > > order.billing_address that map to an instance of the Address class, > > using the shipping_address_id and billing_address_id FKs in the orders > > table. > > Ah, OK, you probably just mixed up the two association methods. > > //jarkko > > -- > Jarkko Laine > http://jlaine.net > http://odesign.fi > > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails > > > >
Jarkko Laine
2005-Apr-12 16:51 UTC
Re: Having two instances of same class, how to set up relationship?
Pat, belongs_to is just a way to tell ActiveRecord that there is a one-to-many (or one-to-one like here) relationship between two classes. If order belongs_to :address, it means that orders table has a foreign_key field (e.g. "address_id") that references id field in addresses table. has_one, on the other hand, means that the foreign key field is on the other side of the relationship. So "order has_one :address" would mean that there is a field "order_id" in the addresses table. This would be fine if you only had a single one-to-one relationship between those two classes. But you don''t have one but two relationships between orders and addresses. Therefore you''d have to have two fields in addresses table, "id_of_order_where_im_shipping_address" and "id_of_order_where_im_billing_address". This is not only awkward, but also adds redundant because many of the addresses only have use for one of these fields. If you would accept that belongs_to is only lingo you could do with this, imho much cleaner schema: orders: id billing_address_id references addresses(id) shipment_address_id references addresses(id) addresses: id The good thing about this schema is that now the two foreign key fields can reference one or two different addresses and there is never any extraneous empty fields. So if you agree with me that this kind of db schema suits you best, then you *need* to use belongs_to to model it in ActiveRecord, whether or not you like the name. I know the names of the relationships might sound backwards in some contexts but you will get used to them very fast (I promise :) Again, here''s a link to Amy Hoy''s excellent cheat sheet that explains which relationship method you should use to model different db relationships in ActiveRecord: http://www.slash7.com/cheats/activerecord_cheatsheet.pdf (I know Scott Barron also had a similar sheet but I never remember its URI...) //jarkko On 12.4.2005, at 19:17, Pat Maddox wrote:> I don''t really understand this. An order doesn''t belong to an > address...in fact, an address doesn''t even belong to an order. An > order just references two different addresses - it has them. So why > would I say that an order belongs to an address? > > > > On Apr 12, 2005 2:03 AM, Jarkko Laine <jarkko-k1O+Gnc6WpmsTnJN9+BGXg@public.gmane.org> wrote: >> Rick and Philip, >> >> Why do you suggest using has_one instead of belongs_to? Using has_one >> means that the shipping_address_id and billing_address_id fields are >> in >> the addresses table, which I think is definitely wrong. An address >> shouldn''t know if it''s a billing address or a shipment address, it''s >> just an address. Besides, it can probably be both of them at the same >> time. >> >> So my take on this would be: >> class Order >> belongs_to :shipping_address, :class_name => ''Address'', >> :foreign_key >> => >> ''shipping_address_id'', :dependant => false >> belongs_to :billing_address, :class_name => ''Address'', >> :foreign_key => >> ''billing_address_id'', :dependant => false >> >> On 12.4.2005, at 00:24, Rick Olson wrote: >>> >>> So, you should be able to use order.shipping_address and >>> order.billing_address that map to an instance of the Address class, >>> using the shipping_address_id and billing_address_id FKs in the >>> orders >>> table. >> >> Ah, OK, you probably just mixed up the two association methods. >> >> //jarkko >> >> -- >> Jarkko Laine >> http://jlaine.net >> http://odesign.fi >> >> >> _______________________________________________ >> Rails mailing list >> Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org >> http://lists.rubyonrails.org/mailman/listinfo/rails >> >> >> >> > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- Jarkko Laine http://jlaine.net http://odesign.fi _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
Pat Maddox
2005-Apr-12 17:36 UTC
Re: Having two instances of same class, how to set up relationship?
Thanks for the explanation. That''s exactly the db schema I have set up, actually. The naming is a tad confusing, but it would explain a lot of the problems I''ve been having, I think. I''ll look over the cheat sheet more in-depth. Thanks for all the help. On Apr 12, 2005 10:51 AM, Jarkko Laine <jarkko-k1O+Gnc6WpmsTnJN9+BGXg@public.gmane.org> wrote:> Pat, > > belongs_to is just a way to tell ActiveRecord that there is a > one-to-many (or one-to-one like here) relationship between two classes. > > If order belongs_to :address, it means that orders table has a > foreign_key field (e.g. "address_id") that references id field in > addresses table. > > has_one, on the other hand, means that the foreign key field is on the > other side of the relationship. So "order has_one :address" would mean > that there is a field "order_id" in the addresses table. This would be > fine if you only had a single one-to-one relationship between those two > classes. > > But you don''t have one but two relationships between orders and > addresses. Therefore you''d have to have two fields in addresses table, > "id_of_order_where_im_shipping_address" and > "id_of_order_where_im_billing_address". This is not only awkward, but > also adds redundant because many of the addresses only have use for one > of these fields. > > If you would accept that belongs_to is only lingo you could do with > this, imho much cleaner schema: > > orders: > id > billing_address_id references addresses(id) > shipment_address_id references addresses(id) > > addresses: > id > > The good thing about this schema is that now the two foreign key fields > can reference one or two different addresses and there is never any > extraneous empty fields. > > So if you agree with me that this kind of db schema suits you best, > then you *need* to use belongs_to to model it in ActiveRecord, whether > or not you like the name. > > I know the names of the relationships might sound backwards in some > contexts but you will get used to them very fast (I promise :) > > Again, here''s a link to Amy Hoy''s excellent cheat sheet that explains > which relationship method you should use to model different db > relationships in ActiveRecord: > http://www.slash7.com/cheats/activerecord_cheatsheet.pdf > > (I know Scott Barron also had a similar sheet but I never remember its > URI...) > > //jarkko > > > On 12.4.2005, at 19:17, Pat Maddox wrote: > > > I don''t really understand this. An order doesn''t belong to an > > address...in fact, an address doesn''t even belong to an order. An > > order just references two different addresses - it has them. So why > > would I say that an order belongs to an address? > > > > > > > > On Apr 12, 2005 2:03 AM, Jarkko Laine <jarkko-k1O+Gnc6WpmsTnJN9+BGXg@public.gmane.org> wrote: > >> Rick and Philip, > >> > >> Why do you suggest using has_one instead of belongs_to? Using has_one > >> means that the shipping_address_id and billing_address_id fields are > >> in > >> the addresses table, which I think is definitely wrong. An address > >> shouldn''t know if it''s a billing address or a shipment address, it''s > >> just an address. Besides, it can probably be both of them at the same > >> time. > >> > >> So my take on this would be: > >> class Order > >> belongs_to :shipping_address, :class_name => ''Address'', > >> :foreign_key > >> => > >> ''shipping_address_id'', :dependant => false > >> belongs_to :billing_address, :class_name => ''Address'', > >> :foreign_key => > >> ''billing_address_id'', :dependant => false > >> > >> On 12.4.2005, at 00:24, Rick Olson wrote: > >>> > >>> So, you should be able to use order.shipping_address and > >>> order.billing_address that map to an instance of the Address class, > >>> using the shipping_address_id and billing_address_id FKs in the > >>> orders > >>> table. > >> > >> Ah, OK, you probably just mixed up the two association methods. > >> > >> //jarkko > >> > >> -- > >> Jarkko Laine > >> http://jlaine.net > >> http://odesign.fi > >> > >> > >> _______________________________________________ > >> Rails mailing list > >> Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > >> http://lists.rubyonrails.org/mailman/listinfo/rails > >> > >> > >> > >> > > _______________________________________________ > > Rails mailing list > > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > > http://lists.rubyonrails.org/mailman/listinfo/rails > > > -- > Jarkko Laine > http://jlaine.net > http://odesign.fi > > >