Reputation: 1106
Running Rails 5.2.3 in API-only mode.
I have a Questions
model, which has a disabled
flag that I update via a PATCH. The specific method I'm calling is namespaced like this: v1/custom_questions/questions#disable
. My Questions
model also has another boolean, standard
.
Now in the app, I have 5 questions that are standard, AKA their standard
field is true
. I also have some functionality where I let users create their own Questions, and these Questions all have standard: false
by default. I want to let users disable their custom questions, but I don't want to allow them to disable the standard
questions.
How can I set up validation that runs whenever the API receives the PATCH /disable
request that checks whether the question supplied is a standard one? I know that I can use validates :validation_method, on: :create
, but I'm not sure how to write this out so that it triggers when I call the disable
method namespaced under V1::CustomQuestions::QuestionsController
.
I currently have this logic in the controller, but I'd rather move this to a model validation so that @question.errors
gets populated if the ID supplied belongs to a standard question.
#questions_controller
class QuestionsController < ApplicationController
def disable
@question = Question.find(params[:id])
if @question.standard?
return
else
@question.disabled = true
end
if @question.save
render json: @question
else
render json: @question.errors, status: :bad_request
end
end
end
I've tried doing the below, however the @question.save
check seems to overwrite any errors I manually create.
if @question.standard?
@question.errors[:standard] << "Cannot deactivate a standard question"
else
@question.deleted = true
end
Upvotes: 0
Views: 733
Reputation: 382
The current structure is the culprit where you got into this situation. The responsibility of validation should be within the model and not outside it. Otherwise, one consumer (QuestionController in this case) may put some kind of validation and another one might skip it entirely.
You can try out the following snippet and see if this works for you.
class QuestionsController < ApplicationController
def disable
@question = Question.find(params[:id])
@question.disabled = true
if @question.save
render json: @question
else
render json: @question.errors, status: :bad_request
end
end
end
class Question < ApplicationRecord
validate :validate_disabled, on: update
def validate_disabled
if standard? && disabled
question.errors.add(:disable, "You cannot disable a standard question")
end
end
end
Upvotes: 1