I''ve got a user class that has two objects, cart and wishlist, that are both of type Cart. When a user gets created, I want to create new records for the cart and wishlist automatically. I specified a method to be called after_create in the User class, which creates the cart objects. When I creata a new user though, the wishlist_id and cart_id in the users table are both null. The user_id in the carts table has the correct value though. Can anyone give me some pointers? Here''s the important part of the class defs: class User < ActiveRecord::Base has_one :cart has_one :wishlist, :class_name => ''Cart'', :foreign_key => ''id'' after_create :build_carts def build_carts new_cart = Cart.new new_cart.user = self new_wishlist = Cart.new new_wishlist.user = self new_cart.save new_wishlist.save self.cart = new_cart self.wishlist = new_wishlist self.save end end class Cart < ActiveRecord::Base belongs_to :user end
Hi Pat, You might want to take a peek at Amy Hoy''s AR Relationships Cheat Sheet [1]. On 12.4.2005, at 07:08, Pat Maddox wrote:> I''ve got a user class that has two objects, cart and wishlist, that > are both of type Cart. When a user gets created, I want to create new > records for the cart and wishlist automatically. I specified a method > to be called after_create in the User class, which creates the cart > objects. When I creata a new user though, the wishlist_id and cart_id > in the users table are both null.There is no use for those fields in a relationship you described. If user has_one :cart, the foreign key field (user_id) is in the carts table. There is never a foreign key field on both sides of the relationship. Never. Because of your situation (two relationships to the same table) I would suggest moving the foreign key fields to the users table. Or, actually, you have them already there so just take the foreign key fields away from the carts table. Then change the model accordingly:> class User < ActiveRecord::Base > has_one :cart=> belongs_to :cart> has_one :wishlist, :class_name => ''Cart'', :foreign_key => ''id''=> belongs_to :wishlist, :class_name => ''Cart'', :foreign_key => ''wishlist_id''> > after_create :build_carts > > def build_cartsself.cart.create self.wishlist.create> self.save > end > end > > class Cart < ActiveRecord::Base > belongs_to :user=> has_one :user # you only need one here end Note that you don''t need to specify relationships from both ways. They are just abstractions for building a foreign key relationship in the db. @user.cart would work even if you would have specified the foreign key in mysql shell. //jarkko [1] http://www.slash7.com/cheats/activerecord_cheatsheet.pdf -- Jarkko Laine http://jlaine.net http://odesign.fi _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
After working on this a little bit more, I realize that there''s nothing involved in the carts at all. They just hold a list of items that the user has in the cart at any given time. If I only had one cart per user, this would be pretty simple - I''d just have a table with items in the cart, and a user_id. But since I have two carts, I can''t quite do it like that. I could make two tables, but since the items are exactly the same, differing only in the cart_id (or type, since there wouldn''t actually be a cart), there''s just no point. How can I set up this relationship? On Apr 12, 2005 1:51 AM, Jarkko Laine <jarkko-k1O+Gnc6WpmsTnJN9+BGXg@public.gmane.org> wrote:> Hi Pat, > > You might want to take a peek at Amy Hoy''s AR Relationships Cheat Sheet > [1]. > > On 12.4.2005, at 07:08, Pat Maddox wrote: > > > I''ve got a user class that has two objects, cart and wishlist, that > > are both of type Cart. When a user gets created, I want to create new > > records for the cart and wishlist automatically. I specified a method > > to be called after_create in the User class, which creates the cart > > objects. When I creata a new user though, the wishlist_id and cart_id > > in the users table are both null. > > There is no use for those fields in a relationship you described. If > user has_one :cart, the foreign key field (user_id) is in the carts > table. There is never a foreign key field on both sides of the > relationship. Never. > > Because of your situation (two relationships to the same table) I would > suggest moving the foreign key fields to the users table. Or, actually, > you have them already there so just take the foreign key fields away > from the carts table. > > Then change the model accordingly: > > > class User < ActiveRecord::Base > > has_one :cart > => belongs_to :cart > > has_one :wishlist, :class_name => ''Cart'', :foreign_key => ''id'' > => belongs_to :wishlist, :class_name => ''Cart'', :foreign_key => > ''wishlist_id'' > > > > after_create :build_carts > > > > def build_carts > > self.cart.create > self.wishlist.create > > > self.save > > end > > end > > > > class Cart < ActiveRecord::Base > > belongs_to :user > => has_one :user # you only need one here > end > > Note that you don''t need to specify relationships from both ways. They > are just abstractions for building a foreign key relationship in the > db. @user.cart would work even if you would have specified the foreign > key in mysql shell. > > //jarkko > > [1] http://www.slash7.com/cheats/activerecord_cheatsheet.pdf > -- > Jarkko Laine > http://jlaine.net > http://odesign.fi > > >
On 12.4.2005, at 23:24, Pat Maddox wrote:> After working on this a little bit more, I realize that there''s > nothing involved in the carts at all. They just hold a list of items > that the user has in the cart at any given time. If I only had one > cart per user, this would be pretty simple - I''d just have a table > with items in the cart, and a user_id. But since I have two carts, I > can''t quite do it like that. I could make two tables, but since the > items are exactly the same, differing only in the cart_id (or type, > since there wouldn''t actually be a cart), there''s just no point. How > can I set up this relationship?Can''t you just make a many-to-many relationship between carts and items: carts_items: cart_id references carts(id) item_id references items(id) carts: id user_id class Cart < ... belongs_to :user has_and_belongs_to_many :items end class Wishlist < ... # uses same table as Cart so define tablename belongs_to :user has_and_belongs_to_many :items, :join_table => "carts_items", :foreign_key => "cart_id" end class Item < ... has_and_belongs_to_many :carts # you don''t necessarily need this unless you need to get # to carts/lists from the item standpoint end Since cart id uniquely identifies all carts and wishlists, there shouldn''t be any reason this wouldn''t work. Methinks, of course ;-) Actually this sounds like a case for inheriting the wishlist class from the cart. I don''t go any deeper into that, tho, since I haven''t really used that kind of things in Rails yet. //jarkko> > > On Apr 12, 2005 1:51 AM, Jarkko Laine <jarkko-k1O+Gnc6WpmsTnJN9+BGXg@public.gmane.org> wrote: >> Hi Pat, >> >> You might want to take a peek at Amy Hoy''s AR Relationships Cheat >> Sheet >> [1]. >> >> On 12.4.2005, at 07:08, Pat Maddox wrote: >> >>> I''ve got a user class that has two objects, cart and wishlist, that >>> are both of type Cart. When a user gets created, I want to create >>> new >>> records for the cart and wishlist automatically. I specified a >>> method >>> to be called after_create in the User class, which creates the cart >>> objects. When I creata a new user though, the wishlist_id and >>> cart_id >>> in the users table are both null. >> >> There is no use for those fields in a relationship you described. If >> user has_one :cart, the foreign key field (user_id) is in the carts >> table. There is never a foreign key field on both sides of the >> relationship. Never. >> >> Because of your situation (two relationships to the same table) I >> would >> suggest moving the foreign key fields to the users table. Or, >> actually, >> you have them already there so just take the foreign key fields away >> from the carts table. >> >> Then change the model accordingly: >> >>> class User < ActiveRecord::Base >>> has_one :cart >> => belongs_to :cart >>> has_one :wishlist, :class_name => ''Cart'', :foreign_key => ''id'' >> => belongs_to :wishlist, :class_name => ''Cart'', :foreign_key => >> ''wishlist_id'' >>> >>> after_create :build_carts >>> >>> def build_carts >> >> self.cart.create >> self.wishlist.create >> >>> self.save >>> end >>> end >>> >>> class Cart < ActiveRecord::Base >>> belongs_to :user >> => has_one :user # you only need one here >> end >> >> Note that you don''t need to specify relationships from both ways. They >> are just abstractions for building a foreign key relationship in the >> db. @user.cart would work even if you would have specified the foreign >> key in mysql shell. >> >> //jarkko >> >> [1] http://www.slash7.com/cheats/activerecord_cheatsheet.pdf >> -- >> 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 http://jlaine.net http://odesign.fi _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
I set up the relations like you suggested, and modified the User model class to create the carts. When I used your exact code, however, it said that cart and wishlist were both nil classes. So I made this change: def build_carts self.cart = Cart.new self.wishlist = Cart.new self.cart.create self.wishlist.create self.save end Now no error occurs, but the cart_id and wishlist_id in the users table are still blank. I thought that by setting up that relation, those foreign keys would automatically be assigned. On Apr 12, 2005 1:51 AM, Jarkko Laine <jarkko-k1O+Gnc6WpmsTnJN9+BGXg@public.gmane.org> wrote:> Hi Pat, > > You might want to take a peek at Amy Hoy''s AR Relationships Cheat Sheet > [1]. > > On 12.4.2005, at 07:08, Pat Maddox wrote: > > > I''ve got a user class that has two objects, cart and wishlist, that > > are both of type Cart. When a user gets created, I want to create new > > records for the cart and wishlist automatically. I specified a method > > to be called after_create in the User class, which creates the cart > > objects. When I creata a new user though, the wishlist_id and cart_id > > in the users table are both null. > > There is no use for those fields in a relationship you described. If > user has_one :cart, the foreign key field (user_id) is in the carts > table. There is never a foreign key field on both sides of the > relationship. Never. > > Because of your situation (two relationships to the same table) I would > suggest moving the foreign key fields to the users table. Or, actually, > you have them already there so just take the foreign key fields away > from the carts table. > > Then change the model accordingly: > > > class User < ActiveRecord::Base > > has_one :cart > => belongs_to :cart > > has_one :wishlist, :class_name => ''Cart'', :foreign_key => ''id'' > => belongs_to :wishlist, :class_name => ''Cart'', :foreign_key => > ''wishlist_id'' > > > > after_create :build_carts > > > > def build_carts > > self.cart.create > self.wishlist.create > > > self.save > > end > > end > > > > class Cart < ActiveRecord::Base > > belongs_to :user > => has_one :user # you only need one here > end > > Note that you don''t need to specify relationships from both ways. They > are just abstractions for building a foreign key relationship in the > db. @user.cart would work even if you would have specified the foreign > key in mysql shell. > > //jarkko > > [1] http://www.slash7.com/cheats/activerecord_cheatsheet.pdf > -- > Jarkko Laine > http://jlaine.net > http://odesign.fi > > >
On 13.4.2005, at 00:01, Pat Maddox wrote:> I set up the relations like you suggested, and modified the User model > class to create the carts. When I used your exact code, however, it > said that cart and wishlist were both nil classes. So I made this > change:That''s weird, because if you look at the api docs (http://rails.rubyonrails.com/classes/ActiveRecord/Associations/ ClassMethods.html#M000397), it clearly says that: <snip> association.create(attributes = {}) - returns a new object of the associated type that has been instantiated with attributes and linked to this object through a foreign key and that has already been saved (if it passed the validation). ... Post#author.create (similar to b = Author.new("post_id" => id); b.save; b) </snip> Hmmm... this sounds actually like a bug in the docs. There''s no way this could work because there is no post_id in authors table, like the line above suggests. The foreign key is in the posts table. Could someone please confirm if there''s only a typo in the docs or if this kind of shorthand object creation is possible at all from the belongs_to side of the relation. //jarkko> > def build_carts > self.cart = Cart.new > self.wishlist = Cart.new > self.cart.create > self.wishlist.create > self.save > end > > Now no error occurs, but the cart_id and wishlist_id in the users > table are still blank. I thought that by setting up that relation, > those foreign keys would automatically be assigned. > > > > On Apr 12, 2005 1:51 AM, Jarkko Laine <jarkko-k1O+Gnc6WpmsTnJN9+BGXg@public.gmane.org> wrote: >> Hi Pat, >> >> You might want to take a peek at Amy Hoy''s AR Relationships Cheat >> Sheet >> [1]. >> >> On 12.4.2005, at 07:08, Pat Maddox wrote: >> >>> I''ve got a user class that has two objects, cart and wishlist, that >>> are both of type Cart. When a user gets created, I want to create >>> new >>> records for the cart and wishlist automatically. I specified a >>> method >>> to be called after_create in the User class, which creates the cart >>> objects. When I creata a new user though, the wishlist_id and >>> cart_id >>> in the users table are both null. >> >> There is no use for those fields in a relationship you described. If >> user has_one :cart, the foreign key field (user_id) is in the carts >> table. There is never a foreign key field on both sides of the >> relationship. Never. >> >> Because of your situation (two relationships to the same table) I >> would >> suggest moving the foreign key fields to the users table. Or, >> actually, >> you have them already there so just take the foreign key fields away >> from the carts table. >> >> Then change the model accordingly: >> >>> class User < ActiveRecord::Base >>> has_one :cart >> => belongs_to :cart >>> has_one :wishlist, :class_name => ''Cart'', :foreign_key => ''id'' >> => belongs_to :wishlist, :class_name => ''Cart'', :foreign_key => >> ''wishlist_id'' >>> >>> after_create :build_carts >>> >>> def build_carts >> >> self.cart.create >> self.wishlist.create >> >>> self.save >>> end >>> end >>> >>> class Cart < ActiveRecord::Base >>> belongs_to :user >> => has_one :user # you only need one here >> end >> >> Note that you don''t need to specify relationships from both ways. They >> are just abstractions for building a foreign key relationship in the >> db. @user.cart would work even if you would have specified the foreign >> key in mysql shell. >> >> //jarkko >> >> [1] http://www.slash7.com/cheats/activerecord_cheatsheet.pdf >> -- >> 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 http://jlaine.net http://odesign.fi _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails