开发者

Rails model passes validation but view still renders errors?

Oddly enough, my model passes validation just fine, and acts as expected, however I still have the error rendered to the view.

# Controller
def up
  @vote = Vote.create :vote => true, :voter => current_user, :voteable => Recipe.find(params[:id])
  respond_to do |format|
    format.js { render :json => {:model => 'vote', :success => @vote.valid?, :errors => @vote.errors }}
  end
  @vote.errors.clear # <= doesn't seem to help
end

The model I wrote has a custom validation:

c开发者_JS百科lass Vote < ActiveRecord::Base

  # ... associations etc.

  validate :voter_voting_too_frequently?

  private

  def voter_voting_too_frequently?
    last_vote_cast_by_voter = Vote.find_last_by_voter_id self.voter
    unless last_vote_cast_by_voter.nil? || last_vote_cast_by_voter.created_at < 5.seconds.ago
      errors.add_to_base("You can only vote every 5 seconds.")
    end
  end
end

And lastly, the response that is rendered to the view: (returned as js no doubt, but would be the same if it were in a <div>)

{"errors":[["base","You can only vote every 5 seconds."]],"model":"vote","success":false}

And even though it was successful, this is continuously returned.

Ideas on how to debug this?


The issue was totally bizarre, and was related to render => :json. Strangely the :success key couldn’t be first in the hash, when the respond_to block renders json.

This was the only change that needed to be changed:

format.js { render :json => {:model => 'vote', :errors => @vote.errors.on_base, :success => @vote.errors.on_base.nil?} }

Also I'm logging a ticket with the rails team.


It doesn't look like it is passing the validation since the success status is false.

If you take a look at you custom validation it seems that the "unless" keyword has caused some confusion.

Try:

if !last_vote_cast_by_voter.nil? && last_vote_cast_by_voter.created_at < 5.seconds.ago
  errors.add_to_base ...


I think your unless statement is wrong. Personally I am not used to them, so I always rewrite to if statements

if last_vote_cast_by_voter.nil? == false && last_vote_cast_by_voter.created_at > 5.seconds.ago

Looking at this line, I would suspect that last_vote_cast_by_voter.created_at should be lower than 5 seconds, therefore I suppose your unless statement should be changed into

unless last_vote_cast_by_voter.nil? || last_vote_cast_by_voter.created_at > 5.seconds.ago

Adding @vote.errors.clear indeed does not help, since the view is rendered at the point already...

If this still is not working try to write a test where you cast some votes. The time between two votes should be 1 second and 10 seconds for example.
Check if Vote.find_last_by_voter_id is working properly.

If all these test are working and rendering your view is not, then something strange is going on in your view and you should post some more information about your view, I guess.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜