yeastymobs-remarkable_mongomapper 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +10 -0
- data/VERSION +1 -1
- data/lib/remarkable_mongomapper/base.rb +0 -2
- data/lib/remarkable_mongomapper/describe.rb +199 -0
- data/lib/remarkable_mongomapper/human_names.rb +37 -0
- data/lib/remarkable_mongomapper/matchers/allow_values_for_matcher.rb +86 -0
- data/lib/remarkable_mongomapper/matchers/validate_presence_of_matcher.rb +4 -1
- data/lib/remarkable_mongomapper.rb +3 -1
- data/locales/en.yml +21 -1
- data/remarkable_mongomapper.gemspec +10 -3
- data/spec/matchers/allow_values_for_matcher_spec.rb +71 -0
- data/spec/matchers/have_key_matcher_spec.rb +1 -1
- data/spec/model_builder.rb +64 -0
- data/spec/models.rb +1 -1
- data/spec/spec_helper.rb +3 -2
- metadata +9 -2
data/Rakefile
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rake'
|
3
|
+
require 'spec/rake/spectask'
|
3
4
|
|
4
5
|
begin
|
5
6
|
require 'jeweler'
|
@@ -15,4 +16,13 @@ begin
|
|
15
16
|
end
|
16
17
|
rescue LoadError
|
17
18
|
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'Default: run specs.'
|
22
|
+
task :default => :spec
|
23
|
+
|
24
|
+
desc 'Run all the specs for the machinist plugin.'
|
25
|
+
Spec::Rake::SpecTask.new do |t|
|
26
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
27
|
+
t.rcov = false
|
18
28
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.1
|
@@ -104,7 +104,6 @@ module Remarkable
|
|
104
104
|
|
105
105
|
return true if model.valid?
|
106
106
|
|
107
|
-
# FIXME
|
108
107
|
error_message_to_avoid = error_message_from_model(model, attribute, error_message_to_avoid)
|
109
108
|
assert_does_not_contain(model.errors.on(attribute), error_message_to_avoid)
|
110
109
|
end
|
@@ -131,7 +130,6 @@ module Remarkable
|
|
131
130
|
|
132
131
|
return false if model.valid? || model.errors.on(attribute).blank?
|
133
132
|
|
134
|
-
# FIXME
|
135
133
|
error_message_to_expect = error_message_from_model(model, attribute, error_message_to_expect)
|
136
134
|
assert_contains(model.errors.on(attribute), error_message_to_expect)
|
137
135
|
end
|
@@ -0,0 +1,199 @@
|
|
1
|
+
module Remarkable
|
2
|
+
module ActiveRecord
|
3
|
+
|
4
|
+
def self.after_include(target) #:nodoc:
|
5
|
+
target.class_inheritable_reader :describe_subject_attributes, :default_subject_attributes
|
6
|
+
target.send :include, Describe
|
7
|
+
end
|
8
|
+
|
9
|
+
# Overwrites describe to provide quick way to configure your subject:
|
10
|
+
#
|
11
|
+
# describe Post
|
12
|
+
# should_validate_presente_of :title
|
13
|
+
#
|
14
|
+
# describe :published => true do
|
15
|
+
# should_validate_presence_of :published_at
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# This is the same as:
|
20
|
+
#
|
21
|
+
# describe Post
|
22
|
+
# should_validate_presente_of :title
|
23
|
+
#
|
24
|
+
# describe "when published is true" do
|
25
|
+
# subject { Post.new(:published => true) }
|
26
|
+
# should_validate_presence_of :published_at
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# The string can be localized using I18n. An example yml file is:
|
31
|
+
#
|
32
|
+
# locale:
|
33
|
+
# remarkable:
|
34
|
+
# mongo_mapper:
|
35
|
+
# describe:
|
36
|
+
# each: "{{key}} is {{value}}"
|
37
|
+
# prepend: "when "
|
38
|
+
# connector: " and "
|
39
|
+
#
|
40
|
+
# You can also call subject attributes to set the default attributes for a
|
41
|
+
# subject. You can even mix with a fixture replacement tool:
|
42
|
+
#
|
43
|
+
# describe Post
|
44
|
+
# # Fixjour example
|
45
|
+
# subject_attributes { valid_post_attributes }
|
46
|
+
#
|
47
|
+
# describe :published => true do
|
48
|
+
# should_validate_presence_of :published_at
|
49
|
+
# end
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# You can retrieve the merged result of all attributes given using the
|
53
|
+
# subject_attributes instance method:
|
54
|
+
#
|
55
|
+
# describe Post
|
56
|
+
# # Fixjour example
|
57
|
+
# subject_attributes { valid_post_attributes }
|
58
|
+
#
|
59
|
+
# describe :published => true do
|
60
|
+
# it "should have default subject attributes" do
|
61
|
+
# subject_attributes.should == { :title => 'My title', :published => true }
|
62
|
+
# end
|
63
|
+
# end
|
64
|
+
# end
|
65
|
+
#
|
66
|
+
module Describe
|
67
|
+
|
68
|
+
def self.included(base) #:nodoc:
|
69
|
+
base.extend ClassMethods
|
70
|
+
end
|
71
|
+
|
72
|
+
module ClassMethods
|
73
|
+
|
74
|
+
# Overwrites describe to provide quick way to configure your subject:
|
75
|
+
#
|
76
|
+
# describe Post
|
77
|
+
# should_validate_presente_of :title
|
78
|
+
#
|
79
|
+
# describe :published => true do
|
80
|
+
# should_validate_presence_of :published_at
|
81
|
+
# end
|
82
|
+
# end
|
83
|
+
#
|
84
|
+
# This is the same as:
|
85
|
+
#
|
86
|
+
# describe Post
|
87
|
+
# should_validate_presente_of :title
|
88
|
+
#
|
89
|
+
# describe "when published is true" do
|
90
|
+
# subject { Post.new(:published => true) }
|
91
|
+
# should_validate_presence_of :published_at
|
92
|
+
# end
|
93
|
+
# end
|
94
|
+
#
|
95
|
+
# The string can be localized using I18n. An example yml file is:
|
96
|
+
#
|
97
|
+
# locale:
|
98
|
+
# remarkable:
|
99
|
+
# mongo_mapper:
|
100
|
+
# describe:
|
101
|
+
# each: "{{key}} is {{value}}"
|
102
|
+
# prepend: "when "
|
103
|
+
# connector: " and "
|
104
|
+
#
|
105
|
+
# See also subject_attributes instance and class methods for more
|
106
|
+
# information.
|
107
|
+
#
|
108
|
+
def describe(*args, &block)
|
109
|
+
if described_class && args.first.is_a?(Hash)
|
110
|
+
attributes = args.shift
|
111
|
+
|
112
|
+
connector = Remarkable.t "remarkable.mongo_mapper.describe.connector", :default => " and "
|
113
|
+
|
114
|
+
description = if self.describe_subject_attributes.blank?
|
115
|
+
Remarkable.t("remarkable.mongo_mapper.describe.prepend", :default => "when ")
|
116
|
+
else
|
117
|
+
connector.lstrip
|
118
|
+
end
|
119
|
+
|
120
|
+
pieces = []
|
121
|
+
attributes.each do |key, value|
|
122
|
+
translated_key = if described_class.respond_to?(:human_attribute_name)
|
123
|
+
described_class.human_attribute_name(key.to_s, :locale => Remarkable.locale)
|
124
|
+
else
|
125
|
+
key.to_s.humanize
|
126
|
+
end
|
127
|
+
|
128
|
+
pieces << Remarkable.t("remarkable.mongo_mapper.describe.each",
|
129
|
+
:default => "{{key}} is {{value}}",
|
130
|
+
:key => translated_key.downcase, :value => value.inspect)
|
131
|
+
end
|
132
|
+
|
133
|
+
description << pieces.join(connector)
|
134
|
+
args.unshift(description)
|
135
|
+
|
136
|
+
# Creates an example group, set the subject and eval the given block.
|
137
|
+
#
|
138
|
+
example_group = super(*args) do
|
139
|
+
write_inheritable_hash(:describe_subject_attributes, attributes)
|
140
|
+
set_described_subject!
|
141
|
+
instance_eval(&block)
|
142
|
+
end
|
143
|
+
else
|
144
|
+
super(*args, &block)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# Sets default attributes for the subject. You can use this to set up
|
149
|
+
# your subject with valid attributes. You can even mix with a fixture
|
150
|
+
# replacement tool and still use quick subjects:
|
151
|
+
#
|
152
|
+
# describe Post
|
153
|
+
# # Fixjour example
|
154
|
+
# subject_attributes { valid_post_attributes }
|
155
|
+
#
|
156
|
+
# describe :published => true do
|
157
|
+
# should_validate_presence_of :published_at
|
158
|
+
# end
|
159
|
+
# end
|
160
|
+
#
|
161
|
+
def subject_attributes(options=nil, &block)
|
162
|
+
write_inheritable_attribute(:default_subject_attributes, options || block)
|
163
|
+
set_described_subject!
|
164
|
+
end
|
165
|
+
|
166
|
+
def set_described_subject!
|
167
|
+
subject {
|
168
|
+
record = self.class.described_class.new
|
169
|
+
record.send(:attributes=, subject_attributes, false)
|
170
|
+
record
|
171
|
+
}
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
# Returns a hash with the subject attributes declared using the
|
176
|
+
# subject_attributes class method and the attributes given using the
|
177
|
+
# describe method.
|
178
|
+
#
|
179
|
+
# describe Post
|
180
|
+
# subject_attributes { valid_post_attributes }
|
181
|
+
#
|
182
|
+
# describe :published => true do
|
183
|
+
# it "should have default subject attributes" do
|
184
|
+
# subject_attributes.should == { :title => 'My title', :published => true }
|
185
|
+
# end
|
186
|
+
# end
|
187
|
+
# end
|
188
|
+
#
|
189
|
+
def subject_attributes
|
190
|
+
default = self.class.default_subject_attributes
|
191
|
+
default = self.instance_eval(&default) if default.is_a?(Proc)
|
192
|
+
default ||= {}
|
193
|
+
|
194
|
+
default.merge(self.class.describe_subject_attributes || {})
|
195
|
+
end
|
196
|
+
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
if defined?(Spec)
|
2
|
+
module Spec #:nodoc:
|
3
|
+
module Example #:nodoc:
|
4
|
+
module ExampleGroupMethods #:nodoc:
|
5
|
+
|
6
|
+
# This allows "describe User" to use the I18n human name of User.
|
7
|
+
#
|
8
|
+
def self.build_description_with_i18n(*args)
|
9
|
+
args.inject("") do |description, arg|
|
10
|
+
arg = if arg.respond_to?(:human_name)
|
11
|
+
arg.human_name(:locale => Remarkable.locale)
|
12
|
+
else
|
13
|
+
arg.to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
description << " " unless (description == "" || arg =~ /^(\s|\.|#)/)
|
17
|
+
description << arg
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# This is for rspec <= 1.1.12.
|
22
|
+
#
|
23
|
+
def self.description_text(*args)
|
24
|
+
self.build_description_with_i18n(*args)
|
25
|
+
end
|
26
|
+
|
27
|
+
# This is for rspec >= 1.2.0.
|
28
|
+
#
|
29
|
+
def self.build_description_from(*args)
|
30
|
+
text = ExampleGroupMethods.build_description_with_i18n(*args)
|
31
|
+
text == "" ? nil : text
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Remarkable
|
2
|
+
module MongoMapper
|
3
|
+
module Matchers
|
4
|
+
class AllowValuesForMatcher < Remarkable::MongoMapper::Base #:nodoc:
|
5
|
+
include Remarkable::Negative
|
6
|
+
arguments :collection => :attributes, :as => :attribute
|
7
|
+
|
8
|
+
optional :message
|
9
|
+
optional :in, :splat => true
|
10
|
+
optional :allow_nil, :allow_blank, :default => true
|
11
|
+
|
12
|
+
collection_assertions :is_valid?, :is_invalid?, :allow_nil?, :allow_blank?
|
13
|
+
|
14
|
+
default_options :message => "is invalid"
|
15
|
+
|
16
|
+
before_assert do
|
17
|
+
first_value = @options[:in].is_a?(Array) ? @options[:in].first : @options[:in]
|
18
|
+
@in_range = first_value.is_a?(Range)
|
19
|
+
|
20
|
+
@options[:in] = if @in_range
|
21
|
+
first_value.to_a[0,2] + first_value.to_a[-2,2]
|
22
|
+
else
|
23
|
+
[*@options[:in]].compact
|
24
|
+
end
|
25
|
+
|
26
|
+
@options[:in].uniq!
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
def is_valid?
|
32
|
+
assert_collection :value, valid_values do |value|
|
33
|
+
good?(value)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def is_invalid?
|
38
|
+
assert_collection :value, invalid_values do |value|
|
39
|
+
bad?(value)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def valid_values
|
44
|
+
@options[:in]
|
45
|
+
end
|
46
|
+
|
47
|
+
def invalid_values
|
48
|
+
[]
|
49
|
+
end
|
50
|
+
|
51
|
+
def interpolation_options
|
52
|
+
options = if @in_range
|
53
|
+
{ :in => (@options[:in].first..@options[:in].last).inspect }
|
54
|
+
elsif @options[:in].is_a?(Array)
|
55
|
+
{ :in => array_to_sentence(@options[:in], true, '[]') }
|
56
|
+
else
|
57
|
+
{ :in => @options[:in].inspect }
|
58
|
+
end
|
59
|
+
|
60
|
+
options.merge!(:behavior => @behavior.to_s)
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
# Ensures that the attribute can be set to the given values.
|
66
|
+
#
|
67
|
+
# == Options
|
68
|
+
#
|
69
|
+
# * <tt>:allow_nil</tt> - when supplied, validates if it allows nil or not.
|
70
|
+
# * <tt>:allow_blank</tt> - when supplied, validates if it allows blank or not.
|
71
|
+
# * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
72
|
+
# Regexp, string or symbol. Default = <tt>I18n.translate('activerecord.errors.messages.invalid')</tt>
|
73
|
+
#
|
74
|
+
# == Examples
|
75
|
+
#
|
76
|
+
# should_allow_values_for :isbn, "isbn 1 2345 6789 0", "ISBN 1-2345-6789-0"
|
77
|
+
# it { should allow_values_for(:isbn, "isbn 1 2345 6789 0", "ISBN 1-2345-6789-0") }
|
78
|
+
#
|
79
|
+
def allow_values_for(attribute, *args, &block)
|
80
|
+
options = args.extract_options!
|
81
|
+
AllowValuesForMatcher.new(attribute, options.merge!(:in => args), &block).spec(self)
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -2,7 +2,6 @@ module Remarkable
|
|
2
2
|
module MongoMapper
|
3
3
|
module Matchers
|
4
4
|
class ValidatePresenceOfMatcher < Remarkable::MongoMapper::Base
|
5
|
-
|
6
5
|
arguments :collection => :attributes, :as => :attribute
|
7
6
|
optional :message
|
8
7
|
|
@@ -19,6 +18,10 @@ module Remarkable
|
|
19
18
|
|
20
19
|
# Ensures that the model cannot be saved if one of the attributes listed is not present.
|
21
20
|
#
|
21
|
+
# == Options
|
22
|
+
#
|
23
|
+
# * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
24
|
+
# Regexp, string or symbol. Default = "can't be empty"
|
22
25
|
#
|
23
26
|
# == Examples
|
24
27
|
#
|
@@ -14,7 +14,9 @@ dir = File.dirname(__FILE__)
|
|
14
14
|
Remarkable.add_locale File.join(dir, '..', 'locales', 'en.yml')
|
15
15
|
|
16
16
|
require File.join(dir, 'remarkable_mongomapper', 'base')
|
17
|
-
|
17
|
+
require File.join(dir, 'remarkable_mongomapper', 'describe')
|
18
|
+
# require File.join(dir, 'remarkable_mongomapper', 'human_names')
|
19
|
+
|
18
20
|
# Add matchers
|
19
21
|
Dir[File.join(dir, 'remarkable_mongomapper', 'matchers', '*.rb')].each do |file|
|
20
22
|
require file
|
data/locales/en.yml
CHANGED
@@ -1,6 +1,26 @@
|
|
1
1
|
en:
|
2
2
|
remarkable:
|
3
3
|
mongo_mapper:
|
4
|
+
describe:
|
5
|
+
each: "{{key}} is {{value}}"
|
6
|
+
prepend: "when "
|
7
|
+
connector: " and "
|
8
|
+
expectations:
|
9
|
+
allow_nil: "{{subject_name}} to {{not}}allow nil values for {{attribute}}"
|
10
|
+
allow_blank: "{{subject_name}} to {{not}}allow blank values for {{attribute}}"
|
11
|
+
optionals:
|
12
|
+
allow_nil:
|
13
|
+
positive: "allowing nil values"
|
14
|
+
negative: "not allowing nil values"
|
15
|
+
allow_blank:
|
16
|
+
positive: "allowing blank values"
|
17
|
+
negative: "not allowing blank values"
|
18
|
+
|
19
|
+
allow_values_for:
|
20
|
+
description: "allow {{in}} as values for {{attributes}}"
|
21
|
+
expectations:
|
22
|
+
is_valid: "{{subject_name}} to be valid when {{attribute}} is set to {{value}}"
|
23
|
+
|
4
24
|
association:
|
5
25
|
many: have many
|
6
26
|
belongs_to: belong to
|
@@ -12,7 +32,7 @@ en:
|
|
12
32
|
options_match: "{{subject_name}} records {{type}} {{association}} with options {{options}}, got {{actual}}"
|
13
33
|
|
14
34
|
have_key:
|
15
|
-
description: "have key(s) {{attributes}}"
|
35
|
+
description: "have key(s) {{attributes}} with type {{type}}"
|
16
36
|
expectations:
|
17
37
|
has_key: "{{subject_name}} to have key named {{attribute}} with type {{type}}"
|
18
38
|
|
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{remarkable_mongomapper}
|
5
|
-
s.version = "0.1.
|
5
|
+
s.version = "0.1.1"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Nicolas M\303\251rouze", "Vincent Hellot", "Mathieu Fosse"]
|
9
|
-
s.date = %q{2009-07-
|
9
|
+
s.date = %q{2009-07-31}
|
10
10
|
s.email = %q{dev@yeastymobs.com}
|
11
11
|
s.extra_rdoc_files = [
|
12
12
|
"LICENSE",
|
@@ -20,14 +20,19 @@ Gem::Specification.new do |s|
|
|
20
20
|
"VERSION",
|
21
21
|
"lib/remarkable_mongomapper.rb",
|
22
22
|
"lib/remarkable_mongomapper/base.rb",
|
23
|
+
"lib/remarkable_mongomapper/describe.rb",
|
24
|
+
"lib/remarkable_mongomapper/human_names.rb",
|
25
|
+
"lib/remarkable_mongomapper/matchers/allow_values_for_matcher.rb",
|
23
26
|
"lib/remarkable_mongomapper/matchers/association_matcher.rb",
|
24
27
|
"lib/remarkable_mongomapper/matchers/have_key_matcher.rb",
|
25
28
|
"lib/remarkable_mongomapper/matchers/validate_presence_of_matcher.rb",
|
26
29
|
"locales/en.yml",
|
27
30
|
"remarkable_mongomapper.gemspec",
|
31
|
+
"spec/matchers/allow_values_for_matcher_spec.rb",
|
28
32
|
"spec/matchers/association_matcher_spec.rb",
|
29
33
|
"spec/matchers/have_key_matcher_spec.rb",
|
30
34
|
"spec/matchers/validate_presence_of_matcher_spec.rb",
|
35
|
+
"spec/model_builder.rb",
|
31
36
|
"spec/models.rb",
|
32
37
|
"spec/spec.opts",
|
33
38
|
"spec/spec_helper.rb"
|
@@ -38,9 +43,11 @@ Gem::Specification.new do |s|
|
|
38
43
|
s.rubygems_version = %q{1.3.5}
|
39
44
|
s.summary = %q{MongoMapper Remarkable Matchers}
|
40
45
|
s.test_files = [
|
41
|
-
"spec/matchers/
|
46
|
+
"spec/matchers/allow_values_for_matcher_spec.rb",
|
47
|
+
"spec/matchers/association_matcher_spec.rb",
|
42
48
|
"spec/matchers/have_key_matcher_spec.rb",
|
43
49
|
"spec/matchers/validate_presence_of_matcher_spec.rb",
|
50
|
+
"spec/model_builder.rb",
|
44
51
|
"spec/models.rb",
|
45
52
|
"spec/spec_helper.rb"
|
46
53
|
]
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe 'allow_values_for' do
|
4
|
+
include ModelBuilder
|
5
|
+
|
6
|
+
# Defines a model, create a validation and returns a raw matcher
|
7
|
+
def define_and_validate(options={})
|
8
|
+
@model = define_model :product do
|
9
|
+
include MongoMapper::Document
|
10
|
+
|
11
|
+
key :title, String
|
12
|
+
key :category, String
|
13
|
+
|
14
|
+
validates_format_of :title, options
|
15
|
+
end
|
16
|
+
|
17
|
+
allow_values_for(:title)
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'messages' do
|
21
|
+
before(:each){ @matcher = define_and_validate(:with => /X|Y|Z/) }
|
22
|
+
|
23
|
+
it 'should contain a description' do
|
24
|
+
@matcher = allow_values_for(:title, "X", "Y", "Z")
|
25
|
+
@matcher.description.should == 'allow "X", "Y", and "Z" as values for title'
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should set is_valid? message' do
|
29
|
+
@matcher.in("A").matches?(subject)
|
30
|
+
@matcher.failure_message.should == 'Expected Product to be valid when title is set to "A"'
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should set allow_nil? message' do
|
34
|
+
@matcher.allow_nil.matches?(subject)
|
35
|
+
@matcher.failure_message.should == 'Expected Product to allow nil values for title'
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should set allow_blank? message' do
|
39
|
+
@matcher.allow_blank.matches?(subject)
|
40
|
+
@matcher.failure_message.should == 'Expected Product to allow blank values for title'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe 'matchers' do
|
45
|
+
it { should define_and_validate(:with => /X|Y|Z/).in('X', 'Y', 'Z') }
|
46
|
+
it { should_not define_and_validate(:with => /X|Y|Z/).in('A') }
|
47
|
+
|
48
|
+
it { should define_and_validate(:with => /X|Y|Z/, :message => 'valid').in('X', 'Y', 'Z').message('valid') }
|
49
|
+
|
50
|
+
create_optional_boolean_specs(:allow_nil, self, :with => /X|Y|Z/)
|
51
|
+
create_optional_boolean_specs(:allow_blank, self, :with => /X|Y|Z/)
|
52
|
+
end
|
53
|
+
|
54
|
+
describe 'macros' do
|
55
|
+
before(:each){ define_and_validate(:with => /X|Y|Z/) }
|
56
|
+
|
57
|
+
should_allow_values_for :title, 'X'
|
58
|
+
should_not_allow_values_for :title, 'A'
|
59
|
+
end
|
60
|
+
|
61
|
+
describe 'failures' do
|
62
|
+
it "should fail if any of the values are valid on invalid cases" do
|
63
|
+
define_and_validate(:with => /X|Y|Z/)
|
64
|
+
|
65
|
+
lambda {
|
66
|
+
should_not allow_values_for(:title, 'A', 'X', 'B')
|
67
|
+
}.should raise_error(Spec::Expectations::ExpectationNotMetError, /Did not expect Product to be valid/)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
@@ -9,7 +9,7 @@ describe 'have_key' do
|
|
9
9
|
|
10
10
|
it 'should contain a description' do
|
11
11
|
matcher = have_key(:title, String)
|
12
|
-
matcher.description.should == 'have key(s) title'
|
12
|
+
matcher.description.should == 'have key(s) title with type String'
|
13
13
|
end
|
14
14
|
|
15
15
|
it 'should set has_key? message' do
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# This is based on Shoulda model builder for Test::Unit.
|
2
|
+
#
|
3
|
+
module ModelBuilder
|
4
|
+
def self.included(base)
|
5
|
+
return unless base.name =~ /^Spec/
|
6
|
+
|
7
|
+
base.class_eval do
|
8
|
+
after(:each) do
|
9
|
+
if @defined_constants
|
10
|
+
@defined_constants.each do |class_name|
|
11
|
+
Object.send(:remove_const, class_name)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
base.extend ClassMethods
|
18
|
+
end
|
19
|
+
|
20
|
+
def define_constant(class_name, &block)
|
21
|
+
class_name = class_name.to_s.camelize
|
22
|
+
|
23
|
+
klass = Class.new
|
24
|
+
Object.const_set(class_name, klass)
|
25
|
+
|
26
|
+
klass.class_eval(&block) if block_given?
|
27
|
+
|
28
|
+
@defined_constants ||= []
|
29
|
+
@defined_constants << class_name
|
30
|
+
|
31
|
+
klass
|
32
|
+
end
|
33
|
+
|
34
|
+
def define_model(name, columns = {}, &block)
|
35
|
+
instance = define_constant(name.to_s.classify, &block).new
|
36
|
+
|
37
|
+
self.class.subject { instance } if self.class.respond_to?(:subject)
|
38
|
+
instance
|
39
|
+
end
|
40
|
+
|
41
|
+
module ClassMethods
|
42
|
+
# This is a macro to run validations of boolean optionals such as :allow_nil
|
43
|
+
# and :allow_blank. This macro tests all scenarios. The specs must have a
|
44
|
+
# define_and_validate method defined.
|
45
|
+
#
|
46
|
+
def create_optional_boolean_specs(optional, base, options={})
|
47
|
+
base.describe "with #{optional} option" do
|
48
|
+
it { should define_and_validate(options.merge(optional => true)).send(optional) }
|
49
|
+
it { should define_and_validate(options.merge(optional => false)).send(optional, false) }
|
50
|
+
it { should_not define_and_validate(options.merge(optional => true)).send(optional, false) }
|
51
|
+
it { should_not define_and_validate(options.merge(optional => false)).send(optional) }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def create_message_specs(base)
|
56
|
+
base.describe "with message option" do
|
57
|
+
it { should define_and_validate(:message => 'valid_message').message('valid_message') }
|
58
|
+
it { should_not define_and_validate(:message => 'not_valid').message('valid_message') }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
data/spec/models.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require "rubygems"
|
2
2
|
|
3
|
-
gem "mongomapper", "~> 0.
|
3
|
+
gem "mongomapper", "~> 0.3.1"
|
4
4
|
require "mongomapper"
|
5
5
|
|
6
6
|
MongoMapper.database = "remarkable_mongomapper"
|
@@ -15,4 +15,5 @@ Spec::Runner.configure do |config|
|
|
15
15
|
end
|
16
16
|
|
17
17
|
require File.join(File.dirname(__FILE__), "..", "lib", "remarkable_mongomapper")
|
18
|
-
require File.join(File.dirname(__FILE__), "models")
|
18
|
+
require File.join(File.dirname(__FILE__), "models")
|
19
|
+
require File.join(File.dirname(__FILE__), "model_builder")
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yeastymobs-remarkable_mongomapper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- "Nicolas M\xC3\xA9rouze"
|
@@ -11,7 +11,7 @@ autorequire:
|
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
13
|
|
14
|
-
date: 2009-07-
|
14
|
+
date: 2009-07-31 00:00:00 -07:00
|
15
15
|
default_executable:
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
@@ -51,14 +51,19 @@ files:
|
|
51
51
|
- VERSION
|
52
52
|
- lib/remarkable_mongomapper.rb
|
53
53
|
- lib/remarkable_mongomapper/base.rb
|
54
|
+
- lib/remarkable_mongomapper/describe.rb
|
55
|
+
- lib/remarkable_mongomapper/human_names.rb
|
56
|
+
- lib/remarkable_mongomapper/matchers/allow_values_for_matcher.rb
|
54
57
|
- lib/remarkable_mongomapper/matchers/association_matcher.rb
|
55
58
|
- lib/remarkable_mongomapper/matchers/have_key_matcher.rb
|
56
59
|
- lib/remarkable_mongomapper/matchers/validate_presence_of_matcher.rb
|
57
60
|
- locales/en.yml
|
58
61
|
- remarkable_mongomapper.gemspec
|
62
|
+
- spec/matchers/allow_values_for_matcher_spec.rb
|
59
63
|
- spec/matchers/association_matcher_spec.rb
|
60
64
|
- spec/matchers/have_key_matcher_spec.rb
|
61
65
|
- spec/matchers/validate_presence_of_matcher_spec.rb
|
66
|
+
- spec/model_builder.rb
|
62
67
|
- spec/models.rb
|
63
68
|
- spec/spec.opts
|
64
69
|
- spec/spec_helper.rb
|
@@ -90,8 +95,10 @@ signing_key:
|
|
90
95
|
specification_version: 3
|
91
96
|
summary: MongoMapper Remarkable Matchers
|
92
97
|
test_files:
|
98
|
+
- spec/matchers/allow_values_for_matcher_spec.rb
|
93
99
|
- spec/matchers/association_matcher_spec.rb
|
94
100
|
- spec/matchers/have_key_matcher_spec.rb
|
95
101
|
- spec/matchers/validate_presence_of_matcher_spec.rb
|
102
|
+
- spec/model_builder.rb
|
96
103
|
- spec/models.rb
|
97
104
|
- spec/spec_helper.rb
|