acconrad
acconrad

Reputation: 3209

Ruby on Rails Use Model Association

I have the rails_best_practices gem and I'm getting the following warning:

APP/app/controllers/users_controller.rb - use model association (for @user_answer)

in reference to this gist of code:

begin
  @user_answer = @user.user_answers.where(:question_id => @question_id).first
  if @user_answer
    @user_answer.answer_id = @answer_id
    @user_answer.save!
    @message = 'Answer updated successfully!'
  else
    @user.user_answers.create(:question_id => params[:questionId], :answer_id => params[:answerId])
    @message = 'Answer submitted successfully!'
  end
rescue ex
  @message = ex.message.split(':')[1].chomp
end

but according to the page on model association it doesn't look like it's violating this, it looks like it is following along correctly. Am I missing something about this?

Upvotes: 0

Views: 102

Answers (1)

acconrad
acconrad

Reputation: 3209

The problem lies in directly accessing the variables in the @user_answer object, and not updating the user_answer within the @user variable...and since Rails has an update method, we can do this like so:

begin
  @user_answer = @user.user_answers.where(:question_id => @question_id).first
  if @user_answer
    @user.user_answers.update(:question_id => @question_id, :answer_id => @answer_id)
    @message = 'Answer updated successfully!'
  else
    @user.user_answers.create(:question_id => @question_id, :answer_id => @answer_id)
    @message = 'Answer submitted successfully!'
  end
rescue ex
  @message = ex.message.split(':')[1].chomp
end

But we can do better. Rather than differ by create and update, we can simply use Ruby's short circuit evaluation to create a `@user_answer symbol and update it whether it is new or not.

begin
  @user_answer = @user.user_answers.where(:question_id => @question_id).first || @user.user_answers.new
  @user_answer.update_attributes!(question_id: @question_id, answer_id: @answer_id)
  @message = 'Answer submitted successfully!'
rescue ex
  @message = ex.message.split(':')[1].chomp
end

Upvotes: 1

Related Questions