In Rails, what is the best way to update a record or create a new one if it doesn't exist?

后端 未结 6 597
终归单人心
终归单人心 2020-12-24 07:14

I have a create statement for some models, but it’s creating a record within a join table regardless of whether the record already exists.

Here is what my code looks

6条回答
  •  再見小時候
    2020-12-24 07:48

    Assuming that the Choice model has a user_id (to associate with a user) and an interest_id (to associate with an interest), something like this should do the trick:

    @user = User.find(current_user)
    @event = Event.find(params[:id])
    
    @event.interests.each do |interest|
      choice = @user.choices.find_or_initialize_by_interest_id(interest.id) do |c|
        c.score = 0 # Or whatever you want the initial value to be - 1
      end
    
      choice.score += 1
      choice.save!
    end
    

    Some notes:

    1. You don't need to include the user_id column in the find_or_*_by_*, as you've already instructed Rails to only fetch choices belonging to @user.
    2. I'm using find_or_initialize_by_*, which is essentially the same as find_or_create_by_*, with the one key difference being that initialize doesn't actually create the record. This would be similar to Model.new as opposed to Model.create.
    3. The block that sets c.score = 0 is only executed if the record does not exist.
    4. choice.score += 1 will update the score value for the record, regardless if it exists or not. Hence, the default score c.score = 0 should be the initial value minus one.
    5. Finally, choice.save! will either update the record (if it already existed) or create the initiated record (if it didn't).

提交回复
热议问题