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 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