samedi 5 avril 2014

Problems with Rails 4 with_options :if model validations


Vote count:

0




I'm refining a Rails 4 high scores API that I built. The change I want to make is to reject bad scores for a specific game.



Game has_many scores
Score belongs_to Game


The way I've been trying to do this based on the official docs is to use with_options :if:



# Asteroids validations
with_options :if => :is_asteroids? do |score|
score.validate :elapsed_and_lives_included?
score.validate :asteroids_elapsed_and_lives_valid?
score.validates :player,
length: { in: 1..10 },
allow_blank: false
score.validates :value,
numericality: {
greater_than_or_equal_to: 0,
}
score.validates :level,
numericality: {
greater_than: 0,
less_than_or_equal_to: 50
}
end

def is_asteroids?
game_id == 2 && is_seed.nil?
end

def elapsed_and_lives_included?
if @elapsed.nil? || @lives.nil?
errors[:base] << "Must include elapsed time and lives"
return false
end
true
end

def asteroids_elapsed_and_lives_valid?
if @lives > 0 && self.level != 50 || @lives > @elapsed
errors[:base] << "Invalid number of lives"
return false
elsif @elapsed < self.level * 300
errors[:base] << "Invalid elapsed time"
return false
end
true
end


But I've run into some pretty serious problems with this.


First, using score.validate/validates in the with_options block causes the validations in the block to not run at all, resulting in the Score instance I pass in through the Rails console to be considered valid even when the validation conditions are not met.


Removing score. from each validation in the block seems to solve that problem, but another issue I've run into is that the method called by the :if statement on which the validations in the block are based never seems to be evaluated for any of the validations in the block - whether score. is used or not. This means that the validations in the block, which are meant specifically for scores coming from Asteroids, will run for scores not coming from Asteroids.


That is, when I pass a Score in with game_id != 2, each of the validations in with_options is run when score. is removed; but if I add score., the validations don't run period, causing the invalid object to be seen by Rails as valid.


I'm caught between a rock and a hard place. What am I screwing up here?



asked 25 secs ago






Aucun commentaire:

Enregistrer un commentaire