I have a Question
model that has many Answer
.
I'm validating that not more than three answers are created for each question:
has_many :answers, -> { order(position: :asc) }, before_add: :set_nested
private
def set_nested(answer)
if answers.size > 3
errors.add(:base, "Too many answers.")
raise "Unable to create answer."
else
answer.question ||= self
end
end
The code is working, when there are too many answers I get "rollback transaction" and "RuntimeError: Unable to create answer."
But then threre are 20 lines of path references to different lines in collection_association.rb
. It's the typical look when you have done something wrong.
Is this as it should be or am I doing the validation a bit too brutal?
To suppress the ugly error stacktrace
and error raised due to before_add
callback, what you can do is rescue
the raised error.
For example:
Update your question.rb
as below:
class AnswersLimitExceeded < StandardError; end ## Add this
class Question < ActiveRecord::Base
has_many :answers, -> { order(position: :asc) }, before_add: :set_nested
private
def set_nested(answer)
if answers.size > 3
errors.add(:base, "Too many answers.")
raise AnswersLimitExceeded, "Unable to create answer." ## Change here
else
answer.question ||= self
end
end
After this update the create
action in your QuestionsController
def create
## ...
begin
if @question.save
## ...
else
## ..
end
rescue AnswersLimitExceeded
render action: 'new'
end
end
This way whenever AnswersLimitExceeded
is raised within your Question
model while creating the associated answers
then it is rescued at controller level thereby suppressing the specific error AnswersLimitExceeded
with message Too many answers
elegantly.
Also, if you notice I created a separate Error class ie, AnswersLimitExceeded
so that I rescue ONLY
this particular exception in Controller and not all others.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.