I''ve got a form with inputs like user[first_name], user[last_name], etc. When editing the user instead of creating a new one I include a user[id]. I then try and save the object using: user = User.new(params[:user]) user.save() I would *expect* that since I included the user[id] it should do an update and should call validate_on_update. But this doesn''t appear to be the case. When I call the save it runs the code in validate_on_create instead (which fails validation). Why is this? -- Posted via http://www.ruby-forum.com/.
Because you need to find the record. You''re creating a new one in memory and then trying to save it to the database. To do both, try: user = User.find_or_create_by_id(params[:user][:id]) user.save Note, user.save can be checked for a return value to see if it was successful. Alternatively you can call user.save! which will raise an exception if it fails. In that case you need a begin / rescue block. Michael
Michael Trier wrote:> Because you need to find the record. You''re creating a new one in > memory and then trying to save it to the database. To do both, try: > > user = User.find_or_create_by_id(params[:user][:id]) > user.save > > Note, user.save can be checked for a return value to see if it was > successful. Alternatively you can call user.save! which will raise an > exception if it fails. In that case you need a begin / rescue block.Yeah I think that''s getting me on the right track. Is there a way to mass-set the attributes using a hash? I tried: User.find_or_create_by_id(params[:user][:id].to_i, params[:user]) But it didn''t work as expected. It just loaded the data from the DB as-is so the changes weren''t saved. -- Posted via http://www.ruby-forum.com/.
The Barge wrote:> Yeah I think that''s getting me on the right track. Is there a way to > mass-set the attributes using a hash? I tried: > > User.find_or_create_by_id(params[:user][:id].to_i, params[:user]) > > But it didn''t work as expected. It just loaded the data from the DB > as-is so the changes weren''t saved.Well I''ll answer my own question. I modified my code to do: user = User.find_or_create_by_id(params["user"]["id"]) user.attributes = params["user"] Then I do a test using user.new_record? to set some different things depending on if its new or updated. After that I call user.save() and it works like a charm! Thanks Michael -- Posted via http://www.ruby-forum.com/.
Glad you found it. Yeah, that''s probably the best approach. Michael
Michael Trier wrote:> Glad you found it. Yeah, that''s probably the best approach. > > MichaelHmm I''m noticing some oddities since I changed my code. Here are some of the columns in my user table when I first create the database. +----+-------+----------+------------+-----------+ | id | login | verified | first_name | last_name | +----+-------+----------+------------+-----------+ | 1 | admin | 1 | Site | Admin | | 2 | staff | 1 | Staff | User | +----+-------+----------+------------+-----------+ If I login as staff, create a user, logout then login as that user. Then lets say I log back out and back in as staff and create a second user, this is what the table looks like: +----+-------+----------+------------+-----------+ | id | login | verified | first_name | last_name | +----+-------+----------+------------+-----------+ | 1 | elmer | 1 | Elmer | Fudd | | 2 | staff | 1 | Staff | User | | 3 | john | 1 | John | Doe | +----+-------+----------+------------+-----------+ Seems to only happen if I log out of the staff account and back in as someone else. It''s really weird, but it overwrote admin! If I keep adding users it keeps incrementing, so after creating the third user (first john, then elmer, now jane) I get: +----+-------+----------+------------+-----------+ | id | login | verified | first_name | last_name | +----+-------+----------+------------+-----------+ | 1 | elmer | 1 | Elmer | Fudd | | 2 | jane | 1 | Jane | Smith | | 3 | john | 1 | John | Doe | +----+-------+----------+------------+-----------+ Any ideas what would be causing this? -- Posted via http://www.ruby-forum.com/.
The Barge wrote:> Michael Trier wrote: >> Glad you found it. Yeah, that''s probably the best approach. >> >> Michael > > Hmm I''m noticing some oddities since I changed my code. Here are some > of the columns in my user table when I first create the database. > > +----+-------+----------+------------+-----------+ > | id | login | verified | first_name | last_name | > +----+-------+----------+------------+-----------+ > | 1 | admin | 1 | Site | Admin | > | 2 | staff | 1 | Staff | User | > +----+-------+----------+------------+-----------+ > > If I login as staff, create a user, logout then login as that user. > Then lets say I log back out and back in as staff and create a second > user, this is what the table looks like: > > +----+-------+----------+------------+-----------+ > | id | login | verified | first_name | last_name | > +----+-------+----------+------------+-----------+ > | 1 | elmer | 1 | Elmer | Fudd | > | 2 | staff | 1 | Staff | User | > | 3 | john | 1 | John | Doe | > +----+-------+----------+------------+-----------+ > > Seems to only happen if I log out of the staff account and back in as > someone else. It''s really weird, but it overwrote admin! > > If I keep adding users it keeps incrementing, so after creating the > third user (first john, then elmer, now jane) I get: > > +----+-------+----------+------------+-----------+ > | id | login | verified | first_name | last_name | > +----+-------+----------+------------+-----------+ > | 1 | elmer | 1 | Elmer | Fudd | > | 2 | jane | 1 | Jane | Smith | > | 3 | john | 1 | John | Doe | > +----+-------+----------+------------+-----------+ > > Any ideas what would be causing this?That is because you are passing it user[:id] on your find_or_create_by_by call. Don''t do that. -- Ray
Ray Baxter wrote:> That is because you are passing it user[:id] on your > find_or_create_by_by call. > > Don''t do that.Well what am I supposed to pass it? -- Posted via http://www.ruby-forum.com/.
The Barge wrote:> Ray Baxter wrote: >> That is because you are passing it user[:id] on your >> find_or_create_by_by call. >> >> Don''t do that. > > Well what am I supposed to pass it?Depends on your use. From the discussion so far, it isn''t clear to me why you want to use user[:id] in your create. If you have a user[:id] then by definition you don''t need to create a user so find is sufficient. If you don''t have a user[:id] yet then you need to create one. The problem is that you are getting the current user''s id in your find_or_create_by_id. Either use logic to detect which is the case, or maybe do a User.find_or_create_by_login(user[:login]) in your controller. If you just create a new user before calling your form then you can just reference that user and not reference the user id at all. -- Ray
yeah, Ray''s right. I got myself in a tizzy and led you down a bad path. I was working off of your original info. Sorry about that. Michael
Ray Baxter wrote:> The Barge wrote: >> Ray Baxter wrote: >>> That is because you are passing it user[:id] on your >>> find_or_create_by_by call. >>> >>> Don''t do that. >> >> Well what am I supposed to pass it? > > > Depends on your use. From the discussion so far, it isn''t clear to me > why you want to use user[:id] in your create. If you have a user[:id] > then by definition you don''t need to create a user so find is > sufficient. If you don''t have a user[:id] yet then you need to create > one. > > The problem is that you are getting the current user''s id in your > find_or_create_by_id. Either use logic to detect which is the case, or > maybe do a User.find_or_create_by_login(user[:login]) in your > controller. > > If you just create a new user before calling your form then you can just > reference that user and not reference the user id at all.I''ll look into this more indepth tomorrow. Thanks for the info. What spawned my question was when I read the rails API about the save() call. * No record exists: Creates a new record with values matching those of the object attributes. * A record does exist: Updates the record with values matching those of the object attributes. So my real question maybe should have been simpler. How does the save call know that a record does exist? So it sounds like from reading what you''ve said that I should be calling: User.find_or_by_user(params[:user]) I could be getting it completely wrong though :) Basically what I''m looking for is a call similar to the Hibernate saveOrUpdate call. I want to pass the hash that comes from the edit form (which also acts as a new user form) and let rails decide whether it should create a new row or update an existing one. -- Posted via http://www.ruby-forum.com/.
yes, you''re correct. Maybe this bit of code will help. I''m using email, but it could just as well be username. Anything that would be unique. def signup # send the email address to us if params[:email].empty? render :update do |page| page.replace_html(''feedback'', ''Please enter a valid email address.'') page.visual_effect :highlight, ''flash'' end else begin user = MailingList.find_or_create_by_email(params[:email]) user.save! EmailNotify.send_mailing_list(user) rescue render :update do |page| page.replace_html(''feedback'', ''There was a problem signing you up for the mailing list. Please try again.'') page.visual_effect :highlight, ''feedback'' end end end end
Michael Trier wrote:> yes, you''re correct. Maybe this bit of code will help. I''m using > email, but it could just as well be username. Anything that would be > unique.Excellent. Thanks for the help! I''ll get started on the changes tomorrow. -- Posted via http://www.ruby-forum.com/.
Michael Trier wrote:> yes, you''re correct. Maybe this bit of code will help. I''m using > email, but it could just as well be username. Anything that would be > unique.Ok, using find_or_create_by_login (which should be fine since it''s unique) will return me the record, and new_record? will work correctly to tell me whether it was loaded from the DB or it''s new. But what happens if there IS no unique column in the DB other than the ID? I have another table that''s joined to the user table and it has no unique columns. I think I''ll just write my own method if Rails doesn''t have anything to do this. I''m just looking for a Hibernate-ish saveOrUpdate. -- Posted via http://www.ruby-forum.com/.
The Barge wrote:> Michael Trier wrote: >> yes, you''re correct. Maybe this bit of code will help. I''m using >> email, but it could just as well be username. Anything that would be >> unique. > > Ok, using find_or_create_by_login (which should be fine since it''s > unique) will return me the record, and new_record? will work correctly > to tell me whether it was loaded from the DB or it''s new. > > But what happens if there IS no unique column in the DB other than the > ID? I have another table that''s joined to the user table and it has no > unique columns.1) You don''t even have unique ids because the new user''s id is nil. You can have a large number of users in process with nil ids. 2) The problem that you were having before was because you were using the name of an object that was not unique. You had a user creating or editing a user. If instead you had a user creating or editing active_user, or some other identifiers, then the user[:id] of the editing user would not be confused with the active_user[:id]. -- Ray
Apparently Analagous Threads
- new crash in dovecot-auth test51
- Acessing new field values in validate_on_update
- [POSSIBLE FRAUD] Re: [EXTERNAL] Re: Help with Tripp Lite Internet600U
- [POSSIBLE FRAUD] Re: [EXTERNAL] Re: Help with Tripp Lite Internet600U
- [POSSIBLE FRAUD] Re: [EXTERNAL] Re: Help with Tripp Lite Internet600U