0

This is what I'm doing:-

@userdata =find_or_create_by_id(:id=>params[:id])

Now how can I know weather I need to use @userdata.save or

@userdata.update_attributes params[:user_object]

And how to pass my user object in case of @userdata.save

Sachin Prasad
  • 5,365
  • 12
  • 54
  • 101

3 Answers3

3

Not sure what you mean by whether to user save or update_attributes. find_or_create_by_id will return a user object, that may or may not be persisted depending on whether validations passed (if it didn't exist already). You can find out by asking @userdata.persisted?

In any case, I recommend using first_or_create:

@userdata = User.where(:id => params[:id]).first_or_create(params[:user_object])
if @userdata.persisted? 
  # proceed
else
  # errors in params, recover
end

UPDATE: Kiddorails is right about the above code not updating the record if it existed prior to the call. The solution is actually pretty simple. Sorry I didn't get it right the first time:

@userdata = User.where(:id => params[:id]).first || User.new
@userdata.update_attributes(params[:user_object])

This works because update_attributes works just fine whether the record is new or persisted.

boulder
  • 3,256
  • 15
  • 21
  • Its bit confusing can you please explain why you are using persisted? – Sachin Prasad May 16 '13 at 12:56
  • And, err.. I don't think `first_or_create` will `update` the attributes if the `User` with that `id` is matched. If it is matched, it will just return the user with that id, without updating with `params[:user_object]` – kiddorails May 16 '13 at 12:59
  • So, should I do something like this: if @userdata.persisted? @userdata.update_attributes params[:user_object] else # Some error occured end – Sachin Prasad May 16 '13 at 13:02
  • No. If the record is new, it would have already `create`d the record earlier, doing `update_attributes` again, won't serve you any purpose. Anyway, see the link I posted in my answer and last comment. That is pretty good solution. – kiddorails May 16 '13 at 13:16
  • kiddorails is right, so I have updated my answer with the correct approach. – boulder May 16 '13 at 15:34
  • @boulder: Bingo! I've also added an `ActiveRecord` helper in your answer which is usually not known; but is perfect to simplify your query :) – kiddorails May 16 '13 at 16:58
  • @kiddorails. Thank you for your suggestion. However find_or_initialize_by_id is deprecated in Rails 4; in order to make the answer Rails 4 compatible I've chosen not to add it. – boulder May 16 '13 at 17:25
1

Perhaps, this can help:

@userdata = User.find_or_create_by_id(params[:id])
if @userdata.new_record? #=> @userdata is a new record
  #Add attributes
  @userdata.save
else
  @userdata.update_attributes params[:user_object]
end

Or even better, make your own method as Best way to find_or_create_by_id but update the attributes if the record is found

Community
  • 1
  • 1
kiddorails
  • 12,961
  • 2
  • 32
  • 41
  • This is wrong. persisted? => true doesn't mean it's a new record. It returns true whether it's a new record, or it already existed. It will return false only if create failed. Additionally, you can use update_attributes in either case. – boulder May 16 '13 at 12:35
  • Agreed. Perhaps [new_record?](http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-new_record-3F) then? – kiddorails May 16 '13 at 12:39
  • How to assign the user object in case of @userdata.save? – Sachin Prasad May 16 '13 at 12:44
  • Sachin. See my answer below. – boulder May 16 '13 at 12:45
  • `@userdata.attributes = params[:user_object]`. Though, solution of @boulder is certainly more generic and conventional. – kiddorails May 16 '13 at 12:53
1

Try this. The first line search object and create if doesn't exist.

   userdata = UserModel.where(:id=>params[:id]).first_or_create(:id=>params[:id])
    unless userdata .nil?
      update_attributes params[:user_object]
    end