I have three tables: groups, memberships, and users. When a user creates a group I need to make sure that a membership in that group is also created. I have considered using transactions but I keep seeing that these are being deprecated. Is there some other practice that is simpler or preferred? Groups: name description owner_id (user_id) [has_many :users, through :memberships] [has_many :memberships] Memberships: groups_id user_id confirmed_at [belongs_to :groups] [belongs_to :users] Users: user_id login: [has_many :groups, through membership] [has_many :memberships] -- David Andrew Thompson http://dathompson.blogspot.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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
rein.henrichs-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
2007-Sep-01 18:01 UTC
Re: Model transactions
Since Memberships is essentially a join table with an extra attribute, and I see that you already have your :through relationships defined, simply doing @group = Group.new( params[:group] ) @user.groups << @group will create the membership record (assuming that @user is the User object). Rein On Sep 1, 12:51 pm, "David Andrew Thompson" <dandrew.thomp...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> I have three tables: groups, memberships, and users. When a user creates a > group I need to make sure that a membership in that group is also created. I > have considered using transactions but I keep seeing that these are being > deprecated. Is there some other practice that is simpler or preferred? > > Groups: > name > description > owner_id (user_id) > [has_many :users, through :memberships] > [has_many :memberships] > > Memberships: > groups_id > user_id > confirmed_at > [belongs_to :groups] > [belongs_to :users] > > Users: > user_id > login: > [has_many :groups, through membership] > [has_many :memberships] > > -- > David Andrew Thompsonhttp://dathompson.blogspot.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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
rein.henrichs-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
2007-Sep-01 18:06 UTC
Re: Model transactions
I see on my second reading that you want to both set the owner_id of the group and create a membership. This is a bit more complicated (but not much!) You will need to specify the association between Group and User: class Group < AR::Base belongs_to :owner, :class_name => "User", :foreign_key => "owner_id" end class User < AR::Base has_many :owned_groups, :class_name => "Group", :foreign_key => "owner_id" end then your code to create a group belonging to this user could be: @group = Group.new( params[:group] ) @group.owner = @user @user.groups << @group You could also use scoping: @user.owned_groups.build( params[:group] ) @user.groups << @group The key is that @user.owned_groups as set up here are the groups where the group''s owner_id == @user.id and @user.groups are the groups that the @user is a member of via the memberships join table. On Sep 1, 1:01 pm, rein.henri...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org wrote:> Since Memberships is essentially a join table with an extra attribute, > and I see that you already have your :through relationships defined, > simply doing > > @group = Group.new( params[:group] ) > @user.groups << @group > > will create the membership record (assuming that @user is the User > object). > > Rein > > On Sep 1, 12:51 pm, "David Andrew Thompson" > > <dandrew.thomp...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > I have three tables: groups, memberships, and users. When a user creates a > > group I need to make sure that a membership in that group is also created. I > > have considered using transactions but I keep seeing that these are being > > deprecated. Is there some other practice that is simpler or preferred? > > > Groups: > > name > > description > > owner_id (user_id) > > [has_many :users, through :memberships] > > [has_many :memberships] > > > Memberships: > > groups_id > > user_id > > confirmed_at > > [belongs_to :groups] > > [belongs_to :users] > > > Users: > > user_id > > login: > > [has_many :groups, through membership] > > [has_many :memberships] > > > -- > > David Andrew Thompsonhttp://dathompson.blogspot.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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
As far as I can see, it is better to use has_and_belongs_to_many to define the relationship of user and group. On Sep 1, 1:51 pm, "David Andrew Thompson" <dandrew.thomp...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> I have three tables: groups, memberships, and users. When a user creates a > group I need to make sure that a membership in that group is also created. I > have considered using transactions but I keep seeing that these are being > deprecated. Is there some other practice that is simpler or preferred? > > Groups: > name > description > owner_id (user_id) > [has_many :users, through :memberships] > [has_many :memberships] > > Memberships: > groups_id > user_id > confirmed_at > [belongs_to :groups] > [belongs_to :users] > > Users: > user_id > login: > [has_many :groups, through membership] > [has_many :memberships] > > -- > David Andrew Thompsonhttp://dathompson.blogspot.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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
David Andrew Thompson wrote:> I have three tables: groups, memberships, and users. When a user > creates a group I need to make sure that a membership in that group is > also created. I have considered using transactions but I keep seeing > that these are being deprecated.IIRC transactions aren''t deprecated only the form where the rollback not only applies to the DB but to the ActiveRecord::Base objects too. The day ActiveRecord::Base completely removes transaction support is the day someone will fork it or provide the feature as a plugin :-) Lionel --~--~---------~--~----~------------~-------~--~----~ 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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
rein.henrichs-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
2007-Sep-02 21:37 UTC
Re: Model transactions
David, There are two relationships between user and group: One is a many to many relationship (the concept of membership), one is a one to many (the concept of ownership). The many to many is already expressed via a has_many :through with a Membership join model. This is roughly equivalent to a habtm but also allows attributes on the join (like the confirmed_at timestamp) because the join table is represented as a first order class via the Membership model. Habtm would not be sufficient for this relationship. The other is the "ownership" of the group, as expressed with the owner_id foreign key. This is a completely separate relationship and needs to be specified as a has_many/belongs_to. I hope this better explains the reasoning behind the relationships I outlined above. On Sep 2, 3:55 pm, Jack Zhan <jack.xiaobo.z...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> As far as I can see, it is better to use has_and_belongs_to_many to > define the relationship of user and group. > > On Sep 1, 1:51 pm, "David Andrew Thompson" > > <dandrew.thomp...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > I have three tables: groups, memberships, and users. When a user creates a > > group I need to make sure that a membership in that group is also created. I > > have considered using transactions but I keep seeing that these are being > > deprecated. Is there some other practice that is simpler or preferred? > > > Groups: > > name > > description > > owner_id (user_id) > > [has_many :users, through :memberships] > > [has_many :memberships] > > > Memberships: > > groups_id > > user_id > > confirmed_at > > [belongs_to :groups] > > [belongs_to :users] > > > Users: > > user_id > > login: > > [has_many :groups, through membership] > > [has_many :memberships] > > > -- > > David Andrew Thompsonhttp://dathompson.blogspot.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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
rein.henrichs-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
2007-Sep-02 21:40 UTC
Re: Model transactions
You are correct. My code above for creating and assigning a group can be wrapped in a transaction do [code here] end block to wrap it in a transaction to provide rollback if any of the operations fails. It is the Model.transaction form that is deprecated. See http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html On Sep 2, 4:01 pm, Lionel Bouton <lionel-subscript...-WTamNBQcZIx7tPAFqOLdPg@public.gmane.org> wrote:> David Andrew Thompson wrote: > > I have three tables: groups, memberships, and users. When a user > > creates a group I need to make sure that a membership in that group is > > also created. I have considered using transactions but I keep seeing > > that these are being deprecated. > > IIRC transactions aren''t deprecated only the form where the rollback not > only applies to the DB but to the ActiveRecord::Base objects too. > > The day ActiveRecord::Base completely removes transaction support is the > day someone will fork it or provide the feature as a plugin :-) > > Lionel--~--~---------~--~----~------------~-------~--~----~ 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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
I would encapsulate all of this on the user model. class Group < AR::Base belongs_to :owner, :class_name => "User", :foreign_key => "owner_id" end class User < ActiveRecord::Base has_many :groups, :through => :memberships has_many :memberships def create_group(options) g = Group.new(options.merge({ :owner => self })) groups << g if g.save g end end Your controller code becomes the even simpler: @group = @user.create_group params[:group] Now you''ve got a method which explains what you _really_ want to do, and handles it without the application code worrying about the details. Pat On 9/1/07, rein.henrichs-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org <rein.henrichs-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > I see on my second reading that you want to both set the owner_id of > the group and create a membership. This is a bit more complicated (but > not much!) > > You will need to specify the association between Group and User: > > class Group < AR::Base > > belongs_to :owner, :class_name => "User", :foreign_key => "owner_id" > > end > > class User < AR::Base > > has_many :owned_groups, :class_name => "Group", :foreign_key => > "owner_id" > > end > > then your code to create a group belonging to this user could be: > > @group = Group.new( params[:group] ) > @group.owner = @user > @user.groups << @group > > You could also use scoping: > > @user.owned_groups.build( params[:group] ) > @user.groups << @group > > The key is that @user.owned_groups as set up here are the groups where > the group''s owner_id == @user.id and @user.groups are the groups that > the @user is a member of via the memberships join table. > > On Sep 1, 1:01 pm, rein.henri...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org wrote: > > Since Memberships is essentially a join table with an extra attribute, > > and I see that you already have your :through relationships defined, > > simply doing > > > > @group = Group.new( params[:group] ) > > @user.groups << @group > > > > will create the membership record (assuming that @user is the User > > object). > > > > Rein > > > > On Sep 1, 12:51 pm, "David Andrew Thompson" > > > > <dandrew.thomp...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > I have three tables: groups, memberships, and users. When a user creates a > > > group I need to make sure that a membership in that group is also created. I > > > have considered using transactions but I keep seeing that these are being > > > deprecated. Is there some other practice that is simpler or preferred? > > > > > Groups: > > > name > > > description > > > owner_id (user_id) > > > [has_many :users, through :memberships] > > > [has_many :memberships] > > > > > Memberships: > > > groups_id > > > user_id > > > confirmed_at > > > [belongs_to :groups] > > > [belongs_to :users] > > > > > Users: > > > user_id > > > login: > > > [has_many :groups, through membership] > > > [has_many :memberships] > > > > > -- > > > David Andrew Thompsonhttp://dathompson.blogspot.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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
rein.henrichs-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
2007-Sep-02 23:17 UTC
Re: Model transactions
Pat, That''s an excellent intention-revealing abstraction and a great example of the smart model, dumb controller design paradigm. Rein On Sep 2, 4:57 pm, "Pat Maddox" <perg...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> I would encapsulate all of this on the user model. > > class Group < AR::Base > belongs_to :owner, :class_name => "User", :foreign_key => "owner_id" > end > > class User < ActiveRecord::Base > has_many :groups, :through => :memberships > has_many :memberships > > def create_group(options) > g = Group.new(options.merge({ :owner => self })) > groups << g if g.save > g > end > end > > Your controller code becomes the even simpler: > > @group = @user.create_group params[:group] > > Now you''ve got a method which explains what you _really_ want to do, > and handles it without the application code worrying about the > details. > > Pat > > On 9/1/07, rein.henri...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org <rein.henri...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > I see on my second reading that you want to both set the owner_id of > > the group and create a membership. This is a bit more complicated (but > > not much!) > > > You will need to specify the association between Group and User: > > > class Group < AR::Base > > > belongs_to :owner, :class_name => "User", :foreign_key => "owner_id" > > > end > > > class User < AR::Base > > > has_many :owned_groups, :class_name => "Group", :foreign_key => > > "owner_id" > > > end > > > then your code to create a group belonging to this user could be: > > > @group = Group.new( params[:group] ) > > @group.owner = @user > > @user.groups << @group > > > You could also use scoping: > > > @user.owned_groups.build( params[:group] ) > > @user.groups << @group > > > The key is that @user.owned_groups as set up here are the groups where > > the group''s owner_id == @user.id and @user.groups are the groups that > > the @user is a member of via the memberships join table. > > > On Sep 1, 1:01 pm, rein.henri...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org wrote: > > > Since Memberships is essentially a join table with an extra attribute, > > > and I see that you already have your :through relationships defined, > > > simply doing > > > > @group = Group.new( params[:group] ) > > > @user.groups << @group > > > > will create the membership record (assuming that @user is the User > > > object). > > > > Rein > > > > On Sep 1, 12:51 pm, "David Andrew Thompson" > > > > <dandrew.thomp...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > I have three tables: groups, memberships, and users. When a user creates a > > > > group I need to make sure that a membership in that group is also created. I > > > > have considered using transactions but I keep seeing that these are being > > > > deprecated. Is there some other practice that is simpler or preferred? > > > > > Groups: > > > > name > > > > description > > > > owner_id (user_id) > > > > [has_many :users, through :memberships] > > > > [has_many :memberships] > > > > > Memberships: > > > > groups_id > > > > user_id > > > > confirmed_at > > > > [belongs_to :groups] > > > > [belongs_to :users] > > > > > Users: > > > > user_id > > > > login: > > > > [has_many :groups, through membership] > > > > [has_many :memberships] > > > > > -- > > > > David Andrew Thompsonhttp://dathompson.blogspot.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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Fantastic thread! Thanks so much everyone. This was immensely helpful. -Dave -- David Andrew Thompson http://dathompson.blogspot.com On 9/2/07, rein.henrichs-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org <rein.henrichs-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > > Pat, > > That''s an excellent intention-revealing abstraction and a great > example of the smart model, dumb controller design paradigm. > > Rein > > On Sep 2, 4:57 pm, "Pat Maddox" <perg...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > I would encapsulate all of this on the user model. > > > > class Group < AR::Base > > belongs_to :owner, :class_name => "User", :foreign_key => "owner_id" > > end > > > > class User < ActiveRecord::Base > > has_many :groups, :through => :memberships > > has_many :memberships > > > > def create_group(options) > > g = Group.new(options.merge({ :owner => self })) > > groups << g if g.save > > g > > end > > end > > > > Your controller code becomes the even simpler: > > > > @group = @user.create_group params[:group] > > > > Now you''ve got a method which explains what you _really_ want to do, > > and handles it without the application code worrying about the > > details. > > > > Pat > > > > On 9/1/07, rein.henri...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org <rein.henri...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > > > > > I see on my second reading that you want to both set the owner_id of > > > the group and create a membership. This is a bit more complicated (but > > > not much!) > > > > > You will need to specify the association between Group and User: > > > > > class Group < AR::Base > > > > > belongs_to :owner, :class_name => "User", :foreign_key => "owner_id" > > > > > end > > > > > class User < AR::Base > > > > > has_many :owned_groups, :class_name => "Group", :foreign_key => > > > "owner_id" > > > > > end > > > > > then your code to create a group belonging to this user could be: > > > > > @group = Group.new( params[:group] ) > > > @group.owner = @user > > > @user.groups << @group > > > > > You could also use scoping: > > > > > @user.owned_groups.build( params[:group] ) > > > @user.groups << @group > > > > > The key is that @user.owned_groups as set up here are the groups where > > > the group''s owner_id == @user.id and @user.groups are the groups that > > > the @user is a member of via the memberships join table. > > > > > On Sep 1, 1:01 pm, rein.henri...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org wrote: > > > > Since Memberships is essentially a join table with an extra > attribute, > > > > and I see that you already have your :through relationships defined, > > > > simply doing > > > > > > @group = Group.new( params[:group] ) > > > > @user.groups << @group > > > > > > will create the membership record (assuming that @user is the User > > > > object). > > > > > > Rein > > > > > > On Sep 1, 12:51 pm, "David Andrew Thompson" > > > > > > <dandrew.thomp...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > I have three tables: groups, memberships, and users. When a user > creates a > > > > > group I need to make sure that a membership in that group is also > created. I > > > > > have considered using transactions but I keep seeing that these > are being > > > > > deprecated. Is there some other practice that is simpler or > preferred? > > > > > > > Groups: > > > > > name > > > > > description > > > > > owner_id (user_id) > > > > > [has_many :users, through :memberships] > > > > > [has_many :memberships] > > > > > > > Memberships: > > > > > groups_id > > > > > user_id > > > > > confirmed_at > > > > > [belongs_to :groups] > > > > > [belongs_to :users] > > > > > > > Users: > > > > > user_id > > > > > login: > > > > > [has_many :groups, through membership] > > > > > [has_many :memberships] > > > > > > > -- > > > > > David Andrew Thompsonhttp://dathompson.blogspot.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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---