3

I'm using Ruby on Rails and i have a find_or_create_by_custom_stuff method. However i would like to know if the object i get back was found, or was created. Something like this

user = User.find_or_create_by_custom_stuff(params[:user])
if user.was_found_from_database?
  ...
elsif user.was_recently_created?
  ...
end

Is there any way I can do this without relying on the created_at timestamp of the user?

5 Answers 5

17

You have the ActiveRecord method for that

@instance.new_record?

For you

user = User.find_or_create(params[:user])
user.new_record?

Note :

.new_record? => NOT RECORDED IN DATABASE 
Sign up to request clarification or add additional context in comments.

2 Comments

.new_record? will, in this case, always return false (user is a DB created object after the User.find_or_create)
@Tamer Salama your are right ! My response it's false ! Your response work effectively, my apologizes...
3

I would try not to use the find_or_create* method. The reason is that almost always the finder pattern will diverge from the creation one.

Another approach could be:

user = User.custom_finder(params)
if user.blank?
   user = User.create(params)
   #some business logic goes here
else
   #other business logic goes here
end

This could also be implemented into the User model for better structure

3 Comments

This is a better way to do it. Using create means that the new object will be persisted in the database, thus making it indistinguishable from a found object (unless you look at created_at, which would be very sloppy of you).
agreed, going to a find_or_new_by_whatever(...) makes more sense, thanks!
There is a first_or_initialize check here: apidock.com/rails/v5.2.3/ActiveRecord/Relation/…
0

You can try find_or_initialize_by and then do the new_record? check. One thing to keep in mind is that a user could be created before you have the chance to save your new record. You also have that same issue with find_or_create_by but this might give a larger window for such a thing to happen.

user = User.find_or_initialize_by(email: params[:email])
if user.new_record?
  if user.save
    render json: user, status: :created
  else
    render json: { errors: @like.errors }, status: :unprocessable_entity
  end
else
  render json: user
end

Comments

-1
user = User.find_or_create_by_custom_stuff(params[:user])
if user.new_record?
  # record does not exist in datastore
else
  ...
end

2 Comments

user.new_record? will always return true as it is a DB created object. find_or_create_* will attempt a find - and then if it doesn't exist will create one. hence, the returned object is a created record.
Ah, you're right. I was thinking of new, not create. Thank you.
-1
user_total = User.count
user = User.find_or_create_by_custom_stuff(params[:user])
if user_total == User.count
 #No new user was created, find method was used.
 ...
else
 #New user created, create method was used.
 ...
end

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.