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 -~----------~----~----~----~------~----~------~--~---