remarkable_activerecord 3.0.4 → 3.0.5

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 CHANGED
@@ -4,13 +4,17 @@ Remarkable ActiveRecord is a collection of matchers to ActiveRecord. Why use
4
4
  Remarkable?
5
5
 
6
6
  * The only one with matchers for all ActiveRecord validations, with support to
7
- all options;
7
+ all options (except :on and the option :with in validates_format_of);
8
8
 
9
9
  * Matchers for all ActiveRecord associations. The only one which supports all
10
10
  these options:
11
11
 
12
- :through, :class_name, :foreign_key, :dependent, :join_table, :uniq,
13
- :readonly, :validate, :autosave, :counter_cache, :polymorphic
12
+ :through, :source, :source_type, :class_name, :foreign_key, :dependent,
13
+ :join_table, :uniq, :readonly, :validate, :autosave, :counter_cache, :polymorphic
14
+
15
+ Plus SQL options:
16
+
17
+ :select, :conditions, :include, :group, :having, :order, :limit, :offset
14
18
 
15
19
  Besides in Remarkable 3.0 matchers became much smarter. Whenever :join_table
16
20
  or :through is given as option, it checks if the given table exists. Whenever
@@ -60,14 +60,7 @@ module Remarkable
60
60
  # to be used as default.
61
61
  #
62
62
  def allow_nil?(message_key=:message) #:nodoc:
63
- valid, options = assert_good_or_bad_if_key(:allow_nil, nil, message_key)
64
-
65
- unless valid
66
- default = Remarkable.t "remarkable.active_record.allow_nil", default_i18n_options.except(:scope).merge(options)
67
- return false, options.merge(:default => default)
68
- end
69
-
70
- true
63
+ assert_good_or_bad_if_key(:allow_nil, nil, message_key)
71
64
  end
72
65
 
73
66
  # Default allow_blank? validation. It accepts the message_key which is
@@ -77,14 +70,7 @@ module Remarkable
77
70
  # to be used as default.
78
71
  #
79
72
  def allow_blank?(message_key=:message) #:nodoc:
80
- valid, options = assert_good_or_bad_if_key(:allow_blank, '', message_key)
81
-
82
- unless valid
83
- default = Remarkable.t "remarkable.active_record.allow_blank", default_i18n_options.except(:scope).merge(options)
84
- return false, options.merge(:default => default)
85
- end
86
-
87
- true
73
+ assert_good_or_bad_if_key(:allow_blank, '', message_key)
88
74
  end
89
75
 
90
76
  # Shortcut for assert_good_value.
@@ -4,15 +4,13 @@ module Remarkable
4
4
  class AssociationMatcher < Remarkable::ActiveRecord::Base #:nodoc:
5
5
  arguments :macro, :collection => :associations, :as => :association
6
6
 
7
- optionals :through, :class_name, :foreign_key, :dependent, :join_table, :as
7
+ optionals :through, :source, :source_type, :class_name, :foreign_key, :dependent, :join_table, :as
8
+ optionals :select, :conditions, :include, :group, :having, :order, :limit, :offset, :finder_sql, :counter_sql
8
9
  optionals :uniq, :readonly, :validate, :autosave, :polymorphic, :counter_cache, :default => true
9
10
 
10
- # Stores optionals declared above in a CONSTANT to generate assertions
11
- ASSOCIATION_OPTIONS = self.matcher_optionals
12
-
13
- collection_assertions :association_exists?, :macro_matches?, :through_exists?,
11
+ collection_assertions :association_exists?, :macro_matches?, :through_exists?, :source_exists?,
14
12
  :join_table_exists?, :foreign_key_exists?, :polymorphic_exists?,
15
- :counter_cache_exists?
13
+ :counter_cache_exists?, :options_match?
16
14
 
17
15
  protected
18
16
 
@@ -25,16 +23,22 @@ module Remarkable
25
23
  end
26
24
 
27
25
  def through_exists?
28
- return true unless @options.key?(:through)
29
- subject_class.reflect_on_association(@options[:through])
26
+ return true unless @options.key?(:through)
27
+ reflection.through_reflection rescue false
28
+ end
29
+
30
+ def source_exists?
31
+ return true unless @options.key?(:through)
32
+ reflection.source_reflection rescue false
30
33
  end
31
34
 
32
35
  def join_table_exists?
33
- return true unless has_join_table?
34
- ::ActiveRecord::Base.connection.tables.include?(reflection_join_table)
36
+ return true unless reflection.macro == :has_and_belongs_to_many
37
+ ::ActiveRecord::Base.connection.tables.include?(reflection.options[:join_table])
35
38
  end
36
39
 
37
- def foreign_key_exists?
40
+ def foreign_key_exists?
41
+ return true unless foreign_key_table
38
42
  table_has_column?(foreign_key_table, reflection_foreign_key)
39
43
  end
40
44
 
@@ -47,18 +51,18 @@ module Remarkable
47
51
  return true unless @options[:counter_cache]
48
52
  table_has_column?(reflection.klass.table_name, reflection.counter_cache_column.to_s)
49
53
  end
50
-
51
- ASSOCIATION_OPTIONS.each do |option|
52
- collection_assertion :"#{option}_matches?"
53
-
54
- class_eval <<-METHOD, __FILE__, __LINE__
55
- def #{option}_matches?
56
- return true unless @options.key?(#{option.inspect})
57
- actual_value = respond_to?(:reflection_#{option}, true) ? reflection_#{option} : reflection.options[#{option.inspect}].to_s
58
-
59
- return true if @options[#{option.inspect}].to_s == actual_value
60
- end
61
- METHOD
54
+
55
+ def options_match?
56
+ actual_options = {}
57
+
58
+ @options.keys.each do |key|
59
+ method = :"reflection_#{key}"
60
+
61
+ @options[key] = @options[key].to_s
62
+ actual_options[key] = (respond_to?(method, true) ? send(method) : reflection.options[key]).to_s
63
+ end
64
+
65
+ return @options == actual_options, :actual => actual_options.inspect
62
66
  end
63
67
 
64
68
  private
@@ -76,27 +80,25 @@ module Remarkable
76
80
  reflection.primary_key_name.to_s
77
81
  end
78
82
 
79
- def reflection_join_table
80
- (reflection.options[:join_table] || reflection.options[:through]).to_s
81
- end
82
-
83
- def has_join_table?
84
- reflection.options.key?(:through) || reflection.macro == :has_and_belongs_to_many
85
- end
86
-
87
83
  def table_has_column?(table_name, column)
88
84
  ::ActiveRecord::Base.connection.columns(table_name, 'Remarkable column retrieval').any?{|c| c.name == column }
89
85
  end
90
86
 
87
+ # In through we don't check the foreign_key, because it's spread
88
+ # accross the through and the source reflection which should be tested
89
+ # with their own macros.
90
+ #
91
91
  # In cases a join table exists (has_and_belongs_to_many and through
92
92
  # associations), we check the foreign key in the join table.
93
93
  #
94
94
  # On belongs to, the foreign_key is in the subject class table and in
95
95
  # other cases it's on the reflection class table.
96
96
  #
97
- def foreign_key_table
98
- if has_join_table?
99
- reflection_join_table
97
+ def foreign_key_table
98
+ if reflection.options.key?(:through)
99
+ nil
100
+ elsif reflection.macro == :has_and_belongs_to_many
101
+ reflection.options[:join_table]
100
102
  elsif reflection.macro == :belongs_to
101
103
  subject_class.table_name
102
104
  else
@@ -105,7 +107,7 @@ module Remarkable
105
107
  end
106
108
 
107
109
  def interpolation_options
108
- options = { :macro => Remarkable.t(@macro, :scope => matcher_i18n_scope, :default => @macro.to_s) }
110
+ options = { :macro => Remarkable.t(@macro, :scope => matcher_i18n_scope, :default => @macro.to_s), :options => @options.inspect }
109
111
 
110
112
  if @subject && reflection
111
113
  options.merge!(
@@ -114,14 +116,10 @@ module Remarkable
114
116
  :reflection_table => reflection.klass.table_name.inspect,
115
117
  :foreign_key_table => foreign_key_table.inspect,
116
118
  :polymorphic_column => reflection_foreign_key.sub(/_id$/, '_type').inspect,
117
- :counter_cache_column => reflection.counter_cache_column.to_s.inspect
119
+ :counter_cache_column => reflection.counter_cache_column.to_s.inspect,
120
+ :join_table => reflection.options[:join_table].inspect,
121
+ :foreign_key => reflection_foreign_key.inspect
118
122
  ) rescue nil # rescue to allow specs to run properly
119
-
120
- ASSOCIATION_OPTIONS.each do |option|
121
- value_to_compare = respond_to?(:"reflection_#{option}", true) ? send(:"reflection_#{option}") : reflection.options[option].to_s
122
- options[:"actual_#{option}"] = value_to_compare.inspect
123
- end
124
-
125
123
  end
126
124
 
127
125
  options
@@ -143,6 +141,9 @@ module Remarkable
143
141
  # It also checks if the column actually exists in the table.
144
142
  # * <tt>:polymorphic</tt> - if the association should be polymorphic or not.
145
143
  # When true it also checks for the association_type column in the subject table.
144
+ #
145
+ # Plus all supported sql conditions options: :select, :conditions, :order,
146
+ # :limit, :offset, :include, :group, :having.
146
147
  #
147
148
  # == Examples
148
149
  #
@@ -164,7 +165,10 @@ module Remarkable
164
165
  # * <tt>:uniq</tt> - checks wether uniq is true or false.
165
166
  # * <tt>:readonly</tt> - checks wether readonly is true or false.
166
167
  # * <tt>:validate</tt> - checks wether validate is true or false.
167
- # * <tt>:autosave</tt> - checks wether autosave is true or false.
168
+ # * <tt>:autosave</tt> - checks wether autosave is true or false.
169
+ #
170
+ # Plus all supported sql conditions options: :select, :conditions, :order,
171
+ # :limit, :offset, :include, :group, :having.
168
172
  #
169
173
  # == Examples
170
174
  #
@@ -183,14 +187,19 @@ module Remarkable
183
187
  #
184
188
  # * <tt>:class_name</tt> - the expected associted class name.
185
189
  # * <tt>:through</tt> - the expected join model which to perform the query.
186
- # It also checks if the through table exists.
190
+ # It also checks if the through table exists.
191
+ # * <tt>:source</tt> - the source of the through association.
192
+ # * <tt>:source_type</tt> - the source type of the through association.
187
193
  # * <tt>:foreign_key</tt> - the expected foreign key in the associated table.
188
194
  # When used with :through, it will check for the foreign key in the join table.
189
195
  # * <tt>:dependent</tt> - the expected dependent value for the association.
190
196
  # * <tt>:uniq</tt> - checks wether uniq is true or false.
191
197
  # * <tt>:readonly</tt> - checks wether readonly is true or false.
192
198
  # * <tt>:validate</tt> - checks wether validate is true or false.
193
- # * <tt>:autosave</tt> - checks wether autosave is true or false.
199
+ # * <tt>:autosave</tt> - checks wether autosave is true or false.
200
+ #
201
+ # Plus all supported sql conditions options: :select, :conditions, :order,
202
+ # :limit, :offset, :include, :group, :having.
194
203
  #
195
204
  # == Examples
196
205
  #
@@ -214,12 +223,17 @@ module Remarkable
214
223
  #
215
224
  # * <tt>:class_name</tt> - the expected associted class name.
216
225
  # * <tt>:through</tt> - the expected join model which to perform the query.
217
- # It also checks if the through table exists.
226
+ # It also checks if the through table exists.
227
+ # * <tt>:source</tt> - the source of the through association.
228
+ # * <tt>:source_type</tt> - the source type of the through association.
218
229
  # * <tt>:foreign_key</tt> - the expected foreign key in the associated table.
219
230
  # When used with :through, it will check for the foreign key in the join table.
220
231
  # * <tt>:dependent</tt> - the expected dependent value for the association.
221
232
  # * <tt>:validate</tt> - checks wether validate is true or false.
222
- # * <tt>:autosave</tt> - checks wether autosave is true or false.
233
+ # * <tt>:autosave</tt> - checks wether autosave is true or false.
234
+ #
235
+ # Plus all supported sql conditions options: :select, :conditions, :order,
236
+ # :limit, :offset, :include, :group, :having.
223
237
  #
224
238
  # == Examples
225
239
  #
data/locale/en.yml CHANGED
@@ -1,20 +1,21 @@
1
1
  en:
2
2
  remarkable:
3
- active_record:
4
- allow_nil: "{{subject_name}} to {{not}}allow nil values for {{attribute}}"
5
- allow_blank: "{{subject_name}} to {{not}}allow blank values for {{attribute}}"
3
+ active_record:
4
+ expectations:
5
+ allow_nil: "{{subject_name}} to {{not}}allow nil values for {{attribute}}"
6
+ allow_blank: "{{subject_name}} to {{not}}allow blank values for {{attribute}}"
7
+ optionals:
8
+ allow_nil:
9
+ positive: "allowing nil values"
10
+ negative: "not allowing nil values"
11
+ allow_blank:
12
+ positive: "allowing blank values"
13
+ negative: "not allowing blank values"
6
14
 
7
15
  allow_values_for:
8
16
  description: "allow {{in}} as values for {{attributes}}"
9
17
  expectations:
10
18
  is_valid: "{{subject_name}} to be valid when {{attribute}} is set to {{value}}"
11
- optionals:
12
- allow_nil:
13
- positive: "allowing nil values"
14
- negative: "not allowing nil values"
15
- allow_blank:
16
- positive: "allowing blank values"
17
- negative: "not allowing blank values"
18
19
 
19
20
  allow_mass_assignment_of:
20
21
  description: "allow mass assignment of {{attributes}}"
@@ -31,26 +32,20 @@ en:
31
32
  expectations:
32
33
  association_exists: "{{subject_name}} records {{macro}} {{association}}, got no association"
33
34
  macro_matches: "{{subject_name}} records {{macro}} {{association}}, got {{subject_name}} records {{actual_macro}} {{association}}"
34
- through_exists: "{{subject_name}} records {{macro}} {{association}} through {{through}}, through association does not exist"
35
- join_table_exists: "join table {{actual_join_table}} to exist, but does not"
36
- foreign_key_exists: "foreign key {{actual_foreign_key}} to exist on {{foreign_key_table}}, but does not"
35
+ through_exists: "{{subject_name}} records {{macro}} {{association}} through {{through}}, through association does not exist"
36
+ source_exists: "{{subject_name}} records {{macro}} {{association}} through {{through}}, source association does not exist"
37
+ join_table_exists: "join table {{join_table}} to exist, but does not"
38
+ foreign_key_exists: "foreign key {{foreign_key}} to exist on {{foreign_key_table}}, but does not"
37
39
  polymorphic_exists: "{{subject_table}} to have {{polymorphic_column}} as column, but does not"
38
- counter_cache_exists: "{{reflection_table}} to have {{counter_cache_column}} as column, but does not"
39
- through_matches: "{{association}} association through {{through}}, got {{actual_through}}"
40
- class_name_matches: "{{association}} association with class name {{class_name}}, got {{actual_class_name}}"
41
- foreign_key_matches: "{{association}} association with foreign key {{foreign_key}}, got {{actual_foreign_key}}"
42
- dependent_matches: "{{association}} association with dependent {{dependent}}, got {{actual_dependent}}"
43
- join_table_matches: "{{association}} association with join table {{join_table}}, got {{actual_join_table}}"
44
- uniq_matches: "{{association}} association with uniq equals to {{uniq}}, got {{actual_uniq}}"
45
- readonly_matches: "{{association}} association with readonly equals to {{readonly}}, got {{actual_readonly}}"
46
- validate_matches: "{{association}} association with validate equals to {{validate}}, got {{actual_validate}}"
47
- autosave_matches: "{{association}} association with autosave equals to {{autosave}}, got {{actual_autosave}}"
48
- polymorphic_matches: "{{association}} association with polymorphic equals to {{polymorphic}}, got {{actual_polymorphic}}"
49
- as_matches: "{{association}} association with polymorphic interface {{as}}, got {{actual_as}}"
50
- counter_cache_matches: "{{association}} association with counter cache {{counter_cache}}, got {{actual_counter_cache}}"
40
+ counter_cache_exists: "{{reflection_table}} to have {{counter_cache_column}} as column, but does not"
41
+ options_match: "{{subject_name}} records {{macro}} {{association}} with options {{options}}, got {{actual}}"
51
42
  optionals:
52
43
  through:
53
- positive: "through {{value}}"
44
+ positive: "through {{value}}"
45
+ source:
46
+ positive: "with source {{inspect}}"
47
+ source_type:
48
+ positive: "with source type {{inspect}}"
54
49
  class_name:
55
50
  positive: "with class name {{inspect}}"
56
51
  foreign_key:
@@ -75,7 +70,23 @@ en:
75
70
  positive: "through the polymorphic interface {{inspect}}"
76
71
  counter_cache:
77
72
  positive: "with counter cache {{inspect}}"
78
- negative: "without counter cache"
73
+ negative: "without counter cache"
74
+ select:
75
+ positive: "selecting {{inspect}}"
76
+ conditions:
77
+ positive: "with conditions {{inspect}}"
78
+ include:
79
+ positive: "including {{inspect}}"
80
+ group:
81
+ positive: "grouping by {{inspect}}"
82
+ having:
83
+ positive: "having {{inspect}}"
84
+ order:
85
+ positive: "with order {{inspect}}"
86
+ limit:
87
+ positive: "with limit {{inspect}}"
88
+ offset:
89
+ positive: "with offset {{inspect}}"
79
90
 
80
91
  have_column:
81
92
  description: "have column(s) named {{columns}}"
@@ -126,9 +137,6 @@ en:
126
137
  optionals:
127
138
  accept:
128
139
  positive: "with value {{inspect}}"
129
- allow_nil:
130
- positive: "allowing nil values"
131
- negative: "not allowing nil values"
132
140
 
133
141
  validate_associated:
134
142
  description: "require associated {{associations}} to be valid"
@@ -146,26 +154,12 @@ en:
146
154
  expectations:
147
155
  is_valid: "{{subject_name}} to be valid when {{attribute}} is set to {{value}}"
148
156
  is_invalid: "{{subject_name}} to be invalid when {{attribute}} is set to {{value}}"
149
- optionals:
150
- allow_nil:
151
- positive: "allowing nil values"
152
- negative: "not allowing nil values"
153
- allow_blank:
154
- positive: "allowing blank values"
155
- negative: "not allowing blank values"
156
157
 
157
158
  validate_inclusion_of:
158
159
  description: "ensure inclusion of {{attributes}} in {{in}}"
159
160
  expectations:
160
161
  is_valid: "{{subject_name}} to be valid when {{attribute}} is set to {{value}}"
161
162
  is_invalid: "{{subject_name}} to be invalid when {{attribute}} is set to {{value}}"
162
- optionals:
163
- allow_nil:
164
- positive: "allowing nil values"
165
- negative: "not allowing nil values"
166
- allow_blank:
167
- positive: "allowing blank values"
168
- negative: "not allowing blank values"
169
163
 
170
164
  validate_length_of:
171
165
  description: "ensure length of {{attributes}}"
@@ -183,12 +177,6 @@ en:
183
177
  positive: "is minimum {{inspect}} characters"
184
178
  is:
185
179
  positive: "is equal to {{inspect}} characters"
186
- allow_nil:
187
- positive: "allowing nil values"
188
- negative: "not allowing nil values"
189
- allow_blank:
190
- positive: "allowing blank values"
191
- negative: "not allowing blank values"
192
180
 
193
181
  validate_numericality_of:
194
182
  description: "ensure numericality of {{attributes}}"
@@ -217,12 +205,6 @@ en:
217
205
  positive: "is less than or equal to {{inspect}}"
218
206
  greater_than_or_equal_to:
219
207
  positive: "is greater than or equal to {{inspect}}"
220
- allow_nil:
221
- positive: "allowing nil values"
222
- negative: "not allowing nil values"
223
- allow_blank:
224
- positive: "allowing blank values"
225
- negative: "not allowing blank values"
226
208
 
227
209
  validate_presence_of:
228
210
  description: "require {{attributes}} to be set"
@@ -242,10 +224,4 @@ en:
242
224
  case_sensitive:
243
225
  positive: "case sensitive"
244
226
  negative: "case insensitive"
245
- allow_nil:
246
- positive: "allowing nil values"
247
- negative: "not allowing nil values"
248
- allow_blank:
249
- positive: "allowing blank values"
250
- negative: "not allowing blank values"
251
-
227
+
@@ -75,36 +75,16 @@ describe 'association_matcher' do
75
75
  matcher.failure_message.should == 'Expected "companies" to have "projects_count" as column, but does not'
76
76
  end
77
77
 
78
- it 'should set validate_matches? message' do
79
- matcher = define_and_validate(:validate => false)
80
- matcher.validate.matches?(@model)
81
- matcher.failure_message.should == 'Expected company association with validate equals to true, got "false"'
82
- end
83
-
84
- it 'should set readonly_matches? message' do
85
- matcher = define_and_validate(:readonly => false)
86
- matcher.readonly.matches?(@model)
87
- matcher.failure_message.should == 'Expected company association with readonly equals to true, got "false"'
88
- end
89
-
90
- if RAILS_VERSION =~ /^2.3/
91
- it 'should set autosave_matches? message' do
92
- matcher = define_and_validate(:autosave => false)
93
- matcher.autosave.matches?(@model)
94
- matcher.failure_message.should == 'Expected company association with autosave equals to true, got "false"'
95
- end
96
- end
97
-
98
- it 'should set polymorphic_matches? message' do
78
+ it 'should set options_matches? message when polymorphic is given' do
99
79
  matcher = define_and_validate(:polymorphic => false)
100
80
  matcher.polymorphic.matches?(@model)
101
- matcher.failure_message.should == 'Expected company association with polymorphic equals to true, got "false"'
81
+ matcher.failure_message.should == 'Expected Project records belong to company with options {:polymorphic=>"true"}, got {:polymorphic=>"false"}'
102
82
  end
103
83
 
104
- it 'should set counter_cache_matches? message' do
84
+ it 'should set options_matches? message when counter_cache is given' do
105
85
  matcher = define_and_validate(:counter_cache => true)
106
86
  matcher.counter_cache(false).matches?(@model)
107
- matcher.failure_message.should == 'Expected company association with counter cache false, got "true"'
87
+ matcher.failure_message.should == 'Expected Project records belong to company with options {:counter_cache=>"false"}, got {:counter_cache=>"true"}'
108
88
  end
109
89
  end
110
90
 
@@ -244,31 +224,11 @@ describe 'association_matcher' do
244
224
  matcher.failure_message.should == 'Expected foreign key "project_id" to exist on "labels_projects", but does not'
245
225
  end
246
226
 
247
- it 'should set validate_matches? message' do
248
- matcher = define_and_validate(:validate => false)
249
- matcher.validate.matches?(@model)
250
- matcher.failure_message.should == 'Expected labels association with validate equals to true, got "false"'
251
- end
252
-
253
- it 'should set readonly_matches? message' do
254
- matcher = define_and_validate(:readonly => false)
255
- matcher.readonly.matches?(@model)
256
- matcher.failure_message.should == 'Expected labels association with readonly equals to true, got "false"'
257
- end
258
-
259
- if RAILS_VERSION =~ /^2.3/
260
- it 'should set autosave_matches? message' do
261
- matcher = define_and_validate(:autosave => false)
262
- matcher.autosave.matches?(@model)
263
- matcher.failure_message.should == 'Expected labels association with autosave equals to true, got "false"'
264
- end
265
- end
266
-
267
- it 'should set uniq_matches? message' do
227
+ it 'should set options_matches? message' do
268
228
  matcher = define_and_validate(:uniq => false)
269
229
  matcher.uniq.matches?(@model)
270
- matcher.failure_message.should == 'Expected labels association with uniq equals to true, got "false"'
271
- end
230
+ matcher.failure_message.should == 'Expected Project records have and belong to many labels with options {:uniq=>"true"}, got {:uniq=>"false"}'
231
+ end
272
232
  end
273
233
 
274
234
  describe 'matchers' do
@@ -348,17 +308,19 @@ describe 'association_matcher' do
348
308
 
349
309
  # Defines a model, create a validation and returns a raw matcher
350
310
  def define_and_validate(options={})
351
- columns = options.delete(:association_columns) || { :task_id => :integer, :project_id => :integer }
352
- define_model :task, columns
311
+ columns = options.delete(:association_columns) || { :task_id => :integer, :project_id => :integer, :todo_id => :integer }
312
+ define_model :task, columns
313
+ define_model :todo, columns
353
314
 
354
315
  define_model :project_task, columns do
355
316
  belongs_to :task
356
- belongs_to :project
357
- end unless options.delete(:skip_through)
317
+ belongs_to :project
318
+ belongs_to :todo
319
+ end unless options.delete(:skip_source)
358
320
 
359
- @model = define_model :project, options.delete(:model_columns) || {} do
321
+ @model = define_model :project, options.delete(:model_columns) || {} do
322
+ has_many :project_tasks unless options.delete(:skip_through)
360
323
  has_many :tasks, options
361
- has_many :project_tasks
362
324
  end
363
325
 
364
326
  have_many :tasks
@@ -403,15 +365,28 @@ describe 'association_matcher' do
403
365
  end
404
366
 
405
367
  it 'should set through_exists? message' do
406
- matcher = define_and_validate(:through => 'project_tasks')
407
- matcher.through(:another).matches?(@model)
408
- matcher.failure_message.should == 'Expected Project records have many tasks through :another, through association does not exist'
409
- end
410
-
411
- it 'should set join_table_exists? message' do
412
- matcher = define_and_validate(:through => 'project_tasks', :skip_through => true)
368
+ matcher = define_and_validate(:through => :project_tasks, :skip_through => true)
369
+ matcher.through(:project_tasks).matches?(@model)
370
+ matcher.failure_message.should == 'Expected Project records have many tasks through :project_tasks, through association does not exist'
371
+ end
372
+
373
+ it 'should set source_exists? message' do
374
+ matcher = define_and_validate(:through => :project_tasks, :skip_source => true)
413
375
  matcher.through(:project_tasks).matches?(@model)
414
- matcher.failure_message.should == 'Expected join table "project_tasks" to exist, but does not'
376
+ matcher.failure_message.should == 'Expected Project records have many tasks through :project_tasks, source association does not exist'
377
+ end
378
+
379
+ it 'should set options_matches? message when dependent is given' do
380
+ matcher = define_and_validate(:dependent => :destroy)
381
+ matcher.dependent(:nullify).matches?(@model)
382
+ matcher.failure_message.should == 'Expected Project records have many tasks with options {:dependent=>"nullify"}, got {:dependent=>"destroy"}'
383
+ end
384
+
385
+ it 'should set options_matches? message when source is given' do
386
+ matcher = define_and_validate(:through => :project_tasks, :source => :todo)
387
+ matcher.through(:project_tasks).source(:task).matches?(@model)
388
+ matcher.failure_message.should match(/:source=>"task"/)
389
+ matcher.failure_message.should match(/:source=>"todo"/)
415
390
  end
416
391
  end
417
392
 
@@ -456,11 +431,16 @@ describe 'association_matcher' do
456
431
  end
457
432
 
458
433
  describe 'with through option' do
459
- it { should define_and_validate(:through => 'project_tasks') }
460
- it { should define_and_validate(:through => 'project_tasks').through(:project_tasks) }
434
+ it { should define_and_validate(:through => :project_tasks) }
435
+ it { should define_and_validate(:through => :project_tasks).through(:project_tasks) }
461
436
 
462
- it { should_not define_and_validate(:through => 'project_tasks').through(:something) }
463
- it { should_not define_and_validate(:through => 'project_tasks', :skip_through => true).through(:project_tasks) }
437
+ it { should_not define_and_validate(:through => :project_tasks).through(:something) }
438
+ it { should_not define_and_validate(:through => :project_tasks, :skip_through => true).through(:project_tasks) }
439
+ end
440
+
441
+ describe 'with source option' do
442
+ it { should define_and_validate(:through => :project_tasks, :source => :todo).source(:todo) }
443
+ it { should_not define_and_validate(:through => :project_tasks, :source => :todo).source(:task) }
464
444
  end
465
445
 
466
446
  create_optional_boolean_specs(:uniq, self)
@@ -470,7 +450,7 @@ describe 'association_matcher' do
470
450
  end
471
451
 
472
452
  describe 'macros' do
473
- before(:each){ define_and_validate(:through => 'project_tasks', :readonly => true, :validate => true) }
453
+ before(:each){ define_and_validate(:through => :project_tasks, :readonly => true, :validate => true) }
474
454
 
475
455
  should_have_many :tasks
476
456
  should_have_many :tasks, :readonly => true
@@ -487,17 +467,19 @@ describe 'association_matcher' do
487
467
 
488
468
  # Defines a model, create a validation and returns a raw matcher
489
469
  def define_and_validate(options={})
490
- columns = options.delete(:association_columns) || { :manager_id => :integer, :project_id => :integer }
491
- define_model :manager, columns
470
+ columns = options.delete(:association_columns) || { :manager_id => :integer, :project_id => :integer, :boss_id => :integer }
471
+ define_model :manager, columns
472
+ define_model :boss, columns
492
473
 
493
474
  define_model :project_manager, columns do
494
475
  belongs_to :manager
495
- belongs_to :project
496
- end unless options.delete(:skip_through)
476
+ belongs_to :project
477
+ belongs_to :boss
478
+ end unless options.delete(:skip_source)
497
479
 
498
- @model = define_model :project, options.delete(:model_columns) || {} do
480
+ @model = define_model :project, options.delete(:model_columns) || {} do
481
+ has_many :project_managers unless options.delete(:skip_through)
499
482
  has_one :manager, options
500
- has_many :project_managers
501
483
  end
502
484
 
503
485
  have_one :manager
@@ -536,15 +518,28 @@ describe 'association_matcher' do
536
518
  end
537
519
 
538
520
  it 'should set through_exists? message' do
539
- matcher = define_and_validate(:through => 'project_managers')
540
- matcher.through(:another).matches?(@model)
541
- matcher.failure_message.should == 'Expected Project records have one manager through :another, through association does not exist'
542
- end
543
-
544
- it 'should set join_table_exists? message' do
545
- matcher = define_and_validate(:through => 'project_managers', :skip_through => true)
521
+ matcher = define_and_validate(:through => :project_managers, :skip_through => true)
522
+ matcher.through(:project_managers).matches?(@model)
523
+ matcher.failure_message.should == 'Expected Project records have one manager through :project_managers, through association does not exist'
524
+ end
525
+
526
+ it 'should set source_exists? message' do
527
+ matcher = define_and_validate(:through => :project_managers, :skip_source => true)
546
528
  matcher.through(:project_managers).matches?(@model)
547
- matcher.failure_message.should == 'Expected join table "project_managers" to exist, but does not'
529
+ matcher.failure_message.should == 'Expected Project records have one manager through :project_managers, source association does not exist'
530
+ end
531
+
532
+ it 'should set options_matches? message when dependent is given' do
533
+ matcher = define_and_validate(:dependent => :destroy)
534
+ matcher.dependent(:nullify).matches?(@model)
535
+ matcher.failure_message.should == 'Expected Project records have one manager with options {:dependent=>"nullify"}, got {:dependent=>"destroy"}'
536
+ end
537
+
538
+ it 'should set options_matches? message when source is given' do
539
+ matcher = define_and_validate(:through => :project_managers, :source => :boss)
540
+ matcher.through(:project_managers).source(:manager).matches?(@model)
541
+ matcher.failure_message.should match(/:source=>"manager"/)
542
+ matcher.failure_message.should match(/:source=>"boss"/)
548
543
  end
549
544
  end
550
545
 
@@ -589,11 +584,16 @@ describe 'association_matcher' do
589
584
  end
590
585
 
591
586
  describe 'with through option' do
592
- it { should define_and_validate(:through => 'project_managers') }
593
- it { should define_and_validate(:through => 'project_managers').through(:project_managers) }
587
+ it { should define_and_validate(:through => :project_managers) }
588
+ it { should define_and_validate(:through => :project_managers).through(:project_managers) }
594
589
 
595
- it { should_not define_and_validate(:through => 'project_managers').through(:something) }
596
- it { should_not define_and_validate(:through => 'project_managers', :skip_through => true).through(:project_managers) }
590
+ it { should_not define_and_validate(:through => :project_managers).through(:something) }
591
+ it { should_not define_and_validate(:through => :project_managers, :skip_through => true).through(:project_managers) }
592
+ end
593
+
594
+ describe 'with source option' do
595
+ it { should define_and_validate(:through => :project_managers, :source => :boss).source(:boss) }
596
+ it { should_not define_and_validate(:through => :project_managers, :source => :boss).source(:manager) }
597
597
  end
598
598
 
599
599
  create_optional_boolean_specs(:validate, self)
@@ -601,7 +601,7 @@ describe 'association_matcher' do
601
601
  end
602
602
 
603
603
  describe 'macros' do
604
- before(:each){ define_and_validate(:through => 'project_managers', :validate => true) }
604
+ before(:each){ define_and_validate(:through => :project_managers, :validate => true) }
605
605
 
606
606
  should_have_one :manager
607
607
  should_have_one :manager, :validate => true
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: remarkable_activerecord
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.4
4
+ version: 3.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carlos Brando
@@ -11,7 +11,7 @@ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
13
 
14
- date: 2009-04-18 00:00:00 +02:00
14
+ date: 2009-04-20 00:00:00 +02:00
15
15
  default_executable:
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
@@ -22,7 +22,7 @@ dependencies:
22
22
  requirements:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
- version: 3.0.4
25
+ version: 3.0.5
26
26
  version:
27
27
  description: "Remarkable ActiveRecord: collection of matchers and macros with I18n for ActiveRecord"
28
28
  email: