remarkable_activerecord 3.0.4 → 3.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README +7 -3
- data/lib/remarkable_activerecord/base.rb +2 -16
- data/lib/remarkable_activerecord/matchers/association_matcher.rb +61 -47
- data/locale/en.yml +40 -64
- data/spec/association_matcher_spec.rb +85 -85
- metadata +3 -3
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, :
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
34
|
-
::ActiveRecord::Base.connection.tables.include?(
|
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
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
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
|
99
|
-
|
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
|
-
|
5
|
-
|
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
|
-
|
36
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
-
|
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 =>
|
407
|
-
matcher.through(:
|
408
|
-
matcher.failure_message.should == 'Expected Project records have many tasks through :
|
409
|
-
end
|
410
|
-
|
411
|
-
it 'should set
|
412
|
-
matcher = define_and_validate(:through =>
|
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
|
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 =>
|
460
|
-
it { should define_and_validate(:through =>
|
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 =>
|
463
|
-
it { should_not define_and_validate(:through =>
|
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 =>
|
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
|
-
|
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 =>
|
540
|
-
matcher.through(:
|
541
|
-
matcher.failure_message.should == 'Expected Project records have one manager through :
|
542
|
-
end
|
543
|
-
|
544
|
-
it 'should set
|
545
|
-
matcher = define_and_validate(:through =>
|
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
|
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 =>
|
593
|
-
it { should define_and_validate(:through =>
|
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 =>
|
596
|
-
it { should_not define_and_validate(:through =>
|
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 =>
|
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
|
+
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-
|
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.
|
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:
|