yeastymobs-remarkable_mongomapper 0.0.1 → 0.1.0
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/README.md +23 -1
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/remarkable_mongomapper/base.rb +219 -0
- data/lib/remarkable_mongomapper/matchers/association_matcher.rb +105 -0
- data/lib/remarkable_mongomapper/matchers/have_key_matcher.rb +10 -15
- data/lib/remarkable_mongomapper/matchers/validate_presence_of_matcher.rb +5 -4
- data/locales/en.yml +14 -4
- data/remarkable_mongomapper.gemspec +9 -6
- data/spec/matchers/association_matcher_spec.rb +104 -0
- data/spec/matchers/have_key_matcher_spec.rb +6 -6
- data/spec/models.rb +36 -0
- data/spec/spec_helper.rb +1 -1
- metadata +6 -3
data/README.md
CHANGED
@@ -1 +1,23 @@
|
|
1
|
-
Remarkable
|
1
|
+
# Remarkable MongoMapper
|
2
|
+
|
3
|
+
Remarkable matchers for [MongoMapper](http://github.com/jnunemaker/mongomapper).
|
4
|
+
|
5
|
+
## Matchers
|
6
|
+
|
7
|
+
<pre><code>
|
8
|
+
it { should have_key(:name, String) }
|
9
|
+
it { should have_keys(:name, :phone_number, String) }
|
10
|
+
it { should validate_presence_of(:name, :phone_number, :message => "not there!") }
|
11
|
+
it { should belong_to(:user, :class_name => 'Person') }
|
12
|
+
it { should have_many(:users, :class_name => 'Person', :polymorphic => true) }
|
13
|
+
</code></pre>
|
14
|
+
|
15
|
+
## Contributions
|
16
|
+
|
17
|
+
It is far from complete! It'd be very helpful to have some help.
|
18
|
+
|
19
|
+
## Contributors
|
20
|
+
|
21
|
+
* Nicolas Mérouze
|
22
|
+
* Mathieu Fosse
|
23
|
+
* Vincent Hellot
|
data/Rakefile
CHANGED
@@ -11,7 +11,7 @@ begin
|
|
11
11
|
gem.authors = ["Nicolas Mérouze", "Vincent Hellot", "Mathieu Fosse"]
|
12
12
|
|
13
13
|
gem.add_dependency('remarkable', '~> 3.1.8')
|
14
|
-
gem.add_dependency('mongomapper', '~> 0.
|
14
|
+
gem.add_dependency('mongomapper', '~> 0.3.1')
|
15
15
|
end
|
16
16
|
rescue LoadError
|
17
17
|
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0
|
@@ -1,6 +1,225 @@
|
|
1
1
|
module Remarkable
|
2
2
|
module MongoMapper
|
3
3
|
class Base < Remarkable::Base
|
4
|
+
I18N_COLLECTION = [ :attributes, :associations ]
|
5
|
+
|
6
|
+
# Provides a way to send options to all MongoMapper matchers.
|
7
|
+
#
|
8
|
+
# validates_presence_of(:name).with_options(:allow_nil => false)
|
9
|
+
#
|
10
|
+
# Is equivalent to:
|
11
|
+
#
|
12
|
+
# validates_presence_of(:name, :allow_nil => false)
|
13
|
+
#
|
14
|
+
def with_options(opts={})
|
15
|
+
@options.merge!(opts)
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
# Checks for the given key in @options, if it exists and it's true,
|
22
|
+
# tests that the value is bad, otherwise tests that the value is good.
|
23
|
+
#
|
24
|
+
# It accepts the key to check for, the value that is used for testing
|
25
|
+
# and an @options key where the message to search for is.
|
26
|
+
#
|
27
|
+
def assert_bad_or_good_if_key(key, value, message_key=:message) #:nodoc:
|
28
|
+
return positive? unless @options.key?(key)
|
29
|
+
|
30
|
+
if @options[key]
|
31
|
+
return bad?(value, message_key), :not => not_word
|
32
|
+
else
|
33
|
+
return good?(value, message_key), :not => ''
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Checks for the given key in @options, if it exists and it's true,
|
38
|
+
# tests that the value is good, otherwise tests that the value is bad.
|
39
|
+
#
|
40
|
+
# It accepts the key to check for, the value that is used for testing
|
41
|
+
# and an @options key where the message to search for is.
|
42
|
+
#
|
43
|
+
def assert_good_or_bad_if_key(key, value, message_key=:message) #:nodoc:
|
44
|
+
return positive? unless @options.key?(key)
|
45
|
+
|
46
|
+
if @options[key]
|
47
|
+
return good?(value, message_key), :not => ''
|
48
|
+
else
|
49
|
+
return bad?(value, message_key), :not => not_word
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Default allow_nil? validation. It accepts the message_key which is
|
54
|
+
# the key which contain the message in @options.
|
55
|
+
#
|
56
|
+
# It also gets an allow_nil message on remarkable.mongo_mapper.allow_nil
|
57
|
+
# to be used as default.
|
58
|
+
#
|
59
|
+
def allow_nil?(message_key=:message) #:nodoc:
|
60
|
+
assert_good_or_bad_if_key(:allow_nil, nil, message_key)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Default allow_blank? validation. It accepts the message_key which is
|
64
|
+
# the key which contain the message in @options.
|
65
|
+
#
|
66
|
+
# It also gets an allow_blank message on remarkable.mongo_mapper.allow_blank
|
67
|
+
# to be used as default.
|
68
|
+
#
|
69
|
+
def allow_blank?(message_key=:message) #:nodoc:
|
70
|
+
assert_good_or_bad_if_key(:allow_blank, '', message_key)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Shortcut for assert_good_value.
|
74
|
+
#
|
75
|
+
def good?(value, message_sym=:message) #:nodoc:
|
76
|
+
assert_good_value(@subject, @attribute, value, @options[message_sym])
|
77
|
+
end
|
78
|
+
|
79
|
+
# Shortcut for assert_bad_value.
|
80
|
+
#
|
81
|
+
def bad?(value, message_sym=:message) #:nodoc:
|
82
|
+
assert_bad_value(@subject, @attribute, value, @options[message_sym])
|
83
|
+
end
|
84
|
+
|
85
|
+
# Asserts that an MongoMapper model validates with the passed
|
86
|
+
# <tt>value</tt> by making sure the <tt>error_message_to_avoid</tt> is not
|
87
|
+
# contained within the list of errors for that attribute.
|
88
|
+
#
|
89
|
+
# assert_good_value(User.new, :email, "user@example.com")
|
90
|
+
# assert_good_value(User.new, :ssn, "123456789", /length/)
|
91
|
+
#
|
92
|
+
# If a class is passed as the first argument, a new object will be
|
93
|
+
# instantiated before the assertion. If an instance variable exists with
|
94
|
+
# the same name as the class (underscored), that object will be used
|
95
|
+
# instead.
|
96
|
+
#
|
97
|
+
# assert_good_value(User, :email, "user@example.com")
|
98
|
+
#
|
99
|
+
# @product = Product.new(:tangible => false)
|
100
|
+
# assert_good_value(Product, :price, "0")
|
101
|
+
#
|
102
|
+
def assert_good_value(model, attribute, value, error_message_to_avoid=//) # :nodoc:
|
103
|
+
model.send("#{attribute}=", value)
|
104
|
+
|
105
|
+
return true if model.valid?
|
106
|
+
|
107
|
+
# FIXME
|
108
|
+
error_message_to_avoid = error_message_from_model(model, attribute, error_message_to_avoid)
|
109
|
+
assert_does_not_contain(model.errors.on(attribute), error_message_to_avoid)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Asserts that an MongoMapper model invalidates the passed
|
113
|
+
# <tt>value</tt> by making sure the <tt>error_message_to_expect</tt> is
|
114
|
+
# contained within the list of errors for that attribute.
|
115
|
+
#
|
116
|
+
# assert_bad_value(User.new, :email, "invalid")
|
117
|
+
# assert_bad_value(User.new, :ssn, "123", /length/)
|
118
|
+
#
|
119
|
+
# If a class is passed as the first argument, a new object will be
|
120
|
+
# instantiated before the assertion. If an instance variable exists with
|
121
|
+
# the same name as the class (underscored), that object will be used
|
122
|
+
# instead.
|
123
|
+
#
|
124
|
+
# assert_bad_value(User, :email, "invalid")
|
125
|
+
#
|
126
|
+
# @product = Product.new(:tangible => true)
|
127
|
+
# assert_bad_value(Product, :price, "0")
|
128
|
+
#
|
129
|
+
def assert_bad_value(model, attribute, value, error_message_to_expect=:invalid) #:nodoc:
|
130
|
+
model.send("#{attribute}=", value)
|
131
|
+
|
132
|
+
return false if model.valid? || model.errors.on(attribute).blank?
|
133
|
+
|
134
|
+
# FIXME
|
135
|
+
error_message_to_expect = error_message_from_model(model, attribute, error_message_to_expect)
|
136
|
+
assert_contains(model.errors.on(attribute), error_message_to_expect)
|
137
|
+
end
|
138
|
+
|
139
|
+
# Return the error message to be checked. If the message is not a Symbol
|
140
|
+
# neither a Hash, it returns the own message.
|
141
|
+
#
|
142
|
+
# But the nice thing is that when the message is a Symbol we get the error
|
143
|
+
# messsage from within the model, using already existent structure inside
|
144
|
+
# MongoMapper.
|
145
|
+
#
|
146
|
+
# This allows a couple things from the user side:
|
147
|
+
#
|
148
|
+
# 1. Specify symbols in their tests:
|
149
|
+
#
|
150
|
+
# should_allow_values_for(:shirt_size, 'S', 'M', 'L', :message => :inclusion)
|
151
|
+
#
|
152
|
+
# As we know, allow_values_for searches for a :invalid message. So if we
|
153
|
+
# were testing a validates_inclusion_of with allow_values_for, previously
|
154
|
+
# we had to do something like this:
|
155
|
+
#
|
156
|
+
# should_allow_values_for(:shirt_size, 'S', 'M', 'L', :message => 'not included in list')
|
157
|
+
#
|
158
|
+
# Now everything gets resumed to a Symbol.
|
159
|
+
#
|
160
|
+
# 2. Do not worry with specs if their are using I18n API properly.
|
161
|
+
#
|
162
|
+
# As we know, I18n API provides several interpolation options besides
|
163
|
+
# fallback when creating error messages. If the user changed the message,
|
164
|
+
# macros would start to pass when they shouldn't.
|
165
|
+
#
|
166
|
+
# Using the underlying mechanism inside ActiveRecord makes us free from
|
167
|
+
# all thos errors.
|
168
|
+
#
|
169
|
+
# We replace {{count}} interpolation for 12345 which later is replaced
|
170
|
+
# by a regexp which contains \d+.
|
171
|
+
#
|
172
|
+
def error_message_from_model(model, attribute, message) #:nodoc:
|
173
|
+
# FIXME
|
174
|
+
message
|
175
|
+
end
|
176
|
+
|
177
|
+
# Asserts that the given collection does not contain item x. If x is a
|
178
|
+
# regular expression, ensure that none of the elements from the collection
|
179
|
+
# match x.
|
180
|
+
#
|
181
|
+
def assert_does_not_contain(collection, x) #:nodoc:
|
182
|
+
!assert_contains(collection, x)
|
183
|
+
end
|
184
|
+
|
185
|
+
# Changes how collection are interpolated to provide localized names
|
186
|
+
# whenever is possible.
|
187
|
+
#
|
188
|
+
def collection_interpolation #:nodoc:
|
189
|
+
described_class = if @subject
|
190
|
+
subject_class
|
191
|
+
elsif @spec
|
192
|
+
@spec.send(:described_class)
|
193
|
+
end
|
194
|
+
|
195
|
+
if i18n_collection? && described_class.respond_to?(:human_attribute_name)
|
196
|
+
options = {}
|
197
|
+
|
198
|
+
collection_name = self.class.matcher_arguments[:collection].to_sym
|
199
|
+
if collection = instance_variable_get("@#{collection_name}")
|
200
|
+
collection = collection.map do |attr|
|
201
|
+
described_class.human_attribute_name(attr.to_s, :locale => Remarkable.locale).downcase
|
202
|
+
end
|
203
|
+
options[collection_name] = array_to_sentence(collection)
|
204
|
+
end
|
205
|
+
|
206
|
+
object_name = self.class.matcher_arguments[:as]
|
207
|
+
if object = instance_variable_get("@#{object_name}")
|
208
|
+
object = described_class.human_attribute_name(object.to_s, :locale => Remarkable.locale).downcase
|
209
|
+
options[object_name] = object
|
210
|
+
end
|
211
|
+
|
212
|
+
options
|
213
|
+
else
|
214
|
+
super
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
# Returns true if the given collection should be translated.
|
219
|
+
#
|
220
|
+
def i18n_collection? #:nodoc:
|
221
|
+
RAILS_I18N && I18N_COLLECTION.include?(self.class.matcher_arguments[:collection])
|
222
|
+
end
|
4
223
|
end
|
5
224
|
end
|
6
225
|
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module Remarkable
|
2
|
+
module MongoMapper
|
3
|
+
module Matchers
|
4
|
+
class AssociationMatcher < Remarkable::MongoMapper::Base
|
5
|
+
arguments :type, :collection => :associations, :as => :association
|
6
|
+
|
7
|
+
optionals :class_name
|
8
|
+
|
9
|
+
collection_assertions :association_exists?, :type_matches?, :klass_exists?, :options_match?
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
def association_exists?
|
14
|
+
reflection
|
15
|
+
end
|
16
|
+
|
17
|
+
def type_matches?
|
18
|
+
reflection.type == @type
|
19
|
+
end
|
20
|
+
|
21
|
+
def klass_exists?
|
22
|
+
return true if @options[:polymorphic]
|
23
|
+
reflection.klass rescue nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def options_match?
|
27
|
+
actual_options = {}
|
28
|
+
|
29
|
+
@options.keys.each do |key|
|
30
|
+
method = :"reflection_#{key}"
|
31
|
+
|
32
|
+
@options[key] = @options[key].to_s
|
33
|
+
actual_options[key] = (respond_to?(method, true) ? send(method) : reflection.options[key]).to_s
|
34
|
+
end
|
35
|
+
|
36
|
+
return @options == actual_options, :actual => actual_options.inspect
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def reflection
|
42
|
+
@reflection ||= subject_class.associations[@association]
|
43
|
+
end
|
44
|
+
|
45
|
+
def interpolation_options
|
46
|
+
options = {}
|
47
|
+
options[:type] = Remarkable.t(@type, :scope => matcher_i18n_scope, :default => @type.to_s.gsub("_", ""))
|
48
|
+
options[:options] = @options.inspect
|
49
|
+
|
50
|
+
if @subject && reflection
|
51
|
+
options.merge!(
|
52
|
+
:actual_type => Remarkable.t(reflection.type, :scope => matcher_i18n_scope, :default => reflection.type.to_s)
|
53
|
+
)
|
54
|
+
end
|
55
|
+
|
56
|
+
options
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
# Ensures that the many relationship exists. Will also test that the
|
62
|
+
# associated table has the required columns.
|
63
|
+
#
|
64
|
+
# == Options
|
65
|
+
#
|
66
|
+
# * <tt>:class_name</tt> - the expected associted class name.
|
67
|
+
# * <tt>:polymorphic</tt> - if the association should be polymorphic or not.
|
68
|
+
# When true it also checks for the association_type column in the subject table.
|
69
|
+
#
|
70
|
+
# == Examples
|
71
|
+
#
|
72
|
+
# should_have_many :addresses
|
73
|
+
# should_have_many :users, :class_name => 'Person'
|
74
|
+
#
|
75
|
+
# it { should have_many(:addresses) }
|
76
|
+
# it { should have_many(:users, :class_name => 'Person') }
|
77
|
+
#
|
78
|
+
def have_many(*associations, &block)
|
79
|
+
AssociationMatcher.new(:many, *associations, &block).spec(self)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Ensures that the many relationship exists. Will also test that the
|
83
|
+
# associated table has the required columns.
|
84
|
+
#
|
85
|
+
# == Options
|
86
|
+
#
|
87
|
+
# * <tt>:class_name</tt> - the expected associted class name.
|
88
|
+
# * <tt>:polymorphic</tt> - if the association should be polymorphic or not.
|
89
|
+
# When true it also checks for the association_type column in the subject table.
|
90
|
+
#
|
91
|
+
# == Examples
|
92
|
+
#
|
93
|
+
# should_belong_to :user
|
94
|
+
# should_belong_to :user, :class_name => 'Person'
|
95
|
+
#
|
96
|
+
# it { should belong_to(:user) }
|
97
|
+
# it { should belong_to(:user, :class_name => 'Person') }
|
98
|
+
#
|
99
|
+
def belong_to(*associations, &block)
|
100
|
+
AssociationMatcher.new(:belongs_to, *associations, &block).spec(self)
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -1,24 +1,20 @@
|
|
1
1
|
module Remarkable
|
2
2
|
module MongoMapper
|
3
3
|
module Matchers
|
4
|
-
class HaveKeyMatcher < Remarkable::MongoMapper::Base
|
4
|
+
class HaveKeyMatcher < Remarkable::MongoMapper::Base
|
5
5
|
|
6
|
-
arguments :collection => :
|
7
|
-
|
8
|
-
optional :type
|
9
|
-
|
10
|
-
default_options :type => nil
|
6
|
+
arguments :type, :collection => :attributes, :as => :attribute
|
11
7
|
|
12
8
|
collection_assertions :has_key?
|
13
9
|
|
14
|
-
before_assert do
|
15
|
-
|
16
|
-
end
|
10
|
+
# before_assert do
|
11
|
+
# @type = @options[:type]
|
12
|
+
# end
|
17
13
|
|
18
14
|
protected
|
19
15
|
|
20
16
|
def has_key?
|
21
|
-
@subject.
|
17
|
+
@subject.respond_to?(@attribute) && @subject.class.keys[@attribute] == ::MongoMapper::Key.new(@attribute, @type)
|
22
18
|
end
|
23
19
|
|
24
20
|
end
|
@@ -27,14 +23,13 @@ module Remarkable
|
|
27
23
|
#
|
28
24
|
# == Examples
|
29
25
|
#
|
30
|
-
#
|
26
|
+
# should_have_key :name, String
|
31
27
|
#
|
32
|
-
# it { should
|
33
|
-
# it { should
|
34
|
-
# it { should have_column(:name).type(String) }
|
28
|
+
# it { should have_key(:name, String) }
|
29
|
+
# it { should have_keys(:name, :phone_number, String) }
|
35
30
|
#
|
36
31
|
def have_key(*args, &block)
|
37
|
-
HaveKeyMatcher.new(*args, &block).spec(self)
|
32
|
+
HaveKeyMatcher.new(args.pop, *args, &block).spec(self)
|
38
33
|
end
|
39
34
|
alias :have_keys :have_key
|
40
35
|
|
@@ -1,17 +1,18 @@
|
|
1
1
|
module Remarkable
|
2
2
|
module MongoMapper
|
3
3
|
module Matchers
|
4
|
-
class ValidatePresenceOfMatcher < Remarkable::MongoMapper::Base
|
4
|
+
class ValidatePresenceOfMatcher < Remarkable::MongoMapper::Base
|
5
5
|
|
6
|
-
arguments :collection => :
|
6
|
+
arguments :collection => :attributes, :as => :attribute
|
7
|
+
optional :message
|
7
8
|
|
8
9
|
collection_assertions :allow_nil?
|
10
|
+
default_options :message => "can't be empty"
|
9
11
|
|
10
12
|
protected
|
11
13
|
|
12
14
|
def allow_nil?
|
13
|
-
|
14
|
-
!@subject.valid? && !@subject.errors.on(@key).blank?
|
15
|
+
bad?(nil, :message)
|
15
16
|
end
|
16
17
|
|
17
18
|
end
|
data/locales/en.yml
CHANGED
@@ -1,12 +1,22 @@
|
|
1
1
|
en:
|
2
2
|
remarkable:
|
3
3
|
mongo_mapper:
|
4
|
+
association:
|
5
|
+
many: have many
|
6
|
+
belongs_to: belong to
|
7
|
+
description: "{{type}} {{associations}}"
|
8
|
+
expectations:
|
9
|
+
association_exists: "{{subject_name}} records {{type}} {{association}}, but the association does not exist"
|
10
|
+
type_matches: "{{subject_name}} records {{type}} {{association}}, got {{subject_name}} records {{actual_type}} {{association}}"
|
11
|
+
klass_exists: "{{subject_name}} records {{type}} {{association}}, but the association class does not exist"
|
12
|
+
options_match: "{{subject_name}} records {{type}} {{association}} with options {{options}}, got {{actual}}"
|
13
|
+
|
4
14
|
have_key:
|
5
|
-
description: "have key(s) {{
|
15
|
+
description: "have key(s) {{attributes}}"
|
6
16
|
expectations:
|
7
|
-
has_key: "{{subject_name}} to have key named {{
|
17
|
+
has_key: "{{subject_name}} to have key named {{attribute}} with type {{type}}"
|
8
18
|
|
9
19
|
validate_presence_of:
|
10
|
-
description: "require {{
|
20
|
+
description: "require {{attributes}} to be set"
|
11
21
|
expectations:
|
12
|
-
allow_nil: "{{subject_name}} to require {{
|
22
|
+
allow_nil: "{{subject_name}} to require {{attribute}} to be set"
|
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{remarkable_mongomapper}
|
5
|
-
s.version = "0.0
|
5
|
+
s.version = "0.1.0"
|
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-29}
|
10
10
|
s.email = %q{dev@yeastymobs.com}
|
11
11
|
s.extra_rdoc_files = [
|
12
12
|
"LICENSE",
|
@@ -20,10 +20,12 @@ 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/matchers/association_matcher.rb",
|
23
24
|
"lib/remarkable_mongomapper/matchers/have_key_matcher.rb",
|
24
25
|
"lib/remarkable_mongomapper/matchers/validate_presence_of_matcher.rb",
|
25
26
|
"locales/en.yml",
|
26
27
|
"remarkable_mongomapper.gemspec",
|
28
|
+
"spec/matchers/association_matcher_spec.rb",
|
27
29
|
"spec/matchers/have_key_matcher_spec.rb",
|
28
30
|
"spec/matchers/validate_presence_of_matcher_spec.rb",
|
29
31
|
"spec/models.rb",
|
@@ -36,7 +38,8 @@ Gem::Specification.new do |s|
|
|
36
38
|
s.rubygems_version = %q{1.3.5}
|
37
39
|
s.summary = %q{MongoMapper Remarkable Matchers}
|
38
40
|
s.test_files = [
|
39
|
-
"spec/matchers/
|
41
|
+
"spec/matchers/association_matcher_spec.rb",
|
42
|
+
"spec/matchers/have_key_matcher_spec.rb",
|
40
43
|
"spec/matchers/validate_presence_of_matcher_spec.rb",
|
41
44
|
"spec/models.rb",
|
42
45
|
"spec/spec_helper.rb"
|
@@ -48,13 +51,13 @@ Gem::Specification.new do |s|
|
|
48
51
|
|
49
52
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
50
53
|
s.add_runtime_dependency(%q<remarkable>, ["~> 3.1.8"])
|
51
|
-
s.add_runtime_dependency(%q<mongomapper>, ["~> 0.
|
54
|
+
s.add_runtime_dependency(%q<mongomapper>, ["~> 0.3.1"])
|
52
55
|
else
|
53
56
|
s.add_dependency(%q<remarkable>, ["~> 3.1.8"])
|
54
|
-
s.add_dependency(%q<mongomapper>, ["~> 0.
|
57
|
+
s.add_dependency(%q<mongomapper>, ["~> 0.3.1"])
|
55
58
|
end
|
56
59
|
else
|
57
60
|
s.add_dependency(%q<remarkable>, ["~> 3.1.8"])
|
58
|
-
s.add_dependency(%q<mongomapper>, ["~> 0.
|
61
|
+
s.add_dependency(%q<mongomapper>, ["~> 0.3.1"])
|
59
62
|
end
|
60
63
|
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe 'association_matcher' do
|
4
|
+
subject do
|
5
|
+
Article.new
|
6
|
+
end
|
7
|
+
|
8
|
+
describe 'have_many' do
|
9
|
+
|
10
|
+
describe 'messages' do
|
11
|
+
it 'should contain a description' do
|
12
|
+
matcher = have_many(:comments)
|
13
|
+
matcher.description.should == 'have many comments'
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should set association_exists? message' do
|
17
|
+
matcher = have_many(:whatever)
|
18
|
+
matcher.matches?(subject)
|
19
|
+
matcher.failure_message.should == 'Expected Article records have many whatever, but the association does not exist'
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should set type_matches? message' do
|
23
|
+
matcher = belong_to(:comments)
|
24
|
+
matcher.matches?(subject)
|
25
|
+
matcher.failure_message.should == 'Expected Article records belong to comments, got Article records have many comments'
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should set klass_exists? message' do
|
29
|
+
matcher = have_many(:unknowns)
|
30
|
+
matcher.matches?(subject)
|
31
|
+
matcher.failure_message.should == 'Expected Article records have many unknowns, but the association class does not exist'
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should set options_matches? message when :class_name is given' do
|
35
|
+
matcher = have_many(:ratings, :class_name => 'Rating')
|
36
|
+
matcher.matches?(subject)
|
37
|
+
matcher.failure_message.should == 'Expected Article records have many ratings with options {:class_name=>"Rating"}, got {:class_name=>"Rate"}'
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should set options_matches? message when :polymorphic is given' do
|
41
|
+
matcher = have_many(:assets, :polymorphic => true)
|
42
|
+
matcher.matches?(subject)
|
43
|
+
matcher.failure_message.should == 'Expected Article records have many assets with options {:polymorphic=>"true"}, got {:polymorphic=>""}'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'matchers' do
|
48
|
+
it { should have_many(:comments) }
|
49
|
+
it { should_not belong_to(:comment) }
|
50
|
+
end
|
51
|
+
|
52
|
+
describe 'macros' do
|
53
|
+
should_have_many :comments
|
54
|
+
should_not_belong_to :comment
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
describe 'belong_to' do
|
60
|
+
|
61
|
+
describe 'messages' do
|
62
|
+
it 'should contain a description' do
|
63
|
+
matcher = belong_to(:user)
|
64
|
+
matcher.description.should == 'belong to user'
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should set association_exists? message' do
|
68
|
+
matcher = belong_to(:whatever)
|
69
|
+
matcher.matches?(subject)
|
70
|
+
matcher.failure_message.should == 'Expected Article records belong to whatever, but the association does not exist'
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should set type_matches? message' do
|
74
|
+
matcher = have_many(:user)
|
75
|
+
matcher.matches?(subject)
|
76
|
+
matcher.failure_message.should == 'Expected Article records have many user, got Article records belong to user'
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should set klass_exists? message' do
|
80
|
+
matcher = belong_to(:unknown)
|
81
|
+
matcher.matches?(subject)
|
82
|
+
matcher.failure_message.should == 'Expected Article records belong to unknown, but the association class does not exist'
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should set options_matches? message when :class_name is given' do
|
86
|
+
matcher = belong_to(:site, :class_name => 'Website')
|
87
|
+
matcher.matches?(subject)
|
88
|
+
matcher.failure_message.should == 'Expected Article records belong to site with options {:class_name=>"Website"}, got {:class_name=>"Site"}'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe 'matchers' do
|
93
|
+
it { should belong_to(:user) }
|
94
|
+
it { should_not have_many(:users) }
|
95
|
+
end
|
96
|
+
|
97
|
+
describe 'macros' do
|
98
|
+
should_belong_to :user
|
99
|
+
should_not_have_many :users
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
@@ -8,12 +8,12 @@ describe 'have_key' do
|
|
8
8
|
describe 'messages' do
|
9
9
|
|
10
10
|
it 'should contain a description' do
|
11
|
-
matcher = have_key(:title,
|
11
|
+
matcher = have_key(:title, String)
|
12
12
|
matcher.description.should == 'have key(s) title'
|
13
13
|
end
|
14
14
|
|
15
15
|
it 'should set has_key? message' do
|
16
|
-
matcher = have_key(:owner,
|
16
|
+
matcher = have_key(:owner, String)
|
17
17
|
matcher.matches?(subject)
|
18
18
|
matcher.failure_message.should == 'Expected Article to have key named owner with type String'
|
19
19
|
end
|
@@ -21,12 +21,12 @@ describe 'have_key' do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
describe 'matchers' do
|
24
|
-
it { should have_key(:title,
|
25
|
-
it { should have_keys(:title, :body,
|
24
|
+
it { should have_key(:title, String) }
|
25
|
+
it { should have_keys(:title, :body, String) }
|
26
26
|
end
|
27
27
|
|
28
28
|
describe 'macros' do
|
29
|
-
should_have_key :title,
|
30
|
-
should_have_keys :title, :body,
|
29
|
+
should_have_key :title, String
|
30
|
+
should_have_keys :title, :body, String
|
31
31
|
end
|
32
32
|
end
|
data/spec/models.rb
CHANGED
@@ -3,4 +3,40 @@ class Article
|
|
3
3
|
|
4
4
|
key :title, String, :required => true
|
5
5
|
key :body, String
|
6
|
+
|
7
|
+
many :comments
|
8
|
+
many :unknowns
|
9
|
+
many :ratings, :class_name => "Rate"
|
10
|
+
many :assets
|
11
|
+
belongs_to :user
|
12
|
+
belongs_to :unknown
|
13
|
+
belongs_to :site, :class_name => 'Site'
|
14
|
+
end
|
15
|
+
|
16
|
+
class Comment
|
17
|
+
include MongoMapper::EmbeddedDocument
|
18
|
+
|
19
|
+
key :body, String
|
20
|
+
end
|
21
|
+
|
22
|
+
class User
|
23
|
+
include MongoMapper::Document
|
24
|
+
|
25
|
+
key :login, String
|
26
|
+
end
|
27
|
+
|
28
|
+
class Rate
|
29
|
+
include MongoMapper::EmbeddedDocument
|
30
|
+
end
|
31
|
+
|
32
|
+
class Rating
|
33
|
+
include MongoMapper::EmbeddedDocument
|
34
|
+
end
|
35
|
+
|
36
|
+
class Site
|
37
|
+
include MongoMapper::EmbeddedDocument
|
38
|
+
end
|
39
|
+
|
40
|
+
class Webiste
|
41
|
+
include MongoMapper::EmbeddedDocument
|
6
42
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -11,7 +11,7 @@ end
|
|
11
11
|
|
12
12
|
Spec::Runner.configure do |config|
|
13
13
|
config.before(:all) { reset_test_db! }
|
14
|
-
config.after(:all)
|
14
|
+
config.after(:all) { reset_test_db! }
|
15
15
|
end
|
16
16
|
|
17
17
|
require File.join(File.dirname(__FILE__), "..", "lib", "remarkable_mongomapper")
|
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.0
|
4
|
+
version: 0.1.0
|
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-29 00:00:00 -07:00
|
15
15
|
default_executable:
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
requirements:
|
33
33
|
- - ~>
|
34
34
|
- !ruby/object:Gem::Version
|
35
|
-
version: 0.
|
35
|
+
version: 0.3.1
|
36
36
|
version:
|
37
37
|
description:
|
38
38
|
email: dev@yeastymobs.com
|
@@ -51,10 +51,12 @@ files:
|
|
51
51
|
- VERSION
|
52
52
|
- lib/remarkable_mongomapper.rb
|
53
53
|
- lib/remarkable_mongomapper/base.rb
|
54
|
+
- lib/remarkable_mongomapper/matchers/association_matcher.rb
|
54
55
|
- lib/remarkable_mongomapper/matchers/have_key_matcher.rb
|
55
56
|
- lib/remarkable_mongomapper/matchers/validate_presence_of_matcher.rb
|
56
57
|
- locales/en.yml
|
57
58
|
- remarkable_mongomapper.gemspec
|
59
|
+
- spec/matchers/association_matcher_spec.rb
|
58
60
|
- spec/matchers/have_key_matcher_spec.rb
|
59
61
|
- spec/matchers/validate_presence_of_matcher_spec.rb
|
60
62
|
- spec/models.rb
|
@@ -88,6 +90,7 @@ signing_key:
|
|
88
90
|
specification_version: 3
|
89
91
|
summary: MongoMapper Remarkable Matchers
|
90
92
|
test_files:
|
93
|
+
- spec/matchers/association_matcher_spec.rb
|
91
94
|
- spec/matchers/have_key_matcher_spec.rb
|
92
95
|
- spec/matchers/validate_presence_of_matcher_spec.rb
|
93
96
|
- spec/models.rb
|