range_validator 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +2 -0
- data/Gemfile +10 -0
- data/LICENSE +20 -0
- data/README.rdoc +105 -0
- data/Rakefile +45 -0
- data/VERSION +1 -0
- data/lib/range_validator.rb +79 -0
- data/locales/en.yml +6 -0
- data/range_validator.gemspec +67 -0
- data/spec/range_validator_spec.rb +117 -0
- data/spec/spec_helper.rb +7 -0
- metadata +154 -0
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Chris Baker
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
= range_validator
|
2
|
+
|
3
|
+
Range validator for ActiveModel
|
4
|
+
|
5
|
+
validates :field, :range => true
|
6
|
+
validates :field, :range => { :overlapping => :other_records }
|
7
|
+
validates :field, :range => { :not_overlapping => Proc.new{ |record| record.other_records } }
|
8
|
+
|
9
|
+
== Examples
|
10
|
+
|
11
|
+
Suppose we have an Event model and want to ensure its duration is a range.
|
12
|
+
|
13
|
+
class Event
|
14
|
+
include ActiveModel::Validations
|
15
|
+
attr_accessor :duration
|
16
|
+
|
17
|
+
validates :duration, :range => true
|
18
|
+
end
|
19
|
+
|
20
|
+
event = Event.new
|
21
|
+
event.valid? # => false
|
22
|
+
event.errors # => #<OrderedHash {:duration=>["is not a range"]}>
|
23
|
+
|
24
|
+
event.duration = 1..10
|
25
|
+
event.valid? # => true
|
26
|
+
|
27
|
+
We can also validate that the range does or does not overlap with other
|
28
|
+
records. This is easiest to demonstrate using ActiveRecord. First we create a
|
29
|
+
migration for a Meeting model.
|
30
|
+
|
31
|
+
class CreateMeetings < ActiveRecord::Migration
|
32
|
+
def self.up
|
33
|
+
create_table :meetings do |t|
|
34
|
+
t.datetime :meeting_start
|
35
|
+
t.datetime :meeting_end
|
36
|
+
t.integer :room
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.down
|
41
|
+
drop_table :meetings
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
We can use the range validator to ensure that two meetings cannot be booked in
|
46
|
+
the same room at the same time.
|
47
|
+
|
48
|
+
class Meeting < ActiveRecord::Base
|
49
|
+
validates :duration, :range => { :not_overlapping => Proc.new{ |m| Meeting.where(:room => m.room) } }
|
50
|
+
|
51
|
+
def duration
|
52
|
+
meeting_start..meeting_end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
Now meetings will validate like so:
|
57
|
+
|
58
|
+
meeting = Meeting.new
|
59
|
+
meeting.meeting_start = DateTime.now
|
60
|
+
meeting.meeting_end = DateTime.now + 1.hour
|
61
|
+
meeting.room = 12
|
62
|
+
|
63
|
+
meeting.valid? # => true
|
64
|
+
meeting.save
|
65
|
+
|
66
|
+
other_meeting = Meeting.new
|
67
|
+
other_meeting.meeting_start = DateTime.now
|
68
|
+
other_meeting.meeting_end = DateTime.now + 1.hour
|
69
|
+
other_meeting.room = 12
|
70
|
+
|
71
|
+
other_meeting.valid? # => false
|
72
|
+
other_meeting.errors # => #<OrderedHash {:duration=>["overlaps"]}>
|
73
|
+
|
74
|
+
other_meeting.room = 4
|
75
|
+
other_meeting.valid? # => true
|
76
|
+
|
77
|
+
Constructing complex procs in the validates method can become messy fast. We
|
78
|
+
can move that logic into an instance method on the Meeting class and pass
|
79
|
+
a symbol to the range validator instead.
|
80
|
+
|
81
|
+
class Meeting < ActiveRecord::Base
|
82
|
+
validates :duration, :range => { :not_overlapping => :meetings_in_same_room }
|
83
|
+
|
84
|
+
def duration
|
85
|
+
meeting_start..meeting_end
|
86
|
+
end
|
87
|
+
|
88
|
+
def meetings_in_same_room
|
89
|
+
Meeting.where :room => room
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
== Contributing to range_validator
|
94
|
+
|
95
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
96
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
97
|
+
* Fork the project
|
98
|
+
* Start a feature/bugfix branch
|
99
|
+
* Commit and push until you are happy with your contribution
|
100
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
101
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
102
|
+
|
103
|
+
== Copyright
|
104
|
+
|
105
|
+
Copyright (c) 2011 Chris Baker. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'rake'
|
11
|
+
|
12
|
+
require 'jeweler'
|
13
|
+
Jeweler::Tasks.new do |gem|
|
14
|
+
gem.name = "range_validator"
|
15
|
+
gem.homepage = "http://github.com/chrisb87/range_validator"
|
16
|
+
gem.license = "MIT"
|
17
|
+
gem.summary = %Q{ActiveModel validator for ranges}
|
18
|
+
gem.description = %Q{ActiveModel validator for ranges}
|
19
|
+
gem.email = "baker.chris.3@gmail.com"
|
20
|
+
gem.authors = ["Chris Baker"]
|
21
|
+
end
|
22
|
+
Jeweler::RubygemsDotOrgTasks.new
|
23
|
+
|
24
|
+
require 'rspec/core'
|
25
|
+
require 'rspec/core/rake_task'
|
26
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
27
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
28
|
+
end
|
29
|
+
|
30
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
31
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
32
|
+
spec.rcov = true
|
33
|
+
end
|
34
|
+
|
35
|
+
task :default => :spec
|
36
|
+
|
37
|
+
require 'rake/rdoctask'
|
38
|
+
Rake::RDocTask.new do |rdoc|
|
39
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
40
|
+
|
41
|
+
rdoc.rdoc_dir = 'rdoc'
|
42
|
+
rdoc.title = "range_validator #{version}"
|
43
|
+
rdoc.rdoc_files.include('README*')
|
44
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
45
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.1
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'active_model'
|
2
|
+
require 'active_support/core_ext'
|
3
|
+
require 'active_support/i18n'
|
4
|
+
|
5
|
+
I18n.load_path += Dir[File.expand_path(File.join(File.dirname(__FILE__), '../locales', '*.yml')).to_s]
|
6
|
+
|
7
|
+
module ActiveModel
|
8
|
+
|
9
|
+
# == Active Model Range Validator
|
10
|
+
module Validations
|
11
|
+
class RangeValidator < ActiveModel::EachValidator
|
12
|
+
OPTIONS = [:overlapping, :not_overlapping].freeze
|
13
|
+
|
14
|
+
def check_validity!
|
15
|
+
options.each do |option, option_value|
|
16
|
+
next if option_value.is_a?(Symbol) || option_value.is_a?(Proc)
|
17
|
+
raise ArgumentError, ":#{option} must be a symbol or a proc"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def validate_each(record, attribute, value)
|
22
|
+
unless value.is_a? Range
|
23
|
+
record.errors.add(attribute, :not_a_range)
|
24
|
+
return
|
25
|
+
end
|
26
|
+
|
27
|
+
options.slice(*OPTIONS).each do |option, option_value|
|
28
|
+
other_records = retrieve_other_records(record, option_value)
|
29
|
+
|
30
|
+
if option == :overlapping && other_records.blank?
|
31
|
+
record.errors.add(attribute, :no_overlap)
|
32
|
+
end
|
33
|
+
|
34
|
+
other_records.each do |other_record|
|
35
|
+
overlap = value.overlaps? other_record.send(attribute)
|
36
|
+
|
37
|
+
if option == :overlapping && !overlap
|
38
|
+
record.errors.add(attribute, :no_overlap)
|
39
|
+
elsif option == :not_overlapping && overlap
|
40
|
+
record.errors.add(attribute, :overlap)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
protected
|
47
|
+
|
48
|
+
def retrieve_other_records(record, lookup)
|
49
|
+
if lookup.is_a?(Symbol)
|
50
|
+
other_records = record.send(lookup)
|
51
|
+
elsif lookup.is_a?(Proc)
|
52
|
+
other_records = lookup.call(record)
|
53
|
+
end
|
54
|
+
|
55
|
+
responds_to_key = record.respond_to?(:to_key) && !record.to_key.blank?
|
56
|
+
|
57
|
+
(other_records || []).reject do |other_record|
|
58
|
+
other_record.equal?(record) || (responds_to_key && other_record.to_key == record.to_key)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
module HelperMethods
|
64
|
+
# Validates that the specified attributes are valid ranges and, optionally, that they do
|
65
|
+
# or do not overlap with ranges in other models. Examples:
|
66
|
+
#
|
67
|
+
# validates :field, :range => true
|
68
|
+
# validates :field, :range => { :overlapping => Proc.new{ |record| record.other_records } }
|
69
|
+
# validates :field, :range => { :not_overlapping => :other_records }
|
70
|
+
#
|
71
|
+
# When passing a symbol to :overlapping or :not_overlapping, the object must respond_to that
|
72
|
+
# message with a (possibly empty) list of objects that have the same fields.
|
73
|
+
#
|
74
|
+
def validates_range_of(*attr_names)
|
75
|
+
validates_with RangeValidator, _merge_attributes(attr_names)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/locales/en.yml
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{range_validator}
|
8
|
+
s.version = "0.2.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Chris Baker"]
|
12
|
+
s.date = %q{2011-03-25}
|
13
|
+
s.description = %q{ActiveModel validator for ranges}
|
14
|
+
s.email = %q{baker.chris.3@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".rspec",
|
21
|
+
"Gemfile",
|
22
|
+
"LICENSE",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"lib/range_validator.rb",
|
27
|
+
"locales/en.yml",
|
28
|
+
"range_validator.gemspec",
|
29
|
+
"spec/range_validator_spec.rb",
|
30
|
+
"spec/spec_helper.rb"
|
31
|
+
]
|
32
|
+
s.homepage = %q{http://github.com/chrisb87/range_validator}
|
33
|
+
s.licenses = ["MIT"]
|
34
|
+
s.require_paths = ["lib"]
|
35
|
+
s.rubygems_version = %q{1.3.7}
|
36
|
+
s.summary = %q{ActiveModel validator for ranges}
|
37
|
+
s.test_files = [
|
38
|
+
"spec/range_validator_spec.rb",
|
39
|
+
"spec/spec_helper.rb"
|
40
|
+
]
|
41
|
+
|
42
|
+
if s.respond_to? :specification_version then
|
43
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
44
|
+
s.specification_version = 3
|
45
|
+
|
46
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
47
|
+
s.add_runtime_dependency(%q<activemodel>, [">= 3.0.0"])
|
48
|
+
s.add_runtime_dependency(%q<activesupport>, [">= 3.0.0"])
|
49
|
+
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
50
|
+
s.add_development_dependency(%q<rspec>, [">= 2.5.0"])
|
51
|
+
s.add_development_dependency(%q<ruby-debug>, [">= 0"])
|
52
|
+
else
|
53
|
+
s.add_dependency(%q<activemodel>, [">= 3.0.0"])
|
54
|
+
s.add_dependency(%q<activesupport>, [">= 3.0.0"])
|
55
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
56
|
+
s.add_dependency(%q<rspec>, [">= 2.5.0"])
|
57
|
+
s.add_dependency(%q<ruby-debug>, [">= 0"])
|
58
|
+
end
|
59
|
+
else
|
60
|
+
s.add_dependency(%q<activemodel>, [">= 3.0.0"])
|
61
|
+
s.add_dependency(%q<activesupport>, [">= 3.0.0"])
|
62
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
63
|
+
s.add_dependency(%q<rspec>, [">= 2.5.0"])
|
64
|
+
s.add_dependency(%q<ruby-debug>, [">= 0"])
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'range_validator'
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe "RangeValidator" do
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
TestModel.reset_callbacks(:validate)
|
8
|
+
@ranges = { :january => Date.civil(2011,1,1)..Date.civil(2011,1,31),
|
9
|
+
:february => Date.civil(2011,2,1)..Date.civil(2011,2,28),
|
10
|
+
:january_to_february => Date.civil(2011,1,1)..Date.civil(2011,2,28)}
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should be valid when the field is a range" do
|
14
|
+
TestModel.validates :duration, :range => true
|
15
|
+
record = TestModel.new({:duration => 0..1})
|
16
|
+
|
17
|
+
record.should be_valid
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should not be valid when the field is not a range" do
|
21
|
+
TestModel.validates :name, :range => true
|
22
|
+
record = TestModel.new({:name => "name"})
|
23
|
+
|
24
|
+
record.should_not be_valid
|
25
|
+
record.errors.should == {:name => ["is not a range"]}
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "overlapping" do
|
29
|
+
|
30
|
+
before(:each) do
|
31
|
+
TestModel.validates :date_range, :range => { :overlapping => :other_records }
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should be valid when there is overlap" do
|
35
|
+
record1 = TestModel.new({:date_range => @ranges[:january]})
|
36
|
+
record2 = TestModel.new({:date_range => @ranges[:january_to_february], :other_records => [record1]})
|
37
|
+
|
38
|
+
record2.should be_valid
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should not be valid when there is no overlap" do
|
42
|
+
record1 = TestModel.new({:date_range => @ranges[:january]})
|
43
|
+
record2 = TestModel.new({:date_range => @ranges[:february], :other_records => [record1]})
|
44
|
+
|
45
|
+
record2.should_not be_valid
|
46
|
+
record2.errors.should == {:date_range => ["does not overlap"]}
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should not be valid when overlapping an empty set" do
|
50
|
+
record = TestModel.new({:date_range => @ranges[:january], :other_records => []})
|
51
|
+
record.should_not be_valid
|
52
|
+
record.errors.should == {:date_range => ["does not overlap"]}
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should not be valid when overlapping nil" do
|
56
|
+
record = TestModel.new({:date_range => @ranges[:january], :other_records => nil})
|
57
|
+
record.should_not be_valid
|
58
|
+
record.errors.should == {:date_range => ["does not overlap"]}
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should throw an error when given a bad argument" do
|
62
|
+
expect {
|
63
|
+
TestModel.validates :duration, :range => { :overlapping => nil }
|
64
|
+
}.to raise_error ArgumentError, ":overlapping must be a symbol or a proc"
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "not_overlapping" do
|
70
|
+
|
71
|
+
before(:each) do
|
72
|
+
TestModel.validates :date_range, :range => { :not_overlapping => :other_records }
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should be valid when there is no overlap" do
|
76
|
+
record1 = TestModel.new({:date_range => @ranges[:january]})
|
77
|
+
record2 = TestModel.new({:date_range => @ranges[:february], :other_records => [record1]})
|
78
|
+
|
79
|
+
record2.should be_valid
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should not be valid when there is an overlap" do
|
83
|
+
record1 = TestModel.new({:date_range => @ranges[:january]})
|
84
|
+
record2 = TestModel.new({:date_range => @ranges[:january_to_february], :other_records => [record1]})
|
85
|
+
|
86
|
+
record2.should_not be_valid
|
87
|
+
record2.errors.should == {:date_range => ["overlaps"]}
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should be valid when overlapping nil" do
|
91
|
+
record = TestModel.new({:date_range => @ranges[:january], :other_records => nil})
|
92
|
+
record.should be_valid
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should be valid when overlapping an empty set" do
|
96
|
+
record = TestModel.new({:date_range => @ranges[:january], :other_records => []})
|
97
|
+
record.should be_valid
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should not detect overlap with other records with the same object_id" do
|
101
|
+
record = TestModel.new({:date_range => @ranges[:january]})
|
102
|
+
record.other_records = [record]
|
103
|
+
|
104
|
+
record.should be_valid
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should not detect overlap with other records with the same to_key value" do
|
108
|
+
record1 = TestModel.new({:date_range => @ranges[:january], :to_key => [1]})
|
109
|
+
record2 = TestModel.new({:date_range => @ranges[:january], :to_key => [1]})
|
110
|
+
record2.other_records = [record1]
|
111
|
+
|
112
|
+
record2.should be_valid
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: range_validator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 21
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 2
|
9
|
+
- 1
|
10
|
+
version: 0.2.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Chris Baker
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-03-25 00:00:00 -07:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
name: activemodel
|
25
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ">="
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
hash: 7
|
31
|
+
segments:
|
32
|
+
- 3
|
33
|
+
- 0
|
34
|
+
- 0
|
35
|
+
version: 3.0.0
|
36
|
+
requirement: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
name: activesupport
|
41
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
hash: 7
|
47
|
+
segments:
|
48
|
+
- 3
|
49
|
+
- 0
|
50
|
+
- 0
|
51
|
+
version: 3.0.0
|
52
|
+
requirement: *id002
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
name: jeweler
|
57
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
hash: 3
|
63
|
+
segments:
|
64
|
+
- 0
|
65
|
+
version: "0"
|
66
|
+
requirement: *id003
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
name: rspec
|
71
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
hash: 27
|
77
|
+
segments:
|
78
|
+
- 2
|
79
|
+
- 5
|
80
|
+
- 0
|
81
|
+
version: 2.5.0
|
82
|
+
requirement: *id004
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
type: :development
|
85
|
+
prerelease: false
|
86
|
+
name: ruby-debug
|
87
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
88
|
+
none: false
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
hash: 3
|
93
|
+
segments:
|
94
|
+
- 0
|
95
|
+
version: "0"
|
96
|
+
requirement: *id005
|
97
|
+
description: ActiveModel validator for ranges
|
98
|
+
email: baker.chris.3@gmail.com
|
99
|
+
executables: []
|
100
|
+
|
101
|
+
extensions: []
|
102
|
+
|
103
|
+
extra_rdoc_files:
|
104
|
+
- LICENSE
|
105
|
+
- README.rdoc
|
106
|
+
files:
|
107
|
+
- .rspec
|
108
|
+
- Gemfile
|
109
|
+
- LICENSE
|
110
|
+
- README.rdoc
|
111
|
+
- Rakefile
|
112
|
+
- VERSION
|
113
|
+
- lib/range_validator.rb
|
114
|
+
- locales/en.yml
|
115
|
+
- range_validator.gemspec
|
116
|
+
- spec/range_validator_spec.rb
|
117
|
+
- spec/spec_helper.rb
|
118
|
+
has_rdoc: true
|
119
|
+
homepage: http://github.com/chrisb87/range_validator
|
120
|
+
licenses:
|
121
|
+
- MIT
|
122
|
+
post_install_message:
|
123
|
+
rdoc_options: []
|
124
|
+
|
125
|
+
require_paths:
|
126
|
+
- lib
|
127
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
128
|
+
none: false
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
hash: 3
|
133
|
+
segments:
|
134
|
+
- 0
|
135
|
+
version: "0"
|
136
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ">="
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
hash: 3
|
142
|
+
segments:
|
143
|
+
- 0
|
144
|
+
version: "0"
|
145
|
+
requirements: []
|
146
|
+
|
147
|
+
rubyforge_project:
|
148
|
+
rubygems_version: 1.3.7
|
149
|
+
signing_key:
|
150
|
+
specification_version: 3
|
151
|
+
summary: ActiveModel validator for ranges
|
152
|
+
test_files:
|
153
|
+
- spec/range_validator_spec.rb
|
154
|
+
- spec/spec_helper.rb
|