remarkable_activerecord 3.0.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/CHANGELOG +47 -0
- data/LICENSE +20 -0
- data/README +2 -0
- data/lib/remarkable_activerecord/base.rb +238 -0
- data/lib/remarkable_activerecord/human_names.rb +37 -0
- data/lib/remarkable_activerecord/matchers/allow_mass_assignment_of_matcher.rb +34 -0
- data/lib/remarkable_activerecord/matchers/allow_values_for_matcher.rb +94 -0
- data/lib/remarkable_activerecord/matchers/association_matcher.rb +235 -0
- data/lib/remarkable_activerecord/matchers/have_column_matcher.rb +68 -0
- data/lib/remarkable_activerecord/matchers/have_index_matcher.rb +57 -0
- data/lib/remarkable_activerecord/matchers/have_readonly_attributes_matcher.rb +30 -0
- data/lib/remarkable_activerecord/matchers/have_scope_matcher.rb +80 -0
- data/lib/remarkable_activerecord/matchers/validate_acceptance_of_matcher.rb +51 -0
- data/lib/remarkable_activerecord/matchers/validate_associated_matcher.rb +99 -0
- data/lib/remarkable_activerecord/matchers/validate_confirmation_of_matcher.rb +45 -0
- data/lib/remarkable_activerecord/matchers/validate_exclusion_of_matcher.rb +47 -0
- data/lib/remarkable_activerecord/matchers/validate_inclusion_of_matcher.rb +47 -0
- data/lib/remarkable_activerecord/matchers/validate_length_of_matcher.rb +123 -0
- data/lib/remarkable_activerecord/matchers/validate_numericality_of_matcher.rb +184 -0
- data/lib/remarkable_activerecord/matchers/validate_presence_of_matcher.rb +29 -0
- data/lib/remarkable_activerecord/matchers/validate_uniqueness_of_matcher.rb +151 -0
- data/lib/remarkable_activerecord.rb +29 -0
- data/locale/en.yml +253 -0
- data/spec/allow_mass_assignment_of_matcher_spec.rb +57 -0
- data/spec/allow_values_for_matcher_spec.rb +56 -0
- data/spec/association_matcher_spec.rb +616 -0
- data/spec/have_column_matcher_spec.rb +73 -0
- data/spec/have_index_matcher_spec.rb +68 -0
- data/spec/have_readonly_attributes_matcher_spec.rb +47 -0
- data/spec/have_scope_matcher_spec.rb +69 -0
- data/spec/model_builder.rb +101 -0
- data/spec/rcov.opts +2 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +27 -0
- data/spec/validate_acceptance_of_matcher_spec.rb +68 -0
- data/spec/validate_associated_matcher_spec.rb +122 -0
- data/spec/validate_confirmation_of_matcher_spec.rb +58 -0
- data/spec/validate_exclusion_of_matcher_spec.rb +88 -0
- data/spec/validate_inclusion_of_matcher_spec.rb +84 -0
- data/spec/validate_length_of_matcher_spec.rb +165 -0
- data/spec/validate_numericality_of_matcher_spec.rb +180 -0
- data/spec/validate_presence_of_matcher_spec.rb +52 -0
- data/spec/validate_uniqueness_of_matcher_spec.rb +150 -0
- metadata +112 -0
data/locale/en.yml
ADDED
@@ -0,0 +1,253 @@
|
|
1
|
+
en:
|
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}}"
|
6
|
+
|
7
|
+
allow_values_for:
|
8
|
+
description: "allow {{in}} as values for {{attributes}}"
|
9
|
+
expectations:
|
10
|
+
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
|
+
allow_mass_assignment_of:
|
20
|
+
description: "allow mass assignment of {{attributes}}"
|
21
|
+
expectations:
|
22
|
+
is_protected: "{{subject_name}} to allow mass assignment of {{attribute}} ({{subject_name}} is protecting {{attribute}})"
|
23
|
+
is_accessible: "{{subject_name}} to allow mass assignment of {{attribute}} ({{subject_name}} has not made {{attribute}} accessible)"
|
24
|
+
|
25
|
+
association:
|
26
|
+
belongs_to: belong to
|
27
|
+
has_many: have many
|
28
|
+
has_and_belongs_to_many: have and belong to many
|
29
|
+
has_one: have one
|
30
|
+
description: "{{macro}} {{associations}}"
|
31
|
+
expectations:
|
32
|
+
association_exists: "{{subject_name}} records {{macro}} {{association}}, got no association"
|
33
|
+
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"
|
37
|
+
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}}"
|
51
|
+
optionals:
|
52
|
+
through:
|
53
|
+
positive: "through {{value}}"
|
54
|
+
class_name:
|
55
|
+
positive: "with class name {{inspect}}"
|
56
|
+
foreign_key:
|
57
|
+
positive: "with foreign key {{inspect}}"
|
58
|
+
dependent:
|
59
|
+
positive: "with dependent {{inspect}}"
|
60
|
+
join_table:
|
61
|
+
positive: "with join table {{inspect}}"
|
62
|
+
uniq:
|
63
|
+
positive: "with unique records"
|
64
|
+
negative: "without unique records"
|
65
|
+
readonly:
|
66
|
+
positive: "with readonly records"
|
67
|
+
negative: "without readonly records"
|
68
|
+
validate:
|
69
|
+
positive: "validating associated records"
|
70
|
+
negative: "not validating associated records"
|
71
|
+
autosave:
|
72
|
+
positive: "autosaving associated records"
|
73
|
+
negative: "not autosaving associated records"
|
74
|
+
polymorphic:
|
75
|
+
positive: "through a polymorphic interface"
|
76
|
+
as:
|
77
|
+
positive: "through the polymorphic interface {{inspect}}"
|
78
|
+
counter_cache:
|
79
|
+
positive: "with counter cache {{inspect}}"
|
80
|
+
negative: "without counter cache"
|
81
|
+
|
82
|
+
have_column:
|
83
|
+
description: "have column(s) named {{columns}}"
|
84
|
+
expectations:
|
85
|
+
column_exists: "{{subject_name}} to have column named {{column}}"
|
86
|
+
options_match: "{{subject_name}} to have column {{column}} with options {{options}}, got {{actual}}"
|
87
|
+
optionals:
|
88
|
+
type:
|
89
|
+
positive: "with type {{inspect}}"
|
90
|
+
null:
|
91
|
+
positive: "allowing null values"
|
92
|
+
negative: "not allowing null values"
|
93
|
+
default:
|
94
|
+
positive: "with default {{inspect}}"
|
95
|
+
negative: "with default {{inspect}}"
|
96
|
+
limit:
|
97
|
+
positive: "with limit {{inspect}}"
|
98
|
+
|
99
|
+
have_index:
|
100
|
+
description: "have index for column(s) {{columns}}"
|
101
|
+
expectations:
|
102
|
+
index_exists: "index {{column}} to exist on table {{table_name}}"
|
103
|
+
is_unique: "index on {{column}} with unique equals to {{unique}}, got {{actual}}"
|
104
|
+
optionals:
|
105
|
+
unique:
|
106
|
+
positive: "with unique values"
|
107
|
+
negative: "with non unique values"
|
108
|
+
|
109
|
+
have_readonly_attributes:
|
110
|
+
description: "make {{attributes}} read-only"
|
111
|
+
expectations:
|
112
|
+
is_readonly: "{{subject_name}} to make {{attribute}} read-only, got {{actual}}"
|
113
|
+
|
114
|
+
have_scope:
|
115
|
+
description: "have to scope itself to {{options}} when {{scope_name}} is called"
|
116
|
+
expectations:
|
117
|
+
is_scope: "{{scope_name}} when called on {{subject_name}} return a ActiveRecord::NamedScope::Scope object"
|
118
|
+
options_match: "{{scope_name}} when called on {{subject_name}} scope to {{options}}, got {{actual}}"
|
119
|
+
optionals:
|
120
|
+
with:
|
121
|
+
positive: "with {{inspect}} as argument"
|
122
|
+
|
123
|
+
validate_acceptance_of:
|
124
|
+
description: "require {{attributes}} to be accepted"
|
125
|
+
expectations:
|
126
|
+
requires_acceptance: "{{subject_name}} to be invalid if {{attribute}} is not accepted"
|
127
|
+
accept_is_valid: "{{subject_name}} to be valid when {{attribute}} is accepted with value {{accept}}"
|
128
|
+
optionals:
|
129
|
+
accept:
|
130
|
+
positive: "with value {{inspect}}"
|
131
|
+
allow_nil:
|
132
|
+
positive: "allowing nil values"
|
133
|
+
negative: "not allowing nil values"
|
134
|
+
|
135
|
+
validate_associated:
|
136
|
+
description: "require associated {{associations}} to be valid"
|
137
|
+
expectations:
|
138
|
+
is_valid: "{{subject_name}} to be invalid when {{association}} is invalid"
|
139
|
+
|
140
|
+
validate_confirmation_of:
|
141
|
+
description: "require {{attributes}} to be confirmed"
|
142
|
+
expectations:
|
143
|
+
responds_to_confirmation: "{{subject_name}} instance responds to {{attribute}}_confirmation"
|
144
|
+
confirms: "{{subject_name}} to be valid only when {{attribute}} is confirmed"
|
145
|
+
|
146
|
+
validate_exclusion_of:
|
147
|
+
description: "ensure exclusion of {{attributes}} in {{in}}"
|
148
|
+
expectations:
|
149
|
+
is_valid: "{{subject_name}} to be valid when {{attribute}} is set to {{value}}"
|
150
|
+
is_invalid: "{{subject_name}} to be invalid when {{attribute}} is set to {{value}}"
|
151
|
+
optionals:
|
152
|
+
allow_nil:
|
153
|
+
positive: "allowing nil values"
|
154
|
+
negative: "not allowing nil values"
|
155
|
+
allow_blank:
|
156
|
+
positive: "allowing blank values"
|
157
|
+
negative: "not allowing blank values"
|
158
|
+
|
159
|
+
validate_inclusion_of:
|
160
|
+
description: "ensure inclusion of {{attributes}} in {{in}}"
|
161
|
+
expectations:
|
162
|
+
is_valid: "{{subject_name}} to be valid when {{attribute}} is set to {{value}}"
|
163
|
+
is_invalid: "{{subject_name}} to be invalid when {{attribute}} is set to {{value}}"
|
164
|
+
optionals:
|
165
|
+
allow_nil:
|
166
|
+
positive: "allowing nil values"
|
167
|
+
negative: "not allowing nil values"
|
168
|
+
allow_blank:
|
169
|
+
positive: "allowing blank values"
|
170
|
+
negative: "not allowing blank values"
|
171
|
+
|
172
|
+
validate_length_of:
|
173
|
+
description: "ensure length of {{attributes}}"
|
174
|
+
expectations:
|
175
|
+
less_than_min_length: "{{subject_name}} to be invalid when {{attribute}} length is less than {{minimum}} characters"
|
176
|
+
exactly_min_length: "{{subject_name}} to be valid when {{attribute}} length is {{minimum}} characters"
|
177
|
+
more_than_max_length: "{{subject_name}} to be invalid when {{attribute}} length is more than {{maximum}} characters"
|
178
|
+
exactly_max_length: "{{subject_name}} to be valid when {{attribute}} length is {{maximum}} characters"
|
179
|
+
optionals:
|
180
|
+
within:
|
181
|
+
positive: "is within {{inspect}} characters"
|
182
|
+
maximum:
|
183
|
+
positive: "is maximum {{inspect}} characters"
|
184
|
+
minimum:
|
185
|
+
positive: "is minimum {{inspect}} characters"
|
186
|
+
is:
|
187
|
+
positive: "is equal to {{inspect}} characters"
|
188
|
+
allow_nil:
|
189
|
+
positive: "allowing nil values"
|
190
|
+
negative: "not allowing nil values"
|
191
|
+
allow_blank:
|
192
|
+
positive: "allowing blank values"
|
193
|
+
negative: "not allowing blank values"
|
194
|
+
|
195
|
+
validate_numericality_of:
|
196
|
+
description: "ensure numericality of {{attributes}}"
|
197
|
+
expectations:
|
198
|
+
only_numeric_values: "{{subject_name}} to allow only numeric values for {{attribute}}"
|
199
|
+
only_integer: "{{subject_name}} to {{not}}allow only integer values for {{attribute}}"
|
200
|
+
only_even: "{{subject_name}} to allow only even values for {{attribute}}"
|
201
|
+
only_odd: "{{subject_name}} to allow only odd values for {{attribute}}"
|
202
|
+
equals_to: "{{subject_name}} to be valid only when {{attribute}} is equal to {{count}}"
|
203
|
+
more_than_maximum: "{{subject_name}} to be invalid when {{attribute}} is greater than {{count}}"
|
204
|
+
less_than_minimum: "{{subject_name}} to be invalid when {{attribute}} is less than {{count}}"
|
205
|
+
optionals:
|
206
|
+
only_integer:
|
207
|
+
positive: "allowing only integer values"
|
208
|
+
odd:
|
209
|
+
positive: "allowing only odd values"
|
210
|
+
even:
|
211
|
+
positive: "allowing only even values"
|
212
|
+
equal_to:
|
213
|
+
positive: "is equal to {{inspect}}"
|
214
|
+
less_than:
|
215
|
+
positive: "is less than {{inspect}}"
|
216
|
+
greater_than:
|
217
|
+
positive: "is greater than {{inspect}}"
|
218
|
+
less_than_or_equal_to:
|
219
|
+
positive: "is less than or equal to {{inspect}}"
|
220
|
+
greater_than_or_equal_to:
|
221
|
+
positive: "is greater than or equal to {{inspect}}"
|
222
|
+
allow_nil:
|
223
|
+
positive: "allowing nil values"
|
224
|
+
negative: "not allowing nil values"
|
225
|
+
allow_blank:
|
226
|
+
positive: "allowing blank values"
|
227
|
+
negative: "not allowing blank values"
|
228
|
+
|
229
|
+
validate_presence_of:
|
230
|
+
description: "require {{attributes}} to be set"
|
231
|
+
expectations:
|
232
|
+
allow_nil: "{{subject_name}} to require {{attribute}} to be set"
|
233
|
+
|
234
|
+
validate_uniqueness_of:
|
235
|
+
description: "require unique values for {{attributes}}"
|
236
|
+
expectations:
|
237
|
+
responds_to_scope: "{{subject_name}} instance responds to {{method}}"
|
238
|
+
is_unique: "{{subject_name}} to require unique values for {{attribute}}"
|
239
|
+
case_sensitive: "{{subject_name}} to {{not}}be case sensitive on {{attribute}} validation"
|
240
|
+
valid_with_new_scope: "{{subject_name}} to be valid when {{attribute}} scope ({{method}}) change"
|
241
|
+
optionals:
|
242
|
+
scope:
|
243
|
+
positive: "scoped to {{inspect}}"
|
244
|
+
case_sensitive:
|
245
|
+
positive: "case sensitive"
|
246
|
+
negative: "case insensitive"
|
247
|
+
allow_nil:
|
248
|
+
positive: "allowing nil values"
|
249
|
+
negative: "not allowing nil values"
|
250
|
+
allow_blank:
|
251
|
+
positive: "allowing blank values"
|
252
|
+
negative: "not allowing blank values"
|
253
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe 'allow_mass_assignment_of' do
|
4
|
+
include ModelBuilder
|
5
|
+
|
6
|
+
def define_and_validate(options={})
|
7
|
+
@model = define_model :product, :title => :string, :category => :string do
|
8
|
+
attr_protected :title, :category if options[:protected]
|
9
|
+
|
10
|
+
attr_accessible :title, :category if options[:accessible] == true
|
11
|
+
attr_accessible *options[:accessible] if options[:accessible].is_a?(Array)
|
12
|
+
end
|
13
|
+
|
14
|
+
allow_mass_assignment_of(:title, :category)
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'messages' do
|
18
|
+
|
19
|
+
it 'should contain a description' do
|
20
|
+
@matcher = allow_mass_assignment_of(:title, :category)
|
21
|
+
@matcher.description.should == 'allow mass assignment of title and category'
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should set is_protected? message' do
|
25
|
+
@matcher = define_and_validate(:protected => true)
|
26
|
+
@matcher.matches?(@model)
|
27
|
+
@matcher.failure_message.should == 'Expected Product to allow mass assignment of title (Product is protecting title)'
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should set is_accessible? message' do
|
31
|
+
@matcher = define_and_validate(:accessible => [:another])
|
32
|
+
@matcher.matches?(@model)
|
33
|
+
@matcher.failure_message.should == 'Expected Product to allow mass assignment of title (Product has not made title accessible)'
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
describe 'matchers' do
|
39
|
+
it { should define_and_validate }
|
40
|
+
it { should define_and_validate(:accessible => true) }
|
41
|
+
|
42
|
+
it { should_not define_and_validate(:protected => true) }
|
43
|
+
it { should_not define_and_validate(:accessible => [:another]) }
|
44
|
+
end
|
45
|
+
|
46
|
+
describe 'macros' do
|
47
|
+
before(:each){ define_and_validate(:accessible => true) }
|
48
|
+
|
49
|
+
should_allow_mass_assignment_of :title
|
50
|
+
should_allow_mass_assignment_of :category
|
51
|
+
should_allow_mass_assignment_of :title, :category
|
52
|
+
|
53
|
+
should_not_allow_mass_assignment_of :another
|
54
|
+
should_not_allow_mass_assignment_of :title, :another
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe 'allow_values_for' do
|
4
|
+
include ModelBuilder
|
5
|
+
|
6
|
+
# Defines a model, create a validation and returns a raw matcher
|
7
|
+
def define_and_validate(options={})
|
8
|
+
@model = define_model :product, :title => :string, :category => :string do
|
9
|
+
validates_format_of :title, options
|
10
|
+
end
|
11
|
+
|
12
|
+
allow_values_for(:title)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'messages' do
|
16
|
+
before(:each){ @matcher = define_and_validate(:with => /X|Y|Z/) }
|
17
|
+
|
18
|
+
it 'should contain a description' do
|
19
|
+
@matcher = allow_values_for(:title, "X", "Y", "Z")
|
20
|
+
@matcher.description.should == 'allow "X", "Y", and "Z" as values for title'
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should set is_valid? message' do
|
24
|
+
@matcher.in("A").matches?(@model)
|
25
|
+
@matcher.failure_message.should == 'Expected Product to be valid when title is set to "A"'
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should set allow_nil? message' do
|
29
|
+
@matcher.allow_nil.matches?(@model)
|
30
|
+
@matcher.failure_message.should == 'Expected Product to allow nil values for title'
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should set allow_blank? message' do
|
34
|
+
@matcher.allow_blank.matches?(@model)
|
35
|
+
@matcher.failure_message.should == 'Expected Product to allow blank values for title'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe 'matchers' do
|
40
|
+
it { should define_and_validate(:with => /X|Y|Z/).in('X', 'Y', 'Z') }
|
41
|
+
it { should_not define_and_validate(:with => /X|Y|Z/).in('A') }
|
42
|
+
|
43
|
+
it { should define_and_validate(:with => /X|Y|Z/, :message => 'valid').in('X', 'Y', 'Z').message('valid') }
|
44
|
+
|
45
|
+
create_optional_boolean_specs(:allow_nil, self, :with => /X|Y|Z/)
|
46
|
+
create_optional_boolean_specs(:allow_blank, self, :with => /X|Y|Z/)
|
47
|
+
end
|
48
|
+
|
49
|
+
describe 'macros' do
|
50
|
+
before(:each){ define_and_validate(:with => /X|Y|Z/) }
|
51
|
+
|
52
|
+
should_allow_values_for :title, 'X'
|
53
|
+
should_not_allow_values_for :title, 'A'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|