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