remarkable_activerecord 3.1.7 → 3.1.8

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,8 @@
1
+ * Allow booleans to be given to validate_inclusion_of [#89]
2
+
3
+ * Allow allow_values_for and allow_mass_assignment_of matchers to be executed in
4
+ the negative form by including Remarkable::Negative module [#85]
5
+
1
6
  * Ensure quick subject bypass protected attributes [#87]
2
7
 
3
8
  * Added :token and :separator to deal with :tokenizer in validates_length_of [#77]
@@ -1,6 +1,6 @@
1
1
  module Remarkable
2
2
  module ActiveRecord
3
- class Base < Remarkable::Base
3
+ class Base < Remarkable::Base
4
4
  I18N_COLLECTION = [ :attributes, :associations ]
5
5
 
6
6
  # Provides a way to send options to all ActiveRecord matchers.
@@ -25,14 +25,12 @@ module Remarkable
25
25
  # and an @options key where the message to search for is.
26
26
  #
27
27
  def assert_bad_or_good_if_key(key, value, message_key=:message) #:nodoc:
28
- return true unless @options.key?(key)
28
+ return positive? unless @options.key?(key)
29
29
 
30
30
  if @options[key]
31
- return true if bad?(value, message_key)
32
- return false, :not => not_word
31
+ return bad?(value, message_key), :not => not_word
33
32
  else
34
- return true if good?(value, message_key)
35
- return false, :not => ''
33
+ return good?(value, message_key), :not => ''
36
34
  end
37
35
  end
38
36
 
@@ -43,14 +41,12 @@ module Remarkable
43
41
  # and an @options key where the message to search for is.
44
42
  #
45
43
  def assert_good_or_bad_if_key(key, value, message_key=:message) #:nodoc:
46
- return true unless @options.key?(key)
44
+ return positive? unless @options.key?(key)
47
45
 
48
46
  if @options[key]
49
- return true if good?(value, message_key)
50
- return false, :not => ''
47
+ return good?(value, message_key), :not => ''
51
48
  else
52
- return true if bad?(value, message_key)
53
- return false, :not => not_word
49
+ return bad?(value, message_key), :not => not_word
54
50
  end
55
51
  end
56
52
 
@@ -212,8 +208,8 @@ module Remarkable
212
208
 
213
209
  collection_name = self.class.matcher_arguments[:collection].to_sym
214
210
  if collection = instance_variable_get("@#{collection_name}")
215
- collection = collection.map do |attr|
216
- described_class.human_attribute_name(attr.to_s, :locale => Remarkable.locale).downcase
211
+ collection = collection.map do |attr|
212
+ described_class.human_attribute_name(attr.to_s, :locale => Remarkable.locale).downcase
217
213
  end
218
214
  options[collection_name] = array_to_sentence(collection)
219
215
  end
@@ -228,12 +224,12 @@ module Remarkable
228
224
  else
229
225
  super
230
226
  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])
227
+ end
228
+
229
+ # Returns true if the given collection should be translated.
230
+ #
231
+ def i18n_collection? #:nodoc:
232
+ RAILS_I18N && I18N_COLLECTION.include?(self.class.matcher_arguments[:collection])
237
233
  end
238
234
 
239
235
  end
@@ -1,32 +1,40 @@
1
1
  module Remarkable
2
2
  module ActiveRecord
3
3
  module Matchers
4
- class AllowMassAssignmentOfMatcher < Remarkable::ActiveRecord::Base #:nodoc:
4
+ class AllowMassAssignmentOfMatcher < Remarkable::ActiveRecord::Base #:nodoc:
5
+ include Remarkable::Negative
5
6
  arguments :collection => :attributes, :as => :attribute
6
7
 
7
8
  assertion :allows?
8
- collection_assertions :is_protected?, :is_accessible?
9
+ collection_assertions :is_accessible?, :is_protected?
9
10
 
10
11
  protected
11
12
 
12
13
  # If no attribute is given, check if no attribute is being protected,
13
14
  # otherwise it fails.
14
15
  #
15
- def allows?
16
- !@attributes.empty? || protected_attributes.empty?
16
+ def allows?
17
+ return positive? unless @attributes.empty?
18
+ protected_attributes.empty?
17
19
  end
18
20
 
19
- def is_protected?
20
- protected_attributes.empty? || !protected_attributes.include?(@attribute.to_s)
21
+ def is_protected?
22
+ return positive? if protected_attributes.empty?
23
+ !protected_attributes.include?(@attribute.to_s)
21
24
  end
22
25
 
23
- def is_accessible?
24
- accessible_attributes.empty? || accessible_attributes.include?(@attribute.to_s)
26
+ def is_accessible?
27
+ return positive? if accessible_attributes.empty?
28
+ accessible_attributes.include?(@attribute.to_s)
25
29
  end
26
30
 
27
31
  def interpolation_options
28
- if @subject
29
- { :protected_attributes => array_to_sentence(protected_attributes.to_a, false, '[]') }
32
+ if @subject
33
+ if positive?
34
+ { :protected_attributes => array_to_sentence(protected_attributes.to_a, false, '[]') }
35
+ else
36
+ { :accessible_attributes => array_to_sentence(accessible_attributes.to_a, false, '[]') }
37
+ end
30
38
  else
31
39
  {}
32
40
  end
@@ -43,20 +51,7 @@ module Remarkable
43
51
  end
44
52
  end
45
53
 
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
54
+ # Ensures that the attribute can be set on mass update.
60
55
  #
61
56
  # == Examples
62
57
  #
@@ -1,7 +1,8 @@
1
1
  module Remarkable
2
2
  module ActiveRecord
3
3
  module Matchers
4
- class AllowValuesForMatcher < Remarkable::ActiveRecord::Base #:nodoc:
4
+ class AllowValuesForMatcher < Remarkable::ActiveRecord::Base #:nodoc:
5
+ include Remarkable::Negative
5
6
  arguments :collection => :attributes, :as => :attribute
6
7
 
7
8
  optional :message
@@ -27,18 +28,16 @@ module Remarkable
27
28
 
28
29
  protected
29
30
 
30
- def is_valid?
31
- valid_values.each do |value|
32
- return false, :value => value.inspect unless good?(value)
31
+ def is_valid?
32
+ assert_collection :value, valid_values do |value|
33
+ good?(value)
33
34
  end
34
- true
35
35
  end
36
36
 
37
- def is_invalid?
38
- invalid_values.each do |value|
39
- return false, :value => value.inspect unless bad?(value)
37
+ def is_invalid?
38
+ assert_collection :value, invalid_values do |value|
39
+ bad?(value)
40
40
  end
41
- true
42
41
  end
43
42
 
44
43
  def valid_values
@@ -63,19 +62,7 @@ module Remarkable
63
62
 
64
63
  end
65
64
 
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
65
+ # Ensures that the attribute can be set to the given values.
79
66
  #
80
67
  # == Options
81
68
  #
@@ -4,6 +4,8 @@ module Remarkable
4
4
  module ActiveRecord
5
5
  module Matchers
6
6
  class ValidateExclusionOfMatcher < AllowValuesForMatcher #:nodoc:
7
+ # Don't allow it to behave in the negative way.
8
+ undef_method :does_not_match?
7
9
 
8
10
  default_options :message => :exclusion
9
11
 
@@ -12,10 +14,9 @@ module Remarkable
12
14
  def valid_values
13
15
  if @in_range
14
16
  [ @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 ]
17
+ else
18
+ value = @options[:in].select{ |i| i.is_a?(String) }.max
19
+ value ? [ value.next ] : []
19
20
  end
20
21
  end
21
22
 
@@ -4,8 +4,10 @@ module Remarkable
4
4
  module ActiveRecord
5
5
  module Matchers
6
6
  class ValidateInclusionOfMatcher < AllowValuesForMatcher #:nodoc:
7
-
8
- default_options :message => :inclusion
7
+ # Don't allow it to behave in the negative way.
8
+ undef_method :does_not_match?
9
+
10
+ default_options :message => :inclusion
9
11
 
10
12
  protected
11
13
 
@@ -16,10 +18,9 @@ module Remarkable
16
18
  def invalid_values
17
19
  if @in_range
18
20
  [ @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 ]
21
+ else
22
+ value = @options[:in].select{ |i| i.is_a?(String) }.max
23
+ value ? [ value.next ] : []
23
24
  end
24
25
  end
25
26
 
data/locale/en.yml CHANGED
@@ -7,7 +7,7 @@ en:
7
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"
@@ -37,14 +37,18 @@ en:
37
37
  allow_values_for:
38
38
  description: "allow {{in}} as values for {{attributes}}"
39
39
  expectations:
40
- is_valid: "{{subject_name}} to be valid when {{attribute}} is set to {{value}}"
40
+ is_valid: "{{subject_name}} to be valid when {{attribute}} is set to {{value}}"
41
41
 
42
42
  allow_mass_assignment_of:
43
43
  description: "allow mass assignment of {{attributes}}"
44
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
- is_accessible: "{{subject_name}} to allow mass assignment of {{attribute}} ({{subject_name}} has not made {{attribute}} accessible)"
47
+ is_accessible: "{{subject_name}} to allow mass assignment of {{attribute}} ({{subject_name}} has not made {{attribute}} accessible)"
48
+ negative_expectations:
49
+ allows: "{{subject_name}} to allow mass assignment ({{subject_name}} made {{accessible_attributes}} accessible)"
50
+ is_protected: "{{subject_name}} to allow mass assignment of {{attribute}} ({{subject_name}} is not protecting {{attribute}})"
51
+ is_accessible: "{{subject_name}} to allow mass assignment of {{attribute}} ({{subject_name}} has made {{attribute}} accessible)"
48
52
 
49
53
  association:
50
54
  belongs_to: belong to
@@ -75,7 +75,24 @@ describe 'allow_mass_assignment_of' do
75
75
  should_allow_mass_assignment_of :title, :category
76
76
 
77
77
  should_not_allow_mass_assignment_of :another
78
- should_not_allow_mass_assignment_of :title, :another
78
+ end
79
+
80
+ describe 'failures' do
81
+ it "should fail if not all attributes are accessible on should not" do
82
+ define_and_validate(:accessible => true)
83
+
84
+ lambda {
85
+ should_not allow_mass_assignment_of :title, :another
86
+ }.should raise_error(Spec::Expectations::ExpectationNotMetError, /Product has made title accessible/)
87
+ end
88
+
89
+ it "should fail if accessible when protecting" do
90
+ define_and_validate(:accessible => true)
91
+
92
+ lambda {
93
+ should_not allow_mass_assignment_of
94
+ }.should raise_error(Spec::Expectations::ExpectationNotMetError, /Product made category and title accessible/)
95
+ end
79
96
  end
80
97
  end
81
98
 
@@ -56,6 +56,16 @@ describe 'allow_values_for' do
56
56
  it { should validate_format_of(:title, 'X') }
57
57
  should_not_validate_format_of :title, 'A'
58
58
  end
59
+ end
60
+
61
+ describe 'failures' do
62
+ it "should fail if any of the values are valid on invalid cases" do
63
+ define_and_validate(:with => /X|Y|Z/)
64
+
65
+ lambda {
66
+ should_not allow_values_for :title, 'A', 'X', 'B'
67
+ }.should raise_error(Spec::Expectations::ExpectationNotMetError, /Did not expect Product to be valid/)
68
+ end
59
69
  end
60
70
  end
61
71
 
@@ -49,6 +49,9 @@ describe 'validate_inclusion_of' do
49
49
  it { should_not define_and_validate(:in => ['X', 'Y', 'Z']).in('X', 'Y') }
50
50
  it { should_not define_and_validate(:in => ['X', 'Y', 'Z']).in('A') }
51
51
 
52
+ it { should define_and_validate(:in => [true, false]).in(true, false) }
53
+ it { should_not define_and_validate(:in => [true, false]).in('A') }
54
+
52
55
  it { should define_and_validate(:in => 2..3).in(2..3) }
53
56
  it { should define_and_validate(:in => 2..20).in(2..20) }
54
57
  it { should_not define_and_validate(:in => 2..20).in(1..20) }
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.7
4
+ version: 3.1.8
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-07-05 00:00:00 +02:00
14
+ date: 2009-07-16 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.7
35
+ version: 3.1.8
36
36
  version:
37
37
  description: "Remarkable ActiveRecord: collection of matchers and macros with I18n for ActiveRecord"
38
38
  email: