Rails Validate Cup Increment is Always by a Factor of One
I have a Game model which has_many Rounds which has_many Shots. Per game, each cup hit with a shot should be unique. This is easy enough to do with validates_uniqueness_of :cup using a scope of :game_id.
However, how do I validate that each Shot is an increment of +1 of the last shot? I cannot have users select their first shot as having made cup 4. This would make no sense.
My form is using form_for @round which accepts nested attributes for exactly 6 shots.
How do I implement this validation? Do I need to refactor my view or completely reth开发者_开发知识库ink this?
Since you are using Rails 3, you get some nice options here. I'm not sure that I understand your problem completely, but I'm assuming that you want some type of validation where the score starts at 1 and increments each time.
Here's a test.
require 'test_helper'
class ShotTest < ActiveSupport::TestCase
test "score validations by game" do
Shot.delete_all # Just to be sure. In a real test setup I would have handled this elsewhere.
shot = Shot.new(:game_id => 1, :score => 1)
assert shot.valid?
shot.save!
assert ! Shot.new(:game_id => 1, :score => 1).valid?
assert ! Shot.new(:game_id => 1, :score => 3).valid?
assert Shot.new(:game_id => 1, :score => 2).valid?
assert Shot.new(:game_id => 2, :score => 1).valid?
end
end
And an example model.
# Stick this in a lib file somewhere
class IncrementValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
record.errors[attribute] << "must increment score by +1 " unless value == (Shot.maximum(:score, :conditions => {:game_id => record.game_id} ).to_i + 1)
end
end
class Shot < ActiveRecord::Base
validates :score, :uniqueness => {:scope => :game_id}, :increment => true
end
Test output:
$ ruby -I./test test/unit/shot_test.rb
Loaded suite test/unit/shot_test
Started
.
Finished in 0.042116 seconds.
1 tests, 5 assertions, 0 failures, 0 errors
精彩评论