remarkable_activerecord 3.1.6 → 3.1.7
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 +97 -95
- data/lib/remarkable_activerecord/base.rb +12 -3
- data/lib/remarkable_activerecord/describe.rb +10 -3
- data/lib/remarkable_activerecord/matchers/allow_mass_assignment_of_matcher.rb +40 -27
- data/lib/remarkable_activerecord/matchers/allow_values_for_matcher.rb +24 -18
- data/lib/remarkable_activerecord/matchers/association_matcher.rb +75 -75
- data/lib/remarkable_activerecord/matchers/have_scope_matcher.rb +5 -5
- data/lib/remarkable_activerecord/matchers/validate_exclusion_of_matcher.rb +9 -9
- data/lib/remarkable_activerecord/matchers/validate_inclusion_of_matcher.rb +9 -9
- data/lib/remarkable_activerecord/matchers/validate_length_of_matcher.rb +32 -32
- data/locale/en.yml +57 -57
- data/spec/allow_mass_assignment_of_matcher_spec.rb +21 -21
- data/spec/allow_values_for_matcher_spec.rb +7 -7
- data/spec/describe_spec.rb +2 -2
- data/spec/validate_length_of_matcher_spec.rb +25 -25
- metadata +3 -3
data/CHANGELOG
CHANGED
@@ -1,98 +1,100 @@
|
|
1
|
-
*
|
1
|
+
* Ensure quick subject bypass protected attributes [#87]
|
2
2
|
|
3
|
-
*
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
*
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
* Bug fix when a symbol is given has join table to habtm association [#75]
|
24
|
-
|
25
|
-
* Association matchers now searches in the right database for tables [#73]
|
26
|
-
|
27
|
-
* validate_length_of accepts :with_kind_of to enable it to work with associations [#69]
|
28
|
-
In your Post specs now you can write:
|
29
|
-
|
30
|
-
should_validate_length_of :comments, :maximum => 10, :with_kind_of => Comment
|
31
|
-
|
32
|
-
# v3.1
|
33
|
-
|
34
|
-
* Allow validate_presence_of to work with associations [#63]
|
35
|
-
|
36
|
-
* Allow validate_uniqueness_of to work when scopes are not stringfiable values.
|
37
|
-
You can now give timestamps, datetime, date and boolean as scopes [#60]
|
38
|
-
|
39
|
-
* Allow subjects to be overwriten quickly (quick subjects):
|
40
|
-
|
41
|
-
describe Post
|
42
|
-
should_validate_presente_of :title
|
43
|
-
|
44
|
-
describe :published => true do
|
45
|
-
should_validate_presence_of :published_at
|
46
|
-
end
|
3
|
+
* Added :token and :separator to deal with :tokenizer in validates_length_of [#77]
|
4
|
+
|
5
|
+
* Deprecated validate_format_of. It does not have the same API as the respective
|
6
|
+
ActiveRecord macro, raising questions frequentely about its usage [#76]
|
7
|
+
|
8
|
+
* allow_mass_assignment_of when called without arguments checks if any mass
|
9
|
+
assignment is possible [#80]
|
10
|
+
|
11
|
+
* Add :table_name option to have_index (thanks to Lawrence Pit) [#79]
|
12
|
+
|
13
|
+
* Allow default subject attributes to be given [#74]
|
14
|
+
You can even mix with a fixture replacement tool and still use quick subjects:
|
15
|
+
|
16
|
+
describe Post
|
17
|
+
# Fixjour example
|
18
|
+
subject_attributes { valid_post_attributes }
|
19
|
+
|
20
|
+
describe :published => true do
|
21
|
+
should_validate_presence_of :published_at
|
22
|
+
end
|
47
23
|
end
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
24
|
+
|
25
|
+
* Bug fix when a symbol is given has join table to habtm association [#75]
|
26
|
+
|
27
|
+
* Association matchers now searches in the right database for tables [#73]
|
28
|
+
|
29
|
+
* validate_length_of accepts :with_kind_of to enable it to work with associations [#69]
|
30
|
+
In your Post specs now you can write:
|
31
|
+
|
32
|
+
should_validate_length_of :comments, :maximum => 10, :with_kind_of => Comment
|
33
|
+
|
34
|
+
# v3.1
|
35
|
+
|
36
|
+
* Allow validate_presence_of to work with associations [#63]
|
37
|
+
|
38
|
+
* Allow validate_uniqueness_of to work when scopes are not stringfiable values.
|
39
|
+
You can now give timestamps, datetime, date and boolean as scopes [#60]
|
40
|
+
|
41
|
+
* Allow subjects to be overwriten quickly (quick subjects):
|
42
|
+
|
43
|
+
describe Post
|
44
|
+
should_validate_presente_of :title
|
45
|
+
|
46
|
+
describe :published => true do
|
47
|
+
should_validate_presence_of :published_at
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
Is the same as:
|
52
|
+
|
53
|
+
describe Post
|
54
|
+
should_validate_presente_of :title
|
55
|
+
|
56
|
+
describe "when published is true" do
|
57
|
+
subject { Post.new(:published => true) }
|
58
|
+
should_validate_presence_of :published_at
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
And the string can be also localized using I18n [#57]
|
63
|
+
|
64
|
+
[COMPATIBILITY] validate_associated no longer accepts a block to confgure the
|
65
|
+
builder:
|
66
|
+
|
67
|
+
should_validate_associated(:tasks){ |p| p.tasks.build(:captcha => 'i_am_a_robot') }
|
68
|
+
|
69
|
+
The right way to do this is by giving an option called builder and a proc:
|
70
|
+
|
71
|
+
should_validate_associated :tasks, :builder => proc{ |p| p.tasks.build(:captcha => 'i_am_a_robot') }
|
72
|
+
|
73
|
+
* validate_uniqueness_of and accept_nested_attributes_for now use the new
|
74
|
+
interpolation option {{sentence}} [#58]
|
75
|
+
|
76
|
+
* Added accept_nested_attributes_for matcher [#39]
|
77
|
+
|
78
|
+
* Added have_default_scope matcher [#38]
|
79
|
+
|
80
|
+
* Allow :conditions, :include, :joins, :limit, :offset, :order, :select, :readonly,
|
81
|
+
:group, :having, :from, :lock as quick accessors to have_scope matcher
|
82
|
+
|
83
|
+
* Allow all kind of objects to be sent to have_scope (including datetimes, arrays,
|
84
|
+
booleans and nil) (thanks to Szymon Nowak and Nolan Eakins) [#53]
|
85
|
+
|
86
|
+
* Added support to sql options in association_matcher: select, conditions, include,
|
87
|
+
group, having, order, limit and offset, plus finder_sql and counter_sql. [#48]
|
88
|
+
|
89
|
+
* :source and :source_type are now supported by association matcher [#47]
|
90
|
+
|
91
|
+
* validate_inclusion_of became smarter since it now tests invalid values too [#36]
|
92
|
+
|
93
|
+
* Fixed three bugs in validate_uniqueness_of matcher [#42] [#40] [#37]
|
94
|
+
|
93
95
|
# v3.0
|
94
96
|
|
95
|
-
* Added more options to associations matcher. Previously it was handling just
|
97
|
+
* Added more options to associations matcher. Previously it was handling just
|
96
98
|
:dependent and :through options. Now it deals with:
|
97
99
|
|
98
100
|
:through, :class_name, :foreign_key, :dependent, :join_table, :uniq,
|
@@ -130,9 +132,9 @@ subject definitions on rspec. This was also fixed.
|
|
130
132
|
|
131
133
|
# v2.x
|
132
134
|
|
133
|
-
* Added associations, allow_mass_assignment, allow_values_for, have_column,
|
134
|
-
have_index, have_scope, have_readonly_attributes, validate_acceptance_of,
|
135
|
-
validate_associated, validate_confirmation_of, validate_exclusion_of,
|
136
|
-
validate_inclusion_of, validate_length_of, validate_numericality_of,
|
135
|
+
* Added associations, allow_mass_assignment, allow_values_for, have_column,
|
136
|
+
have_index, have_scope, have_readonly_attributes, validate_acceptance_of,
|
137
|
+
validate_associated, validate_confirmation_of, validate_exclusion_of,
|
138
|
+
validate_inclusion_of, validate_length_of, validate_numericality_of,
|
137
139
|
validate_presence_of and validate_uniqueness_of matchers.
|
138
140
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module Remarkable
|
2
2
|
module ActiveRecord
|
3
|
-
class Base < Remarkable::Base
|
3
|
+
class Base < Remarkable::Base
|
4
|
+
I18N_COLLECTION = [ :attributes, :associations ]
|
4
5
|
|
5
6
|
# Provides a way to send options to all ActiveRecord matchers.
|
6
7
|
#
|
@@ -206,12 +207,14 @@ module Remarkable
|
|
206
207
|
@spec.send(:described_class)
|
207
208
|
end
|
208
209
|
|
209
|
-
if
|
210
|
+
if i18n_collection? && described_class.respond_to?(:human_attribute_name)
|
210
211
|
options = {}
|
211
212
|
|
212
213
|
collection_name = self.class.matcher_arguments[:collection].to_sym
|
213
214
|
if collection = instance_variable_get("@#{collection_name}")
|
214
|
-
collection.map
|
215
|
+
collection = collection.map do |attr|
|
216
|
+
described_class.human_attribute_name(attr.to_s, :locale => Remarkable.locale).downcase
|
217
|
+
end
|
215
218
|
options[collection_name] = array_to_sentence(collection)
|
216
219
|
end
|
217
220
|
|
@@ -225,6 +228,12 @@ module Remarkable
|
|
225
228
|
else
|
226
229
|
super
|
227
230
|
end
|
231
|
+
end
|
232
|
+
|
233
|
+
# Returns true if the given collection should be translated.
|
234
|
+
#
|
235
|
+
def i18n_collection? #:nodoc:
|
236
|
+
RAILS_I18N && I18N_COLLECTION.include?(self.class.matcher_arguments[:collection])
|
228
237
|
end
|
229
238
|
|
230
239
|
end
|
@@ -137,7 +137,7 @@ module Remarkable
|
|
137
137
|
#
|
138
138
|
example_group = super(*args) do
|
139
139
|
write_inheritable_hash(:describe_subject_attributes, attributes)
|
140
|
-
|
140
|
+
set_described_subject!
|
141
141
|
instance_eval(&block)
|
142
142
|
end
|
143
143
|
else
|
@@ -160,9 +160,16 @@ module Remarkable
|
|
160
160
|
#
|
161
161
|
def subject_attributes(options=nil, &block)
|
162
162
|
write_inheritable_attribute(:default_subject_attributes, options || block)
|
163
|
-
|
163
|
+
set_described_subject!
|
164
164
|
end
|
165
165
|
|
166
|
+
def set_described_subject!
|
167
|
+
subject {
|
168
|
+
record = self.class.described_class.new
|
169
|
+
record.send(:attributes=, subject_attributes, false)
|
170
|
+
record
|
171
|
+
}
|
172
|
+
end
|
166
173
|
end
|
167
174
|
|
168
175
|
# Returns a hash with the subject attributes declared using the
|
@@ -186,7 +193,7 @@ module Remarkable
|
|
186
193
|
|
187
194
|
default.merge(self.class.describe_subject_attributes || {})
|
188
195
|
end
|
189
|
-
|
196
|
+
|
190
197
|
end
|
191
198
|
end
|
192
199
|
end
|
@@ -3,18 +3,18 @@ module Remarkable
|
|
3
3
|
module Matchers
|
4
4
|
class AllowMassAssignmentOfMatcher < Remarkable::ActiveRecord::Base #:nodoc:
|
5
5
|
arguments :collection => :attributes, :as => :attribute
|
6
|
-
|
6
|
+
|
7
7
|
assertion :allows?
|
8
8
|
collection_assertions :is_protected?, :is_accessible?
|
9
9
|
|
10
10
|
protected
|
11
|
-
|
12
|
-
# If no attribute is given, check if no attribute is being protected,
|
13
|
-
# otherwise it fails.
|
14
|
-
#
|
15
|
-
def allows?
|
16
|
-
!@attributes.empty? || protected_attributes.empty?
|
17
|
-
end
|
11
|
+
|
12
|
+
# If no attribute is given, check if no attribute is being protected,
|
13
|
+
# otherwise it fails.
|
14
|
+
#
|
15
|
+
def allows?
|
16
|
+
!@attributes.empty? || protected_attributes.empty?
|
17
|
+
end
|
18
18
|
|
19
19
|
def is_protected?
|
20
20
|
protected_attributes.empty? || !protected_attributes.include?(@attribute.to_s)
|
@@ -22,28 +22,41 @@ module Remarkable
|
|
22
22
|
|
23
23
|
def is_accessible?
|
24
24
|
accessible_attributes.empty? || accessible_attributes.include?(@attribute.to_s)
|
25
|
-
end
|
26
|
-
|
27
|
-
def interpolation_options
|
28
|
-
if @subject
|
29
|
-
{ :protected_attributes => array_to_sentence(protected_attributes.to_a, false, '[]') }
|
30
|
-
else
|
31
|
-
{}
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def accessible_attributes
|
38
|
-
@accessible_attributes ||= subject_class.accessible_attributes || []
|
39
|
-
end
|
40
|
-
|
41
|
-
def protected_attributes
|
42
|
-
@protected_attributes ||= subject_class.protected_attributes || []
|
25
|
+
end
|
26
|
+
|
27
|
+
def interpolation_options
|
28
|
+
if @subject
|
29
|
+
{ :protected_attributes => array_to_sentence(protected_attributes.to_a, false, '[]') }
|
30
|
+
else
|
31
|
+
{}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def accessible_attributes
|
38
|
+
@accessible_attributes ||= subject_class.accessible_attributes || []
|
39
|
+
end
|
40
|
+
|
41
|
+
def protected_attributes
|
42
|
+
@protected_attributes ||= subject_class.protected_attributes || []
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
# Ensures that the attribute can be set on mass update.
|
46
|
+
# Ensures that the attribute can be set on mass update.
|
47
|
+
#
|
48
|
+
# Beware that when used in the negative form, this matcher fails if any of
|
49
|
+
# the values fail. For example, let's assume we have a accessible and a
|
50
|
+
# protected attribute called :accessible and :protected. The following
|
51
|
+
# assertion WILL pass:
|
52
|
+
#
|
53
|
+
# should_not_allow_mass_assignment_of :protected, :accessible
|
54
|
+
#
|
55
|
+
# If you want to assert that all values fail, you have to do:
|
56
|
+
#
|
57
|
+
# %w(first_protected second_protected).each do |protected|
|
58
|
+
# should_not_allow_mass_assignment_of protected
|
59
|
+
# end
|
47
60
|
#
|
48
61
|
# == Examples
|
49
62
|
#
|
@@ -63,10 +63,19 @@ module Remarkable
|
|
63
63
|
|
64
64
|
end
|
65
65
|
|
66
|
-
# Ensures that the attribute can be set to the given values.
|
67
|
-
#
|
68
|
-
#
|
69
|
-
#
|
66
|
+
# Ensures that the attribute can be set to the given values.
|
67
|
+
#
|
68
|
+
# Beware that when used in the negative form, this matcher fails if any of
|
69
|
+
# the values fail. For example, let's assume we have a valid and invalid
|
70
|
+
# value called "valid" and "invalid". The following assertion WILL pass:
|
71
|
+
#
|
72
|
+
# should_not_allow_values_for :attribute, "valid", "invalid"
|
73
|
+
#
|
74
|
+
# If you want to assert that all values fail, you have to do:
|
75
|
+
#
|
76
|
+
# %w(first_invalid second_invalid).each do |invalid|
|
77
|
+
# should_not_allow_values_for invalid
|
78
|
+
# end
|
70
79
|
#
|
71
80
|
# == Options
|
72
81
|
#
|
@@ -78,25 +87,22 @@ module Remarkable
|
|
78
87
|
# == Examples
|
79
88
|
#
|
80
89
|
# should_allow_values_for :isbn, "isbn 1 2345 6789 0", "ISBN 1-2345-6789-0"
|
81
|
-
# should_not_allow_values_for :isbn, "bad 1", "bad 2"
|
82
|
-
#
|
83
90
|
# it { should allow_values_for(:isbn, "isbn 1 2345 6789 0", "ISBN 1-2345-6789-0") }
|
84
|
-
# it { should_not allow_values_for(:isbn, "bad 1", "bad 2") }
|
85
91
|
#
|
86
92
|
def allow_values_for(attribute, *args, &block)
|
87
93
|
options = args.extract_options!
|
88
94
|
AllowValuesForMatcher.new(attribute, options.merge!(:in => args), &block).spec(self)
|
89
|
-
end
|
90
|
-
|
91
|
-
# Deprecated. Use allow_values_for instead.
|
92
|
-
#
|
93
|
-
def validate_format_of(*args)
|
94
|
-
if caller[0] =~ /\macros.rb/
|
95
|
-
warn "[DEPRECATION] should_validate_format_of is deprecated, use should_allow_values_for instead."
|
96
|
-
else
|
97
|
-
warn "[DEPRECATION] validate_format_of is deprecated, use allow_values_for instead. Called from #{caller[0]}."
|
98
|
-
end
|
99
|
-
allow_values_for(*args)
|
95
|
+
end
|
96
|
+
|
97
|
+
# Deprecated. Use allow_values_for instead.
|
98
|
+
#
|
99
|
+
def validate_format_of(*args)
|
100
|
+
if caller[0] =~ /\macros.rb/
|
101
|
+
warn "[DEPRECATION] should_validate_format_of is deprecated, use should_allow_values_for instead."
|
102
|
+
else
|
103
|
+
warn "[DEPRECATION] validate_format_of is deprecated, use allow_values_for instead. Called from #{caller[0]}."
|
104
|
+
end
|
105
|
+
allow_values_for(*args)
|
100
106
|
end
|
101
107
|
|
102
108
|
end
|
@@ -4,11 +4,11 @@ module Remarkable
|
|
4
4
|
class AssociationMatcher < Remarkable::ActiveRecord::Base #:nodoc:
|
5
5
|
arguments :macro, :collection => :associations, :as => :association
|
6
6
|
|
7
|
-
optionals :through, :source, :source_type, :class_name, :foreign_key, :dependent, :join_table, :as
|
7
|
+
optionals :through, :source, :source_type, :class_name, :foreign_key, :dependent, :join_table, :as
|
8
8
|
optionals :select, :conditions, :include, :group, :having, :order, :limit, :offset, :finder_sql, :counter_sql
|
9
9
|
optionals :uniq, :readonly, :validate, :autosave, :polymorphic, :counter_cache, :default => true
|
10
10
|
|
11
|
-
collection_assertions :association_exists?, :macro_matches?, :through_exists?, :source_exists?,
|
11
|
+
collection_assertions :association_exists?, :macro_matches?, :through_exists?, :source_exists?,
|
12
12
|
:klass_exists?, :join_table_exists?, :foreign_key_exists?, :polymorphic_exists?,
|
13
13
|
:counter_cache_exists?, :options_match?
|
14
14
|
|
@@ -16,38 +16,38 @@ module Remarkable
|
|
16
16
|
|
17
17
|
def association_exists?
|
18
18
|
reflection
|
19
|
-
end
|
20
|
-
|
19
|
+
end
|
20
|
+
|
21
21
|
def macro_matches?
|
22
22
|
reflection.macro == @macro
|
23
23
|
end
|
24
24
|
|
25
25
|
def through_exists?
|
26
|
-
return true unless @options.key?(:through)
|
26
|
+
return true unless @options.key?(:through)
|
27
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
|
33
|
-
end
|
34
|
-
|
35
|
-
# Polymorphic associations does not have a klass.
|
36
|
-
#
|
37
|
-
def klass_exists?
|
38
|
-
return true if @options[:polymorphic]
|
39
|
-
reflection.klass rescue nil
|
40
28
|
end
|
41
|
-
|
42
|
-
|
43
|
-
|
29
|
+
|
30
|
+
def source_exists?
|
31
|
+
return true unless @options.key?(:through)
|
32
|
+
reflection.source_reflection rescue false
|
33
|
+
end
|
34
|
+
|
35
|
+
# Polymorphic associations does not have a klass.
|
36
|
+
#
|
37
|
+
def klass_exists?
|
38
|
+
return true if @options[:polymorphic]
|
39
|
+
reflection.klass rescue nil
|
40
|
+
end
|
41
|
+
|
42
|
+
# has_and_belongs_to_many only works if the tables are in the same
|
43
|
+
# database, so we always look for the table in the subject connection.
|
44
44
|
#
|
45
45
|
def join_table_exists?
|
46
46
|
return true unless reflection.macro == :has_and_belongs_to_many
|
47
47
|
subject_class.connection.tables.include?(reflection.options[:join_table].to_s)
|
48
48
|
end
|
49
49
|
|
50
|
-
def foreign_key_exists?
|
50
|
+
def foreign_key_exists?
|
51
51
|
return true unless foreign_key_table
|
52
52
|
table_has_column?(foreign_key_table_class, foreign_key_table, reflection_foreign_key)
|
53
53
|
end
|
@@ -61,18 +61,18 @@ module Remarkable
|
|
61
61
|
return true unless @options[:counter_cache]
|
62
62
|
klass_table_has_column?(reflection.klass, reflection.counter_cache_column.to_s)
|
63
63
|
end
|
64
|
-
|
65
|
-
def options_match?
|
66
|
-
actual_options = {}
|
67
|
-
|
68
|
-
@options.keys.each do |key|
|
69
|
-
method = :"reflection_#{key}"
|
70
|
-
|
71
|
-
@options[key] = @options[key].to_s
|
72
|
-
actual_options[key] = (respond_to?(method, true) ? send(method) : reflection.options[key]).to_s
|
73
|
-
end
|
74
|
-
|
75
|
-
return @options == actual_options, :actual => actual_options.inspect
|
64
|
+
|
65
|
+
def options_match?
|
66
|
+
actual_options = {}
|
67
|
+
|
68
|
+
@options.keys.each do |key|
|
69
|
+
method = :"reflection_#{key}"
|
70
|
+
|
71
|
+
@options[key] = @options[key].to_s
|
72
|
+
actual_options[key] = (respond_to?(method, true) ? send(method) : reflection.options[key]).to_s
|
73
|
+
end
|
74
|
+
|
75
|
+
return @options == actual_options, :actual => actual_options.inspect
|
76
76
|
end
|
77
77
|
|
78
78
|
private
|
@@ -80,15 +80,15 @@ module Remarkable
|
|
80
80
|
def reflection
|
81
81
|
@reflection ||= subject_class.reflect_on_association(@association.to_sym)
|
82
82
|
end
|
83
|
-
|
83
|
+
|
84
84
|
def subject_table_name
|
85
85
|
subject_class.table_name.to_s
|
86
|
-
end
|
86
|
+
end
|
87
87
|
|
88
88
|
def reflection_class_name
|
89
89
|
reflection.class_name.to_s rescue nil
|
90
|
-
end
|
91
|
-
|
90
|
+
end
|
91
|
+
|
92
92
|
def reflection_table_name
|
93
93
|
reflection.klass.table_name.to_s rescue nil
|
94
94
|
end
|
@@ -99,24 +99,24 @@ module Remarkable
|
|
99
99
|
|
100
100
|
def table_has_column?(klass, table_name, column)
|
101
101
|
klass.connection.columns(table_name, 'Remarkable column retrieval').any?{|c| c.name == column }
|
102
|
-
end
|
103
|
-
|
104
|
-
def klass_table_has_column?(klass, column)
|
105
|
-
table_has_column?(klass, klass.table_name, column)
|
106
102
|
end
|
107
103
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
104
|
+
def klass_table_has_column?(klass, column)
|
105
|
+
table_has_column?(klass, klass.table_name, column)
|
106
|
+
end
|
107
|
+
|
108
|
+
# In through we don't check the foreign_key, because it's spread
|
109
|
+
# accross the through and the source reflection which should be tested
|
110
|
+
# with their own macros.
|
111
|
+
#
|
112
112
|
# In cases a join table exists (has_and_belongs_to_many and through
|
113
113
|
# associations), we check the foreign key in the join table.
|
114
114
|
#
|
115
115
|
# On belongs to, the foreign_key is in the subject class table and in
|
116
116
|
# other cases it's on the reflection class table.
|
117
117
|
#
|
118
|
-
def foreign_key_table
|
119
|
-
if reflection.options.key?(:through)
|
118
|
+
def foreign_key_table
|
119
|
+
if reflection.options.key?(:through)
|
120
120
|
nil
|
121
121
|
elsif reflection.macro == :has_and_belongs_to_many
|
122
122
|
reflection.options[:join_table]
|
@@ -125,22 +125,22 @@ module Remarkable
|
|
125
125
|
else
|
126
126
|
reflection_table_name
|
127
127
|
end
|
128
|
-
end
|
129
|
-
|
130
|
-
# Returns the foreign key table class to use the proper connection
|
131
|
-
# when searching for the table and foreign key.
|
132
|
-
#
|
133
|
-
def foreign_key_table_class
|
128
|
+
end
|
129
|
+
|
130
|
+
# Returns the foreign key table class to use the proper connection
|
131
|
+
# when searching for the table and foreign key.
|
132
|
+
#
|
133
|
+
def foreign_key_table_class
|
134
134
|
if [:belongs_to, :has_and_belongs_to_many].include?(reflection.macro)
|
135
135
|
subject_class
|
136
136
|
else
|
137
137
|
reflection.klass
|
138
|
-
end
|
139
|
-
end
|
138
|
+
end
|
139
|
+
end
|
140
140
|
|
141
141
|
def interpolation_options
|
142
|
-
options = {}
|
143
|
-
options[:macro] = Remarkable.t(@macro, :scope => matcher_i18n_scope, :default => @macro.to_s.gsub("_", ""))
|
142
|
+
options = {}
|
143
|
+
options[:macro] = Remarkable.t(@macro, :scope => matcher_i18n_scope, :default => @macro.to_s.gsub("_", ""))
|
144
144
|
options[:options] = @options.inspect
|
145
145
|
|
146
146
|
if @subject && reflection
|
@@ -150,8 +150,8 @@ module Remarkable
|
|
150
150
|
:reflection_table => reflection_table_name.inspect,
|
151
151
|
:foreign_key_table => foreign_key_table.inspect,
|
152
152
|
:polymorphic_column => reflection_foreign_key.sub(/_id$/, '_type').inspect,
|
153
|
-
:counter_cache_column => reflection.counter_cache_column.to_s.inspect,
|
154
|
-
:join_table => reflection.options[:join_table].inspect,
|
153
|
+
:counter_cache_column => reflection.counter_cache_column.to_s.inspect,
|
154
|
+
:join_table => reflection.options[:join_table].inspect,
|
155
155
|
:foreign_key => reflection_foreign_key.inspect
|
156
156
|
)
|
157
157
|
end
|
@@ -175,9 +175,9 @@ module Remarkable
|
|
175
175
|
# It also checks if the column actually exists in the table.
|
176
176
|
# * <tt>:polymorphic</tt> - if the association should be polymorphic or not.
|
177
177
|
# When true it also checks for the association_type column in the subject table.
|
178
|
-
#
|
179
|
-
# Plus all supported sql conditions options: :select, :conditions, :order,
|
180
|
-
# :limit, :offset, :include, :group, :having.
|
178
|
+
#
|
179
|
+
# Plus all supported sql conditions options: :select, :conditions, :order,
|
180
|
+
# :limit, :offset, :include, :group, :having.
|
181
181
|
#
|
182
182
|
# == Examples
|
183
183
|
#
|
@@ -199,9 +199,9 @@ module Remarkable
|
|
199
199
|
# * <tt>:uniq</tt> - checks wether uniq is true or false.
|
200
200
|
# * <tt>:readonly</tt> - checks wether readonly is true or false.
|
201
201
|
# * <tt>:validate</tt> - checks wether validate is true or false.
|
202
|
-
# * <tt>:autosave</tt> - checks wether autosave is true or false.
|
203
|
-
#
|
204
|
-
# Plus all supported sql conditions options: :select, :conditions, :order,
|
202
|
+
# * <tt>:autosave</tt> - checks wether autosave is true or false.
|
203
|
+
#
|
204
|
+
# Plus all supported sql conditions options: :select, :conditions, :order,
|
205
205
|
# :limit, :offset, :include, :group, :having.
|
206
206
|
#
|
207
207
|
# == Examples
|
@@ -221,8 +221,8 @@ module Remarkable
|
|
221
221
|
#
|
222
222
|
# * <tt>:class_name</tt> - the expected associted class name.
|
223
223
|
# * <tt>:through</tt> - the expected join model which to perform the query.
|
224
|
-
# It also checks if the through table exists.
|
225
|
-
# * <tt>:source</tt> - the source of the through association.
|
224
|
+
# It also checks if the through table exists.
|
225
|
+
# * <tt>:source</tt> - the source of the through association.
|
226
226
|
# * <tt>:source_type</tt> - the source type of the through association.
|
227
227
|
# * <tt>:foreign_key</tt> - the expected foreign key in the associated table.
|
228
228
|
# When used with :through, it will check for the foreign key in the join table.
|
@@ -230,9 +230,9 @@ module Remarkable
|
|
230
230
|
# * <tt>:uniq</tt> - checks wether uniq is true or false.
|
231
231
|
# * <tt>:readonly</tt> - checks wether readonly is true or false.
|
232
232
|
# * <tt>:validate</tt> - checks wether validate 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,
|
233
|
+
# * <tt>:autosave</tt> - checks wether autosave is true or false.
|
234
|
+
#
|
235
|
+
# Plus all supported sql conditions options: :select, :conditions, :order,
|
236
236
|
# :limit, :offset, :include, :group, :having.
|
237
237
|
#
|
238
238
|
# == Examples
|
@@ -257,16 +257,16 @@ module Remarkable
|
|
257
257
|
#
|
258
258
|
# * <tt>:class_name</tt> - the expected associted class name.
|
259
259
|
# * <tt>:through</tt> - the expected join model which to perform the query.
|
260
|
-
# It also checks if the through table exists.
|
261
|
-
# * <tt>:source</tt> - the source of the through association.
|
260
|
+
# It also checks if the through table exists.
|
261
|
+
# * <tt>:source</tt> - the source of the through association.
|
262
262
|
# * <tt>:source_type</tt> - the source type of the through association.
|
263
263
|
# * <tt>:foreign_key</tt> - the expected foreign key in the associated table.
|
264
264
|
# When used with :through, it will check for the foreign key in the join table.
|
265
265
|
# * <tt>:dependent</tt> - the expected dependent value for the association.
|
266
266
|
# * <tt>:validate</tt> - checks wether validate is true or false.
|
267
|
-
# * <tt>:autosave</tt> - checks wether autosave is true or false.
|
268
|
-
#
|
269
|
-
# Plus all supported sql conditions options: :select, :conditions, :order,
|
267
|
+
# * <tt>:autosave</tt> - checks wether autosave is true or false.
|
268
|
+
#
|
269
|
+
# Plus all supported sql conditions options: :select, :conditions, :order,
|
270
270
|
# :limit, :offset, :include, :group, :having.
|
271
271
|
#
|
272
272
|
# == Examples
|
@@ -5,9 +5,9 @@ module Remarkable
|
|
5
5
|
arguments :scope_name
|
6
6
|
assertions :is_scope?, :options_match?
|
7
7
|
|
8
|
-
optionals :with, :splat => true
|
9
|
-
optionals :conditions, :include, :joins, :limit, :offset, :order, :select,
|
10
|
-
:readonly, :group, :having, :from, :lock
|
8
|
+
optionals :with, :splat => true
|
9
|
+
optionals :conditions, :include, :joins, :limit, :offset, :order, :select,
|
10
|
+
:readonly, :group, :having, :from, :lock
|
11
11
|
|
12
12
|
protected
|
13
13
|
|
@@ -41,8 +41,8 @@ module Remarkable
|
|
41
41
|
#
|
42
42
|
# * <tt>with</tt> - Options to be sent to the named scope
|
43
43
|
#
|
44
|
-
# All options that the named scope would pass on to find: :conditions,
|
45
|
-
# :include, :joins, :limit, :offset, :order, :select, :readonly, :group,
|
44
|
+
# All options that the named scope would pass on to find: :conditions,
|
45
|
+
# :include, :joins, :limit, :offset, :order, :select, :readonly, :group,
|
46
46
|
# :having, :from, :lock.
|
47
47
|
#
|
48
48
|
# == Examples
|
@@ -10,12 +10,12 @@ module Remarkable
|
|
10
10
|
protected
|
11
11
|
|
12
12
|
def valid_values
|
13
|
-
if @in_range
|
14
|
-
[ @options[:in].first - 1, @options[:in].last + 1 ]
|
15
|
-
elsif @options[:in].empty?
|
16
|
-
[]
|
17
|
-
else
|
18
|
-
[ @options[:in].map(&:to_s).max.to_s.next ]
|
13
|
+
if @in_range
|
14
|
+
[ @options[:in].first - 1, @options[:in].last + 1 ]
|
15
|
+
elsif @options[:in].empty?
|
16
|
+
[]
|
17
|
+
else
|
18
|
+
[ @options[:in].map(&:to_s).max.to_s.next ]
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
@@ -26,9 +26,9 @@ module Remarkable
|
|
26
26
|
end
|
27
27
|
|
28
28
|
# Ensures that given values are not valid for the attribute. If a range
|
29
|
-
# is given, ensures that the attribute is not valid in the given range.
|
30
|
-
#
|
31
|
-
# If you give that :username does not accept ["admin", "user"], it will
|
29
|
+
# is given, ensures that the attribute is not valid in the given range.
|
30
|
+
#
|
31
|
+
# If you give that :username does not accept ["admin", "user"], it will
|
32
32
|
# test that "uses" (the next of the array max value) is allowed.
|
33
33
|
#
|
34
34
|
# == Options
|
@@ -14,21 +14,21 @@ module Remarkable
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def invalid_values
|
17
|
-
if @in_range
|
18
|
-
[ @options[:in].first - 1, @options[:in].last + 1 ]
|
19
|
-
elsif @options[:in].empty?
|
20
|
-
[]
|
21
|
-
else
|
22
|
-
[ @options[:in].map(&:to_s).max.to_s.next ]
|
17
|
+
if @in_range
|
18
|
+
[ @options[:in].first - 1, @options[:in].last + 1 ]
|
19
|
+
elsif @options[:in].empty?
|
20
|
+
[]
|
21
|
+
else
|
22
|
+
[ @options[:in].map(&:to_s).max.to_s.next ]
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
26
|
end
|
27
27
|
|
28
28
|
# Ensures that given values are valid for the attribute. If a range
|
29
|
-
# is given, ensures that the attribute is valid in the given range.
|
30
|
-
#
|
31
|
-
# If you give that :size accepts ["S", "M", "L"], it will test that "T"
|
29
|
+
# is given, ensures that the attribute is valid in the given range.
|
30
|
+
#
|
31
|
+
# If you give that :size accepts ["S", "M", "L"], it will test that "T"
|
32
32
|
# (the next of the array max value) is not allowed.
|
33
33
|
#
|
34
34
|
# == Options
|
@@ -5,10 +5,10 @@ module Remarkable
|
|
5
5
|
arguments :collection => :attributes, :as => :attribute
|
6
6
|
|
7
7
|
optional :within, :alias => :in
|
8
|
-
optional :minimum, :maximum, :is
|
8
|
+
optional :minimum, :maximum, :is
|
9
9
|
optional :token, :separator, :with_kind_of
|
10
10
|
optional :allow_nil, :allow_blank, :default => true
|
11
|
-
optional :message, :too_short, :too_long, :wrong_length
|
11
|
+
optional :message, :too_short, :too_long, :wrong_length
|
12
12
|
|
13
13
|
collection_assertions :less_than_min_length?, :exactly_min_length?,
|
14
14
|
:more_than_max_length?, :exactly_max_length?,
|
@@ -56,12 +56,12 @@ module Remarkable
|
|
56
56
|
@max_value.nil? || @min_value == @max_value || good?(value_for_length(@max_value), default_message_for(:too_long))
|
57
57
|
end
|
58
58
|
|
59
|
-
def value_for_length(value)
|
60
|
-
if @options[:with_kind_of]
|
61
|
-
[@options[:with_kind_of].new] * value
|
62
|
-
else
|
63
|
-
([@options.fetch(:token, 'x')] * value).join(@options.fetch(:separator, ''))
|
64
|
-
end
|
59
|
+
def value_for_length(value)
|
60
|
+
if @options[:with_kind_of]
|
61
|
+
[@options[:with_kind_of].new] * value
|
62
|
+
else
|
63
|
+
([@options.fetch(:token, 'x')] * value).join(@options.fetch(:separator, ''))
|
64
|
+
end
|
65
65
|
end
|
66
66
|
|
67
67
|
def interpolation_options
|
@@ -101,23 +101,23 @@ module Remarkable
|
|
101
101
|
# Regexp, string or symbol. Default = <tt>I18n.translate('activerecord.errors.messages.wrong_length') % range.last</tt>
|
102
102
|
# * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
103
103
|
# Regexp, string or symbol. Default = <tt>I18n.translate('activerecord.errors.messages.wrong_length') % value</tt>
|
104
|
-
#
|
105
|
-
# It also accepts an extra option called :with_kind_of. If you are validating
|
106
|
-
# the size of an association array, you have to specify the kind of the array
|
107
|
-
# being validated. For example, if your post accepts maximum 10 comments, you
|
108
|
-
# can do:
|
109
|
-
#
|
110
|
-
# should_validate_length_of :comments, :maximum => 10, :with_kind_of => Comment
|
111
|
-
#
|
112
|
-
# Finally, it also accepts :token and :separator, to specify how the
|
113
|
-
# tokenizer should work. For example, if you are splitting the attribute
|
114
|
-
# per word:
|
115
|
-
#
|
116
|
-
# validates_length_of :essay, :minimum => 100, :tokenizer => lambda {|str| str.scan(/\w+/) }
|
117
|
-
#
|
118
|
-
# You could do this:
|
119
|
-
#
|
120
|
-
# should_validate_length_of :essay, :minimum => 100, :token => "word", :separator => " "
|
104
|
+
#
|
105
|
+
# It also accepts an extra option called :with_kind_of. If you are validating
|
106
|
+
# the size of an association array, you have to specify the kind of the array
|
107
|
+
# being validated. For example, if your post accepts maximum 10 comments, you
|
108
|
+
# can do:
|
109
|
+
#
|
110
|
+
# should_validate_length_of :comments, :maximum => 10, :with_kind_of => Comment
|
111
|
+
#
|
112
|
+
# Finally, it also accepts :token and :separator, to specify how the
|
113
|
+
# tokenizer should work. For example, if you are splitting the attribute
|
114
|
+
# per word:
|
115
|
+
#
|
116
|
+
# validates_length_of :essay, :minimum => 100, :tokenizer => lambda {|str| str.scan(/\w+/) }
|
117
|
+
#
|
118
|
+
# You could do this:
|
119
|
+
#
|
120
|
+
# should_validate_length_of :essay, :minimum => 100, :token => "word", :separator => " "
|
121
121
|
#
|
122
122
|
# == Gotcha
|
123
123
|
#
|
@@ -131,16 +131,16 @@ module Remarkable
|
|
131
131
|
# it { should validate_length_of(:password).maximum(20) }
|
132
132
|
# it { should validate_length_of(:password).minimum(6) }
|
133
133
|
# it { should validate_length_of(:age).is(18) }
|
134
|
-
#
|
134
|
+
#
|
135
135
|
# should_validate_length_of :password, :within => 6..20
|
136
136
|
# should_validate_length_of :password, :maximum => 20
|
137
137
|
# should_validate_length_of :password, :minimum => 6
|
138
|
-
# should_validate_length_of :age, :is => 18
|
139
|
-
#
|
140
|
-
# should_validate_length_of :password do |m|
|
141
|
-
# m.minimum 6
|
142
|
-
# m.maximum 20
|
143
|
-
# end
|
138
|
+
# should_validate_length_of :age, :is => 18
|
139
|
+
#
|
140
|
+
# should_validate_length_of :password do |m|
|
141
|
+
# m.minimum 6
|
142
|
+
# m.maximum 20
|
143
|
+
# end
|
144
144
|
#
|
145
145
|
def validate_length_of(*attributes, &block)
|
146
146
|
ValidateLengthOfMatcher.new(*attributes, &block).spec(self)
|
data/locale/en.yml
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
en:
|
2
2
|
remarkable:
|
3
|
-
active_record:
|
4
|
-
describe:
|
5
|
-
each: "{{key}} is {{value}}"
|
6
|
-
prepend: "when "
|
7
|
-
connector: " and "
|
3
|
+
active_record:
|
4
|
+
describe:
|
5
|
+
each: "{{key}} is {{value}}"
|
6
|
+
prepend: "when "
|
7
|
+
connector: " and "
|
8
8
|
expectations:
|
9
9
|
allow_nil: "{{subject_name}} to {{not}}allow nil values for {{attribute}}"
|
10
|
-
allow_blank: "{{subject_name}} to {{not}}allow blank values for {{attribute}}"
|
10
|
+
allow_blank: "{{subject_name}} to {{not}}allow blank values for {{attribute}}"
|
11
11
|
optionals:
|
12
12
|
allow_nil:
|
13
13
|
positive: "allowing nil values"
|
@@ -15,24 +15,24 @@ en:
|
|
15
15
|
allow_blank:
|
16
16
|
positive: "allowing blank values"
|
17
17
|
negative: "not allowing blank values"
|
18
|
-
|
19
|
-
accept_nested_attributes_for:
|
20
|
-
description: "accept nested attributes for {{associations}}"
|
21
|
-
expectations:
|
22
|
-
association_exists: "{{subject_name}} to have association {{association}}, but does not"
|
23
|
-
is_autosave: "{{subject_name}} to have association {{association}} with autosave true, got false"
|
24
|
-
responds_to_attributes: "{{subject_name}} to respond to :{{association}}_attributes=, but does not"
|
25
|
-
allows_destroy: "{{subject_name}} with allow destroy equals to {{allow_destroy}}, got {{actual}}"
|
26
|
-
accepts: "{{subject_name}} to accept attributes {{attributes}} for {{association}}, but does not"
|
27
|
-
rejects: "{{subject_name}} to reject attributes {{attributes}} for {{association}}, but does not"
|
28
|
-
optionals:
|
29
|
-
allow_destroy:
|
30
|
-
positive: "allowing destroy"
|
31
|
-
negative: "not allowing destroy"
|
32
|
-
accept:
|
33
|
-
positive: "accepting {{sentence}}"
|
34
|
-
reject:
|
35
|
-
positive: "rejecting {{sentence}}"
|
18
|
+
|
19
|
+
accept_nested_attributes_for:
|
20
|
+
description: "accept nested attributes for {{associations}}"
|
21
|
+
expectations:
|
22
|
+
association_exists: "{{subject_name}} to have association {{association}}, but does not"
|
23
|
+
is_autosave: "{{subject_name}} to have association {{association}} with autosave true, got false"
|
24
|
+
responds_to_attributes: "{{subject_name}} to respond to :{{association}}_attributes=, but does not"
|
25
|
+
allows_destroy: "{{subject_name}} with allow destroy equals to {{allow_destroy}}, got {{actual}}"
|
26
|
+
accepts: "{{subject_name}} to accept attributes {{attributes}} for {{association}}, but does not"
|
27
|
+
rejects: "{{subject_name}} to reject attributes {{attributes}} for {{association}}, but does not"
|
28
|
+
optionals:
|
29
|
+
allow_destroy:
|
30
|
+
positive: "allowing destroy"
|
31
|
+
negative: "not allowing destroy"
|
32
|
+
accept:
|
33
|
+
positive: "accepting {{sentence}}"
|
34
|
+
reject:
|
35
|
+
positive: "rejecting {{sentence}}"
|
36
36
|
|
37
37
|
allow_values_for:
|
38
38
|
description: "allow {{in}} as values for {{attributes}}"
|
@@ -41,7 +41,7 @@ en:
|
|
41
41
|
|
42
42
|
allow_mass_assignment_of:
|
43
43
|
description: "allow mass assignment of {{attributes}}"
|
44
|
-
expectations:
|
44
|
+
expectations:
|
45
45
|
allows: "{{subject_name}} to allow mass assignment ({{subject_name}} is protecting {{protected_attributes}})"
|
46
46
|
is_protected: "{{subject_name}} to allow mass assignment of {{attribute}} ({{subject_name}} is protecting {{attribute}})"
|
47
47
|
is_accessible: "{{subject_name}} to allow mass assignment of {{attribute}} ({{subject_name}} has not made {{attribute}} accessible)"
|
@@ -53,22 +53,22 @@ en:
|
|
53
53
|
has_one: have one
|
54
54
|
description: "{{macro}} {{associations}}"
|
55
55
|
expectations:
|
56
|
-
association_exists: "{{subject_name}} records {{macro}} {{association}}, but the association does not exist"
|
56
|
+
association_exists: "{{subject_name}} records {{macro}} {{association}}, but the association does not exist"
|
57
57
|
macro_matches: "{{subject_name}} records {{macro}} {{association}}, got {{subject_name}} records {{actual_macro}} {{association}}"
|
58
|
-
through_exists: "{{subject_name}} records {{macro}} {{association}} through {{through}}, through association does not exist"
|
59
|
-
source_exists: "{{subject_name}} records {{macro}} {{association}} through {{through}}, source association does not exist"
|
58
|
+
through_exists: "{{subject_name}} records {{macro}} {{association}} through {{through}}, through association does not exist"
|
59
|
+
source_exists: "{{subject_name}} records {{macro}} {{association}} through {{through}}, source association does not exist"
|
60
60
|
klass_exists: "{{subject_name}} records {{macro}} {{association}}, but the association class does not exist"
|
61
61
|
join_table_exists: "join table {{join_table}} to exist, but does not"
|
62
62
|
foreign_key_exists: "foreign key {{foreign_key}} to exist on {{foreign_key_table}}, but does not"
|
63
63
|
polymorphic_exists: "{{subject_table}} to have {{polymorphic_column}} as column, but does not"
|
64
|
-
counter_cache_exists: "{{reflection_table}} to have {{counter_cache_column}} as column, but does not"
|
64
|
+
counter_cache_exists: "{{reflection_table}} to have {{counter_cache_column}} as column, but does not"
|
65
65
|
options_match: "{{subject_name}} records {{macro}} {{association}} with options {{options}}, got {{actual}}"
|
66
66
|
optionals:
|
67
67
|
through:
|
68
|
-
positive: "through {{value}}"
|
69
|
-
source:
|
70
|
-
positive: "with source {{inspect}}"
|
71
|
-
source_type:
|
68
|
+
positive: "through {{value}}"
|
69
|
+
source:
|
70
|
+
positive: "with source {{inspect}}"
|
71
|
+
source_type:
|
72
72
|
positive: "with source type {{inspect}}"
|
73
73
|
class_name:
|
74
74
|
positive: "with class name {{inspect}}"
|
@@ -94,23 +94,23 @@ en:
|
|
94
94
|
positive: "through the polymorphic interface {{inspect}}"
|
95
95
|
counter_cache:
|
96
96
|
positive: "with counter cache {{inspect}}"
|
97
|
-
negative: "without counter cache"
|
98
|
-
select:
|
99
|
-
positive: "selecting {{inspect}}"
|
100
|
-
conditions:
|
101
|
-
positive: "with conditions {{inspect}}"
|
102
|
-
include:
|
103
|
-
positive: "including {{inspect}}"
|
104
|
-
group:
|
105
|
-
positive: "grouping by {{inspect}}"
|
106
|
-
having:
|
107
|
-
positive: "having {{inspect}}"
|
108
|
-
order:
|
109
|
-
positive: "with order {{inspect}}"
|
110
|
-
limit:
|
111
|
-
positive: "with limit {{inspect}}"
|
112
|
-
offset:
|
113
|
-
positive: "with offset {{inspect}}"
|
97
|
+
negative: "without counter cache"
|
98
|
+
select:
|
99
|
+
positive: "selecting {{inspect}}"
|
100
|
+
conditions:
|
101
|
+
positive: "with conditions {{inspect}}"
|
102
|
+
include:
|
103
|
+
positive: "including {{inspect}}"
|
104
|
+
group:
|
105
|
+
positive: "grouping by {{inspect}}"
|
106
|
+
having:
|
107
|
+
positive: "having {{inspect}}"
|
108
|
+
order:
|
109
|
+
positive: "with order {{inspect}}"
|
110
|
+
limit:
|
111
|
+
positive: "with limit {{inspect}}"
|
112
|
+
offset:
|
113
|
+
positive: "with offset {{inspect}}"
|
114
114
|
|
115
115
|
have_column:
|
116
116
|
description: "have column(s) named {{columns}}"
|
@@ -127,8 +127,8 @@ en:
|
|
127
127
|
positive: "with default value {{inspect}}"
|
128
128
|
negative: "with default value {{inspect}}"
|
129
129
|
limit:
|
130
|
-
positive: "with limit {{inspect}}"
|
131
|
-
|
130
|
+
positive: "with limit {{inspect}}"
|
131
|
+
|
132
132
|
have_default_scope:
|
133
133
|
description: "have a default scope with {{options}}"
|
134
134
|
expectations:
|
@@ -142,8 +142,8 @@ en:
|
|
142
142
|
optionals:
|
143
143
|
unique:
|
144
144
|
positive: "with unique values"
|
145
|
-
negative: "with non unique values"
|
146
|
-
table_name:
|
145
|
+
negative: "with non unique values"
|
146
|
+
table_name:
|
147
147
|
positive: "on table {{value}}"
|
148
148
|
|
149
149
|
have_readonly_attributes:
|
@@ -207,8 +207,8 @@ en:
|
|
207
207
|
minimum:
|
208
208
|
positive: "is minimum {{inspect}} characters"
|
209
209
|
is:
|
210
|
-
positive: "is equal to {{inspect}} characters"
|
211
|
-
with_kind_of:
|
210
|
+
positive: "is equal to {{inspect}} characters"
|
211
|
+
with_kind_of:
|
212
212
|
positive: "with kind of {{value}}"
|
213
213
|
|
214
214
|
validate_numericality_of:
|
@@ -257,4 +257,4 @@ en:
|
|
257
257
|
case_sensitive:
|
258
258
|
positive: "case sensitive"
|
259
259
|
negative: "case insensitive"
|
260
|
-
|
260
|
+
|
@@ -20,14 +20,14 @@ describe 'allow_mass_assignment_of' do
|
|
20
20
|
@matcher = allow_mass_assignment_of(:title, :category)
|
21
21
|
@matcher.description.should == 'allow mass assignment of title and category'
|
22
22
|
end
|
23
|
-
|
24
|
-
it 'should set allows? message' do
|
23
|
+
|
24
|
+
it 'should set allows? message' do
|
25
25
|
define_and_validate(:protected => true)
|
26
26
|
@matcher = allow_mass_assignment_of
|
27
27
|
@matcher.matches?(@model)
|
28
28
|
@matcher.failure_message.should == 'Expected Product to allow mass assignment (Product is protecting category and title)'
|
29
|
-
end
|
30
|
-
|
29
|
+
end
|
30
|
+
|
31
31
|
it 'should set is_protected? message' do
|
32
32
|
@matcher = define_and_validate(:protected => true)
|
33
33
|
@matcher.matches?(@model)
|
@@ -47,23 +47,23 @@ describe 'allow_mass_assignment_of' do
|
|
47
47
|
it { should define_and_validate(:accessible => true) }
|
48
48
|
|
49
49
|
it { should_not define_and_validate(:protected => true) }
|
50
|
-
it { should_not define_and_validate(:accessible => [:another]) }
|
51
|
-
|
52
|
-
describe 'with no argument' do
|
53
|
-
it 'should allow mass assignment if no attribute is accessible or protected' do
|
54
|
-
define_and_validate
|
55
|
-
should allow_mass_assignment_of
|
56
|
-
end
|
57
|
-
|
58
|
-
it 'should allow mass assignment if attributes are accessible' do
|
59
|
-
define_and_validate(:accessible => true)
|
60
|
-
should allow_mass_assignment_of
|
61
|
-
end
|
62
|
-
|
63
|
-
it 'should not allow mass assignment if attributes are protected' do
|
64
|
-
define_and_validate(:protected => true)
|
65
|
-
should_not allow_mass_assignment_of
|
66
|
-
end
|
50
|
+
it { should_not define_and_validate(:accessible => [:another]) }
|
51
|
+
|
52
|
+
describe 'with no argument' do
|
53
|
+
it 'should allow mass assignment if no attribute is accessible or protected' do
|
54
|
+
define_and_validate
|
55
|
+
should allow_mass_assignment_of
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should allow mass assignment if attributes are accessible' do
|
59
|
+
define_and_validate(:accessible => true)
|
60
|
+
should allow_mass_assignment_of
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should not allow mass assignment if attributes are protected' do
|
64
|
+
define_and_validate(:protected => true)
|
65
|
+
should_not allow_mass_assignment_of
|
66
|
+
end
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
@@ -49,13 +49,13 @@ describe 'allow_values_for' do
|
|
49
49
|
describe 'macros' do
|
50
50
|
before(:each){ define_and_validate(:with => /X|Y|Z/) }
|
51
51
|
|
52
|
-
should_allow_values_for :title, 'X'
|
53
|
-
should_not_allow_values_for :title, 'A'
|
54
|
-
|
55
|
-
describe 'deprecation' do
|
56
|
-
it { should validate_format_of(:title, 'X') }
|
57
|
-
should_not_validate_format_of :title, 'A'
|
58
|
-
end
|
52
|
+
should_allow_values_for :title, 'X'
|
53
|
+
should_not_allow_values_for :title, 'A'
|
54
|
+
|
55
|
+
describe 'deprecation' do
|
56
|
+
it { should validate_format_of(:title, 'X') }
|
57
|
+
should_not_validate_format_of :title, 'A'
|
58
|
+
end
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
data/spec/describe_spec.rb
CHANGED
@@ -5,9 +5,9 @@ RAILS_I18n = true
|
|
5
5
|
class Post
|
6
6
|
attr_accessor :published, :public, :deleted
|
7
7
|
|
8
|
-
def
|
8
|
+
def attributes=(attributes={}, guard=true)
|
9
9
|
attributes.each do |key, value|
|
10
|
-
send(:"#{key}=", value)
|
10
|
+
send(:"#{key}=", value) unless guard
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
@@ -143,31 +143,31 @@ describe 'validate_length_of' do
|
|
143
143
|
it { should define_and_validate(:is => 3).is(3) }
|
144
144
|
it { should_not define_and_validate(:is => 3).is(2) }
|
145
145
|
it { should_not define_and_validate(:is => 3).is(4) }
|
146
|
-
end
|
147
|
-
|
148
|
-
describe "with token and separator options" do
|
149
|
-
describe "and words as tokens" do
|
150
|
-
before(:each) do
|
151
|
-
@matcher = define_and_validate(:within => 3..5, :tokenizer => lambda { |str| str.scan(/\w+/) })
|
152
|
-
end
|
153
|
-
|
154
|
-
it { should @matcher.within(3..5).token("word").separator(" ") }
|
155
|
-
it { should_not @matcher.within(2..5).token("word").separator(" ") }
|
156
|
-
it { should_not @matcher.within(4..5).token("word").separator(" ") }
|
157
|
-
it { should_not @matcher.within(3..4).token("word").separator(" ") }
|
158
|
-
it { should_not @matcher.within(3..6).token("word").separator(" ") }
|
159
|
-
it { should_not @matcher.within(3..5).token("word").separator("") }
|
160
|
-
it { should_not @matcher.within(3..5).token("word").separator(" a ") }
|
161
|
-
end
|
162
|
-
|
163
|
-
describe "and digits as tokens" do
|
164
|
-
before(:each) do
|
165
|
-
@matcher = define_and_validate(:within => 3..5, :tokenizer => lambda { |str| str.scan(/\d+/) })
|
166
|
-
end
|
167
|
-
|
168
|
-
it { should @matcher.within(3..5).token("1").separator(" ") }
|
169
|
-
it { should_not @matcher.within(3..5).token("a").separator("") }
|
170
|
-
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe "with token and separator options" do
|
149
|
+
describe "and words as tokens" do
|
150
|
+
before(:each) do
|
151
|
+
@matcher = define_and_validate(:within => 3..5, :tokenizer => lambda { |str| str.scan(/\w+/) })
|
152
|
+
end
|
153
|
+
|
154
|
+
it { should @matcher.within(3..5).token("word").separator(" ") }
|
155
|
+
it { should_not @matcher.within(2..5).token("word").separator(" ") }
|
156
|
+
it { should_not @matcher.within(4..5).token("word").separator(" ") }
|
157
|
+
it { should_not @matcher.within(3..4).token("word").separator(" ") }
|
158
|
+
it { should_not @matcher.within(3..6).token("word").separator(" ") }
|
159
|
+
it { should_not @matcher.within(3..5).token("word").separator("") }
|
160
|
+
it { should_not @matcher.within(3..5).token("word").separator(" a ") }
|
161
|
+
end
|
162
|
+
|
163
|
+
describe "and digits as tokens" do
|
164
|
+
before(:each) do
|
165
|
+
@matcher = define_and_validate(:within => 3..5, :tokenizer => lambda { |str| str.scan(/\d+/) })
|
166
|
+
end
|
167
|
+
|
168
|
+
it { should @matcher.within(3..5).token("1").separator(" ") }
|
169
|
+
it { should_not @matcher.within(3..5).token("a").separator("") }
|
170
|
+
end
|
171
171
|
end
|
172
172
|
|
173
173
|
describe "with with kind of" do
|
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.1.
|
4
|
+
version: 3.1.7
|
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-
|
14
|
+
date: 2009-07-05 00:00:00 +02: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: 3.1.
|
35
|
+
version: 3.1.7
|
36
36
|
version:
|
37
37
|
description: "Remarkable ActiveRecord: collection of matchers and macros with I18n for ActiveRecord"
|
38
38
|
email:
|