yeastymobs-remarkable_mongomapper 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1 +1,23 @@
1
- Remarkable matchers for [MongoMapper](http://github.com/jnunemaker/mongomapper).
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.2.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
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 #:nodoc:
4
+ class HaveKeyMatcher < Remarkable::MongoMapper::Base
5
5
 
6
- arguments :collection => :keys, :as => :key
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
- @type = @options[:type]
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.reader?(@key) && @subject.class.keys[@key] == ::MongoMapper::Key.new(@key, @type)
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
- # should_have_column :name, :type => String
26
+ # should_have_key :name, String
31
27
  #
32
- # it { should have_column(:name, :type => String) }
33
- # it { should have_column(:name, :phone_number, :type => String) }
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 #:nodoc:
4
+ class ValidatePresenceOfMatcher < Remarkable::MongoMapper::Base
5
5
 
6
- arguments :collection => :keys, :as => :key
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
- @subject.send("#{@key}=", nil)
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) {{keys}}"
15
+ description: "have key(s) {{attributes}}"
6
16
  expectations:
7
- has_key: "{{subject_name}} to have key named {{key}} with type {{type}}"
17
+ has_key: "{{subject_name}} to have key named {{attribute}} with type {{type}}"
8
18
 
9
19
  validate_presence_of:
10
- description: "require {{keys}} to be set"
20
+ description: "require {{attributes}} to be set"
11
21
  expectations:
12
- allow_nil: "{{subject_name}} to require {{key}} to be set"
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.1"
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-28}
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/have_key_matcher_spec.rb",
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.2.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.2.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.2.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, :type => String)
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, :type => String)
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, :type => String) }
25
- it { should have_keys(:title, :body, :type => String) }
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, :type => String
30
- should_have_keys :title, :body, :type => String
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) { reset_test_db! }
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.1
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-28 00:00:00 -07:00
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.2.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