I have a photographers app that requires giving access to galleries for users. in one part, I want to be able to define gallery access for a user seperate from updating any of the user info. I have this function: def edit_access @user = User.find(params[:id]) @user.galleries = Gallery.find(params[:gallery_ids]) if params[:gallery_ids] if @user.update_attributes(params[:user]) flash[:notice] = ''Account was successfully updated.'' redirect_to :action => ''list'' else @galleries = Gallery.find(:all) render :action => ''manage_access'' end end The function works and updates the correct fields in the galleries_users table, but the page errors out on validation errors on @user. I''m hoping to make a function that only reaches to update @user.galleries and nothing in the user table. How do I do it? I''ve tried update_attributes(params[:user][:galleries]) and a few similar things, but really I''m just hacking and would like to know the proper way. Thanks, Jason -- Posted via http://www.ruby-forum.com/.
Josh Susser
2006-Jun-08 06:58 UTC
[Rails] Re: update only the join table in a HABTM - how?
Jason Pfeifer wrote:> The function works and updates the correct fields in the galleries_users > table, but the page errors out on validation errors on @user. I''m > hoping to make a function that only reaches to update @user.galleries > and nothing in the user table. > > How do I do it? I''ve tried update_attributes(params[:user][:galleries]) > and a few similar things, but really I''m just hacking and would like to > know the proper way.It''s hard to updated attributes in a join table. Try using has_many :through instead. http://blog.hasmanythrough.com/articles/2006/04/20/many-to-many-dance-off -- Josh Susser http://blog.hasmanythrough.com -- Posted via http://www.ruby-forum.com/.
Hi Jason, your user model will have a method called gallery_ids= that has been created by the has_and_belongs_to_many macro. So you could say @user.gallery_ids = [1,2,3,4,5] For models where new_record? is false (i.e. existing records) the change to the database is immediate and doesn''t require you to call save(). Seeing as you''re working on something related to security, and because you are using mass-assignment from params (i.e. update_attributes(params[:blah]) or new(params[:blah]) or attributes = params[:blah]) I think you should probably take a look at a two- part article on my blog: http://tinyurl.com/prxdl It applies to you if you have an action anywhere that allows a user to alter their associated User object''s attributes (like their name or address etc) *and* you use mass-assignment from params to do that (i.e. update_attributes(:user)). If that''s the case then you *MUST* do: attr_protected :gallery_ids in your User model. This doesn''t stop you from saying @user.gallery_ids = [1,2,3,4,5] or @user.gallery_ids = params[:gallery_ids] in your edit_access() action (which I assume is only available to privileged users) but it *will* ensure any spurious :gallery_ids param will be discarded if passed in to a new(), attributes= or update_attributes() call in some other unrelated action. HTH, Trevor -- Trevor Squires http://somethinglearned.com On 7-Jun-06, at 10:50 PM, Jason Pfeifer wrote:> I have a photographers app that requires giving access to galleries > for > users. in one part, I want to be able to define gallery access for a > user seperate from updating any of the user info. I have this > function: > > def edit_access > @user = User.find(params[:id]) > @user.galleries = Gallery.find(params[:gallery_ids]) if > params[:gallery_ids] > if @user.update_attributes(params[:user]) > flash[:notice] = ''Account was successfully updated.'' > redirect_to :action => ''list'' > else > @galleries = Gallery.find(:all) > render :action => ''manage_access'' > end > end > > The function works and updates the correct fields in the > galleries_users > table, but the page errors out on validation errors on @user. I''m > hoping to make a function that only reaches to update @user.galleries > and nothing in the user table. > > How do I do it? I''ve tried update_attributes(params[:user] > [:galleries]) > and a few similar things, but really I''m just hacking and would > like to > know the proper way. > > Thanks, > > Jason > > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails
Jason Pfeifer
2006-Jun-08 17:57 UTC
[Rails] Re: update only the join table in a HABTM - how?
> def edit_access > @user = User.find(params[:id]) > @user.galleries = Gallery.find(params[:gallery_ids]) if > params[:gallery_ids] > if @user.update_attributes(params[:user]) > flash[:notice] = ''Account was successfully updated.'' > redirect_to :action => ''list'' > else > @galleries = Gallery.find(:all) > render :action => ''manage_access'' > end > endIs there not a way in the code above, where I can just say something like: if @user.galleries.update_attributes or if @user.update_attributes(params[:gallery_ids]) or something that just bypasses trying to update the User model? It really only needs to update the join table ''galleries_users'' and nothing else. The initial code actually works for assigning access which is great - I watch it update the tables, but the page gives validation errors for the (non-existent in the view) password field being blank. Even if I could just bypass that validation error everything would work fine.> Jason-- Posted via http://www.ruby-forum.com/.
Trevor Squires
2006-Jun-08 19:18 UTC
[Rails] Re: update only the join table in a HABTM - how?
On 8-Jun-06, at 10:56 AM, Jason Pfeifer wrote:>> def edit_access >> @user = User.find(params[:id]) >> @user.galleries = Gallery.find(params[:gallery_ids]) if >> params[:gallery_ids] >> if @user.update_attributes(params[:user]) >> flash[:notice] = ''Account was successfully updated.'' >> redirect_to :action => ''list'' >> else >> @galleries = Gallery.find(:all) >> render :action => ''manage_access'' >> end >> end > > Is there not a way in the code above, where I can just say something > like: > > if @user.galleries.update_attributes > or if @user.update_attributes(params[:gallery_ids]) >Jason, take another look at my previous email on this subject. @user.gallery_ids = params[:gallery_ids] For existing records, there is no update_attributes() or save() required, it does it immediately. Try it out in the console if you''re skeptical. If you really want to use an update_attributes style call then: @user.update_attribute(:gallery_ids, params[:gallery_ids]) will work because update_attribute (*not* plural) will do the database update without first running validations. But to be honest, the heavy lifting here is being done by the underlying call to gallery_ids= that''s issued by update_attribute(). And also in reference to my previous mail, if you haven''t added the following line to your User model: attr_protected :gallery_ids then you had better *really* know why not. See http://tinyurl.com/ prxdl for more information. HTH, Trevor -- Trevor Squires http://somethinglearned.com> or something that just bypasses trying to update the User model? It > really only needs to update the join table ''galleries_users'' and > nothing > else. > > The initial code actually works for assigning access which is great > - I > watch it update the tables, but the page gives validation errors > for the > (non-existent in the view) password field being blank. Even if I > could > just bypass that validation error everything would work fine. > > >> Jason > > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails
Jason Pfeifer
2006-Jun-08 19:41 UTC
[Rails] Re: Re: update only the join table in a HABTM - how?
> For existing records, there is no update_attributes() or save() > required, it does it immediately. Try it out in the console if > you''re skeptical.Awesome thanks! I guess I didn''t understand that things are being updated in the database without a call to save or an update method. That''s so easy. I''ve put the attr_protected in there as well. Cheers! Jason -- Posted via http://www.ruby-forum.com/.