mongoid4-rspec 1.11.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.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.gitignore +6 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +21 -0
- data/Gemfile +4 -0
- data/LICENSE +20 -0
- data/README.md +207 -0
- data/Rakefile +17 -0
- data/lib/matchers/accept_nested_attributes.rb +67 -0
- data/lib/matchers/allow_mass_assignment.rb +101 -0
- data/lib/matchers/associations.rb +316 -0
- data/lib/matchers/collections.rb +9 -0
- data/lib/matchers/document.rb +163 -0
- data/lib/matchers/indexes.rb +84 -0
- data/lib/matchers/validations.rb +81 -0
- data/lib/matchers/validations/acceptance_of.rb +9 -0
- data/lib/matchers/validations/associated.rb +19 -0
- data/lib/matchers/validations/confirmation_of.rb +9 -0
- data/lib/matchers/validations/custom_validation_of.rb +47 -0
- data/lib/matchers/validations/exclusion_of.rb +49 -0
- data/lib/matchers/validations/format_of.rb +71 -0
- data/lib/matchers/validations/inclusion_of.rb +49 -0
- data/lib/matchers/validations/length_of.rb +147 -0
- data/lib/matchers/validations/numericality_of.rb +74 -0
- data/lib/matchers/validations/presence_of.rb +9 -0
- data/lib/matchers/validations/uniqueness_of.rb +82 -0
- data/lib/matchers/validations/with_message.rb +27 -0
- data/lib/mongoid-rspec.rb +33 -0
- data/lib/mongoid-rspec/version.rb +5 -0
- data/mongoid-rspec.gemspec +25 -0
- data/mongoid4-rspec.gemspec +25 -0
- data/spec/models/article.rb +29 -0
- data/spec/models/comment.rb +6 -0
- data/spec/models/log.rb +4 -0
- data/spec/models/movie_article.rb +8 -0
- data/spec/models/permalink.rb +5 -0
- data/spec/models/person.rb +10 -0
- data/spec/models/profile.rb +16 -0
- data/spec/models/record.rb +5 -0
- data/spec/models/site.rb +9 -0
- data/spec/models/user.rb +36 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/unit/accept_nested_attributes_spec.rb +12 -0
- data/spec/unit/associations_spec.rb +42 -0
- data/spec/unit/collections_spec.rb +7 -0
- data/spec/unit/document_spec.rb +21 -0
- data/spec/unit/indexes_spec.rb +13 -0
- data/spec/unit/validations_spec.rb +52 -0
- data/spec/validators/ssn_validator.rb +16 -0
- metadata +137 -0
@@ -0,0 +1,316 @@
|
|
1
|
+
require 'mongoid/relations'
|
2
|
+
|
3
|
+
module Mongoid
|
4
|
+
module Matchers
|
5
|
+
module Associations
|
6
|
+
|
7
|
+
HAS_MANY = Mongoid::Relations::Referenced::Many
|
8
|
+
HAS_AND_BELONGS_TO_MANY = Mongoid::Relations::Referenced::ManyToMany
|
9
|
+
HAS_ONE = Mongoid::Relations::Referenced::One
|
10
|
+
BELONGS_TO = Mongoid::Relations::Referenced::In
|
11
|
+
EMBEDS_MANY = Mongoid::Relations::Embedded::Many
|
12
|
+
EMBEDS_ONE = Mongoid::Relations::Embedded::One
|
13
|
+
EMBEDDED_IN = Mongoid::Relations::Embedded::In
|
14
|
+
|
15
|
+
class HaveAssociationMatcher
|
16
|
+
def initialize(name, association_type)
|
17
|
+
@association = {}
|
18
|
+
@association[:name] = name.to_s
|
19
|
+
@association[:type] = association_type
|
20
|
+
@expectation_message = "#{type_description} #{@association[:name].inspect}"
|
21
|
+
@expectation_message << " of type #{@association[:class].inspect}" unless @association[:class].nil?
|
22
|
+
end
|
23
|
+
|
24
|
+
def of_type(klass)
|
25
|
+
@association[:class] = klass
|
26
|
+
@expectation_message << " of type #{@association[:class].inspect}"
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
def as_inverse_of(association_inverse_name)
|
31
|
+
raise "#{@association[:type].inspect} does not respond to :inverse_of" unless [HAS_MANY, HAS_AND_BELONGS_TO_MANY, BELONGS_TO, EMBEDDED_IN].include?(@association[:type])
|
32
|
+
@association[:inverse_of] = association_inverse_name.to_s
|
33
|
+
@expectation_message << " which is an inverse of #{@association[:inverse_of].inspect}"
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
def ordered_by(association_field_name)
|
38
|
+
raise "#{@association[:type].inspect} does not respond to :order" unless [HAS_MANY, HAS_AND_BELONGS_TO_MANY, EMBEDS_MANY].include?(@association[:type])
|
39
|
+
@association[:order] = association_field_name.to_s
|
40
|
+
@expectation_message << " ordered by #{@association[:order].inspect}"
|
41
|
+
|
42
|
+
if association_field_name.is_a? Origin::Key
|
43
|
+
@association[:order_operator] = association_field_name.operator
|
44
|
+
@expectation_message << " #{order_way(@association[:order_operator])}"
|
45
|
+
end
|
46
|
+
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
def with_dependent(method_name)
|
51
|
+
@association[:dependent] = method_name
|
52
|
+
@expectation_message << " which specifies dependent as #{@association[:dependent].to_s}"
|
53
|
+
self
|
54
|
+
end
|
55
|
+
|
56
|
+
def with_autosave
|
57
|
+
@association[:autosave] = true
|
58
|
+
@expectation_message << " which specifies autosave as #{@association[:autosave].to_s}"
|
59
|
+
self
|
60
|
+
end
|
61
|
+
|
62
|
+
def with_index
|
63
|
+
@association[:index] = true
|
64
|
+
@expectation_message << " which specifies index as #{@association[:index].to_s}"
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
def with_autobuild
|
69
|
+
@association[:autobuild] = true
|
70
|
+
@expectation_message << " which specifies autobuild as #{@association[:autobuild].to_s}"
|
71
|
+
self
|
72
|
+
end
|
73
|
+
|
74
|
+
def with_polymorphism
|
75
|
+
@association[:polymorphic] = true
|
76
|
+
@expectation_message << " which specifies polymorphic as #{@association[:polymorphic].to_s}"
|
77
|
+
self
|
78
|
+
end
|
79
|
+
|
80
|
+
def with_cascading_callbacks
|
81
|
+
@association[:cascade_callbacks] = true
|
82
|
+
@expectation_message << " which specifies cascade_callbacks as #{@association[:cascade_callbacks].to_s}"
|
83
|
+
self
|
84
|
+
end
|
85
|
+
|
86
|
+
def cyclic
|
87
|
+
@association[:cyclic] = true
|
88
|
+
@expectation_message << " which specifies cyclic as #{@association[:cyclic].to_s}"
|
89
|
+
self
|
90
|
+
end
|
91
|
+
|
92
|
+
def stored_as(store_as)
|
93
|
+
@association[:store_as] = store_as.to_s
|
94
|
+
@expectation_message << " which is stored as #{@association[:store_as].inspect}"
|
95
|
+
self
|
96
|
+
end
|
97
|
+
|
98
|
+
def with_foreign_key(foreign_key)
|
99
|
+
@association[:foreign_key] = foreign_key.to_s
|
100
|
+
@expectation_message << " using foreign key #{@association[:foreign_key].inspect}"
|
101
|
+
self
|
102
|
+
end
|
103
|
+
|
104
|
+
def matches?(actual)
|
105
|
+
@actual = actual.is_a?(Class) ? actual : actual.class
|
106
|
+
metadata = @actual.relations[@association[:name]]
|
107
|
+
|
108
|
+
if metadata.nil?
|
109
|
+
@negative_result_message = "no association named #{@association[:name]}"
|
110
|
+
return false
|
111
|
+
else
|
112
|
+
@positive_result_message = "association named #{@association[:name]}"
|
113
|
+
end
|
114
|
+
|
115
|
+
relation = metadata.relation
|
116
|
+
if relation != @association[:type]
|
117
|
+
@negative_result_message = "#{@actual.inspect} #{type_description(relation, false)} #{@association[:name]}"
|
118
|
+
return false
|
119
|
+
else
|
120
|
+
@positive_result_message = "#{@actual.inspect} #{type_description(relation, false)} #{@association[:name]}"
|
121
|
+
end
|
122
|
+
|
123
|
+
if !@association[:class].nil? and @association[:class] != metadata.klass
|
124
|
+
@negative_result_message = "#{@positive_result_message} of type #{metadata.klass.inspect}"
|
125
|
+
return false
|
126
|
+
else
|
127
|
+
@positive_result_message = "#{@positive_result_message}#{" of type #{metadata.klass.inspect}" if @association[:class]}"
|
128
|
+
end
|
129
|
+
|
130
|
+
if @association[:inverse_of]
|
131
|
+
if @association[:inverse_of].to_s != metadata.inverse_of.to_s
|
132
|
+
@negative_result_message = "#{@positive_result_message} which is an inverse of #{metadata.inverse_of}"
|
133
|
+
return false
|
134
|
+
else
|
135
|
+
@positive_result_message = "#{@positive_result_message} which is an inverse of #{metadata.inverse_of}"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
if @association[:order]
|
140
|
+
if @association[:order].to_s != metadata.order.to_s
|
141
|
+
@negative_result_message = "#{@positive_result_message} ordered by #{metadata.order}"
|
142
|
+
return false
|
143
|
+
else
|
144
|
+
@positive_result_message = "#{@positive_result_message} ordered by #{metadata.order}"
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
if @association[:order_operator]
|
149
|
+
if @association[:order_operator] != metadata.order.operator
|
150
|
+
@negative_result_message = "#{@positive_result_message} #{order_way(@association[:order_operator] * -1)}"
|
151
|
+
return false
|
152
|
+
else
|
153
|
+
@positive_result_message = "#{@positive_result_message} #{order_way(@association[:order_operator])}"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
if @association[:dependent]
|
158
|
+
if @association[:dependent].to_s != metadata.dependent.to_s
|
159
|
+
@negative_result_message = "#{@positive_result_message} which specified dependent as #{metadata.dependent}"
|
160
|
+
return false
|
161
|
+
else
|
162
|
+
@positive_result_message = "#{@positive_result_message} which specified dependent as #{metadata.dependent}"
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
if @association[:autosave]
|
167
|
+
if metadata.autosave != true
|
168
|
+
@negative_result_message = "#{@positive_result_message} which did not set autosave"
|
169
|
+
return false
|
170
|
+
else
|
171
|
+
@positive_result_message = "#{@positive_result_message} which set autosave"
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
if @association[:autobuild]
|
176
|
+
if metadata.autobuilding? != true
|
177
|
+
@negative_result_message = "#{@positive_result_message} which did not set autobuild"
|
178
|
+
return false
|
179
|
+
else
|
180
|
+
@positive_result_message = "#{@positive_result_message} which set autobuild"
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
if @association[:polymorphic]
|
185
|
+
if metadata.polymorphic? != true
|
186
|
+
@negative_result_message = "#{@positive_result_message} which did not set polymorphic"
|
187
|
+
return false
|
188
|
+
else
|
189
|
+
@positive_result_message = "#{@positive_result_message} which set polymorphic"
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
if @association[:cascade_callbacks]
|
194
|
+
if metadata.cascading_callbacks? != true
|
195
|
+
@negative_result_message = "#{@positive_result_message} which did not set cascade_callbacks"
|
196
|
+
return false
|
197
|
+
else
|
198
|
+
@positive_result_message = "#{@positive_result_message} which set cascade_callbacks"
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
if @association[:cyclic]
|
203
|
+
if metadata.cyclic? != true
|
204
|
+
@negative_result_message = "#{@positive_result_message} which did not set cyclic"
|
205
|
+
return false
|
206
|
+
else
|
207
|
+
@positive_result_message = "#{@positive_result_message} which set cyclic"
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
if @association[:store_as]
|
212
|
+
if metadata.store_as != @association[:store_as]
|
213
|
+
@negative_result_message = "#{@positive_result_message} which is stored as #{metadata.store_as}"
|
214
|
+
return false
|
215
|
+
else
|
216
|
+
@positive_result_message = "#{@positive_result_message} which is stored as #{metadata.store_as}"
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
if @association[:index]
|
221
|
+
if metadata.index != true
|
222
|
+
@negative_result_message = "#{@positive_result_message} which did not set index"
|
223
|
+
return false
|
224
|
+
else
|
225
|
+
@positive_result_message = "#{@positive_result_message} which set index"
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
if @association[:foreign_key]
|
230
|
+
if metadata.foreign_key != @association[:foreign_key]
|
231
|
+
@negative_result_message = "#{@positive_result_message} with foreign key #{metadata.foreign_key.inspect}"
|
232
|
+
return false
|
233
|
+
else
|
234
|
+
@positive_result_message = "#{@positive_result_message} with foreign key #{metadata.foreign_key.inspect}"
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
return true
|
239
|
+
end
|
240
|
+
|
241
|
+
def failure_message_for_should
|
242
|
+
"Expected #{@actual.inspect} to #{@expectation_message}, got #{@negative_result_message}"
|
243
|
+
end
|
244
|
+
|
245
|
+
def failure_message_for_should_not
|
246
|
+
"Expected #{@actual.inspect} to not #{@expectation_message}, got #{@positive_result_message}"
|
247
|
+
end
|
248
|
+
|
249
|
+
alias :failure_message :failure_message_for_should
|
250
|
+
alias :failure_message_when_negated :failure_message_for_should_not
|
251
|
+
|
252
|
+
def description
|
253
|
+
@expectation_message
|
254
|
+
end
|
255
|
+
|
256
|
+
def type_description(type = nil, passive = true)
|
257
|
+
type ||= @association[:type]
|
258
|
+
case type.name
|
259
|
+
when EMBEDS_ONE.name
|
260
|
+
(passive ? 'embed' : 'embeds') << ' one'
|
261
|
+
when EMBEDS_MANY.name
|
262
|
+
(passive ? 'embed' : 'embeds') << ' many'
|
263
|
+
when EMBEDDED_IN.name
|
264
|
+
(passive ? 'be' : 'is') << ' embedded in'
|
265
|
+
when HAS_ONE.name
|
266
|
+
(passive ? 'reference' : 'references') << ' one'
|
267
|
+
when HAS_MANY.name
|
268
|
+
(passive ? 'reference' : 'references') << ' many'
|
269
|
+
when HAS_AND_BELONGS_TO_MANY.name
|
270
|
+
(passive ? 'reference' : 'references') << ' and referenced in many'
|
271
|
+
when BELONGS_TO.name
|
272
|
+
(passive ? 'be referenced in' : 'referenced in')
|
273
|
+
else
|
274
|
+
raise "Unknown association type '%s'" % type
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
private
|
279
|
+
def order_way(operator)
|
280
|
+
[nil, "ascending", "descending"][operator]
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
def embed_one(association_name)
|
285
|
+
HaveAssociationMatcher.new(association_name, EMBEDS_ONE)
|
286
|
+
end
|
287
|
+
|
288
|
+
def embed_many(association_name)
|
289
|
+
HaveAssociationMatcher.new(association_name, EMBEDS_MANY)
|
290
|
+
end
|
291
|
+
|
292
|
+
def be_embedded_in(association_name)
|
293
|
+
HaveAssociationMatcher.new(association_name, EMBEDDED_IN)
|
294
|
+
end
|
295
|
+
|
296
|
+
def have_one_related(association_name)
|
297
|
+
HaveAssociationMatcher.new(association_name, HAS_ONE)
|
298
|
+
end
|
299
|
+
alias :have_one :have_one_related
|
300
|
+
|
301
|
+
def have_many_related(association_name)
|
302
|
+
HaveAssociationMatcher.new(association_name, HAS_MANY)
|
303
|
+
end
|
304
|
+
alias :have_many :have_many_related
|
305
|
+
|
306
|
+
def have_and_belong_to_many(association_name)
|
307
|
+
HaveAssociationMatcher.new(association_name, HAS_AND_BELONGS_TO_MANY)
|
308
|
+
end
|
309
|
+
|
310
|
+
def belong_to_related(association_name)
|
311
|
+
HaveAssociationMatcher.new(association_name, BELONGS_TO)
|
312
|
+
end
|
313
|
+
alias :belong_to :belong_to_related
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Matchers
|
3
|
+
class HaveFieldMatcher # :nodoc:
|
4
|
+
def initialize(*attrs)
|
5
|
+
@attributes = attrs.collect(&:to_s)
|
6
|
+
end
|
7
|
+
|
8
|
+
def localized
|
9
|
+
@localized = true
|
10
|
+
self
|
11
|
+
end
|
12
|
+
|
13
|
+
def of_type(type)
|
14
|
+
@type = type
|
15
|
+
self
|
16
|
+
end
|
17
|
+
|
18
|
+
def with_alias(field_alias)
|
19
|
+
@field_alias = field_alias
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
def with_default_value_of(default)
|
24
|
+
@default = default
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def matches?(klass)
|
29
|
+
@klass = klass.is_a?(Class) ? klass : klass.class
|
30
|
+
@errors = []
|
31
|
+
@attributes.each do |attr|
|
32
|
+
if @klass.fields.include?(attr)
|
33
|
+
error = ""
|
34
|
+
if @type and @klass.fields[attr].type != @type
|
35
|
+
error << " of type #{@klass.fields[attr].type}"
|
36
|
+
end
|
37
|
+
|
38
|
+
if !@default.nil?
|
39
|
+
if @klass.fields[attr].default_val.nil?
|
40
|
+
error << " with default not set"
|
41
|
+
elsif @klass.fields[attr].default_val != @default
|
42
|
+
error << " with default value of #{@klass.fields[attr].default_val}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
if @field_alias and @klass.fields[attr].options[:as] != @field_alias
|
47
|
+
error << " with alias #{@klass.fields[attr].options[:as]}"
|
48
|
+
end
|
49
|
+
|
50
|
+
@errors.push("field #{attr.inspect}" << error) unless error.blank?
|
51
|
+
|
52
|
+
if @localized
|
53
|
+
unless @klass.fields[attr].localized?
|
54
|
+
@errors.push "is not localized #{attr.inspect}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
else
|
59
|
+
@errors.push "no field named #{attr.inspect}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
@errors.empty?
|
63
|
+
end
|
64
|
+
|
65
|
+
def failure_message_for_should
|
66
|
+
"Expected #{@klass.inspect} to #{description}, got #{@errors.to_sentence}"
|
67
|
+
end
|
68
|
+
|
69
|
+
def failure_message_for_should_not
|
70
|
+
"Expected #{@klass.inspect} to not #{description}, got #{@klass.inspect} to #{description}"
|
71
|
+
end
|
72
|
+
|
73
|
+
alias :failure_message :failure_message_for_should
|
74
|
+
alias :failure_message_when_negated :failure_message_for_should_not
|
75
|
+
|
76
|
+
def description
|
77
|
+
desc = "have #{@attributes.size > 1 ? 'fields' : 'field'} named #{@attributes.collect(&:inspect).to_sentence}"
|
78
|
+
desc << " of type #{@type.inspect}" if @type
|
79
|
+
desc << " with alias #{@field_alias}" if @field_alias
|
80
|
+
desc << " with default value of #{@default.inspect}" if !@default.nil?
|
81
|
+
desc
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def have_field(*args)
|
86
|
+
HaveFieldMatcher.new(*args)
|
87
|
+
end
|
88
|
+
alias_method :have_fields, :have_field
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
RSpec::Matchers.define :have_instance_method do |name|
|
93
|
+
match do |klass|
|
94
|
+
klass.instance_methods.include?(name.to_sym)
|
95
|
+
end
|
96
|
+
|
97
|
+
description do
|
98
|
+
"have instance method #{name.to_s}"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
RSpec::Matchers.define :be_mongoid_document do
|
103
|
+
match do |doc|
|
104
|
+
doc.class.included_modules.include?(Mongoid::Document)
|
105
|
+
end
|
106
|
+
|
107
|
+
description do
|
108
|
+
"be a Mongoid document"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
RSpec::Matchers.define :be_versioned_document do
|
113
|
+
match do |doc|
|
114
|
+
doc.class.included_modules.include?(Mongoid::Versioning)
|
115
|
+
end
|
116
|
+
|
117
|
+
description do
|
118
|
+
"be a versioned Mongoid document"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
RSpec::Matchers.define :be_timestamped_document do
|
123
|
+
match do |doc|
|
124
|
+
if [*@timestamped_module].any?
|
125
|
+
modules = [*@timestamped_module].map{|m| "Mongoid::Timestamps::#{m.to_s.classify}".constantize }
|
126
|
+
(modules - doc.class.included_modules).empty?
|
127
|
+
else
|
128
|
+
doc.class.included_modules.include?(Mongoid::Timestamps) or
|
129
|
+
doc.class.included_modules.include?(Mongoid::Timestamps::Created) or
|
130
|
+
doc.class.included_modules.include?(Mongoid::Timestamps::Updated)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
chain :with do |timestamped_module|
|
135
|
+
@timestamped_module = timestamped_module
|
136
|
+
end
|
137
|
+
|
138
|
+
description do
|
139
|
+
desc = "be a timestamped Mongoid document"
|
140
|
+
desc << " with #{@timestamped_module}" if @timestamped_module
|
141
|
+
desc
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
RSpec::Matchers.define :be_paranoid_document do
|
146
|
+
match do |doc|
|
147
|
+
doc.class.included_modules.include?(Mongoid::Paranoia)
|
148
|
+
end
|
149
|
+
|
150
|
+
description do
|
151
|
+
"be a paranoid Mongoid document"
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
RSpec::Matchers.define :be_multiparameted_document do
|
156
|
+
match do |doc|
|
157
|
+
doc.class.included_modules.include?(Mongoid::MultiParameterAttributes)
|
158
|
+
end
|
159
|
+
|
160
|
+
description do
|
161
|
+
"be a multiparameted Mongoid document"
|
162
|
+
end
|
163
|
+
end
|