carlosbrando-remarkable 2.2.3 → 2.2.4

Sign up to get free protection for your applications and to get access to all the features.
data/Manifest.txt CHANGED
@@ -11,7 +11,7 @@ lib/remarkable/active_record/helpers.rb
11
11
  lib/remarkable/active_record/macros.rb
12
12
  lib/remarkable/active_record/macros/associations/association_matcher.rb
13
13
  lib/remarkable/active_record/macros/callbacks/callback_matcher.rb
14
- lib/remarkable/active_record/macros/database/column_matcher.rb
14
+ lib/remarkable/active_record/macros/database/have_db_column_matcher.rb
15
15
  lib/remarkable/active_record/macros/database/index_matcher.rb
16
16
  lib/remarkable/active_record/macros/validations/allow_mass_assignment_of_matcher.rb
17
17
  lib/remarkable/active_record/macros/validations/ensure_value_in_list_matcher.rb
data/README.rdoc CHANGED
@@ -102,10 +102,29 @@ Install the gem:
102
102
 
103
103
  sudo gem install carlosbrando-remarkable
104
104
 
105
- In RAILS_ROOT/config/environment.rb:
105
+ == Installing via Rails
106
+
107
+ Specify the gem dependency in your config/environment.rb file:
106
108
 
107
109
  config.gem "carlosbrando-remarkable", :lib => "remarkable", :source => "http://gems.github.com"
108
110
 
111
+ Then run in terminal:
112
+
113
+ $ rake gems:install
114
+ $ rake gems:unpack
115
+
116
+ === As a Plugin
117
+
118
+ You can also install Remarkable as a plugin:
119
+
120
+ $ script/plugin install git://github.com/carlosbrando/remarkable.git
121
+
122
+ Or using git submodules:
123
+
124
+ $ git submodule add git://github.com/carlosbrando/remarkable.git vendor/plugins/remarkable
125
+
126
+ Note: When installed as a plugin, you need to also install the rspec and rspec-rails in your project.
127
+
109
128
  == Requirements
110
129
 
111
130
  * rspec >= 1.1.12
data/lib/remarkable.rb CHANGED
@@ -2,7 +2,7 @@ $:.unshift(File.dirname(__FILE__)) unless
2
2
  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
3
 
4
4
  module Remarkable
5
- VERSION = '2.2.3'
5
+ VERSION = '2.2.4'
6
6
  end
7
7
 
8
8
  if ENV['RAILS_ENV'] == 'test'
@@ -8,6 +8,21 @@ module Remarkable # :nodoc:
8
8
  optional :type, :default, :precision, :limit, :scale, :sql_type
9
9
  optional :primary, :null, :default => true
10
10
 
11
+ # TODO: remove it
12
+ def of_type(type)
13
+ warn "[DEPRECATION] option of_type is deprecated. Use type instead."
14
+ @options[:type] = type
15
+ self
16
+ end
17
+
18
+ # Method used to load all options via hash.
19
+ # (:type, :default, :precision, :limit, :scale, :sql_type, :primary, :null)
20
+ #
21
+ def with_options(opts = {})
22
+ @options.merge!(opts)
23
+ self
24
+ end
25
+
11
26
  assertions :has_column?, :all_options_correct?
12
27
 
13
28
  def failure_message
@@ -62,10 +77,28 @@ module Remarkable # :nodoc:
62
77
  end
63
78
  end
64
79
 
80
+ # Ensures that a column of the database actually exists.
81
+ #
82
+ # Options:
83
+ # * <tt>type</tt> - database column types like :string, :integer, etc.
84
+ #
85
+ # * All options available in migrations are also available here.
86
+ # (.type, .default, .precision, .limit, .scale, .sql_type, .primary, .null)
87
+ #
88
+ # * <tt>with_options</tt> - option used to load the above options via hash
89
+ # (:type => :string, :primary => true, etc.)
90
+ #
91
+ # Example:
92
+ # it { should have_db_column(:name).type(:string) }
93
+ # it { should have_db_column(:age).with_options(:type => :integer) }
94
+ # it { should_not have_db_column(:salary) }
95
+ #
65
96
  def have_db_column(column, options = {})
66
97
  ColumnMatcher.new(column, options)
67
98
  end
68
-
99
+
100
+ # Alias for #have_db_column
101
+ #
69
102
  def have_db_columns(*columns)
70
103
  ColumnMatcher.new(*columns)
71
104
  end
@@ -2,46 +2,18 @@ module Remarkable # :nodoc:
2
2
  module ActiveRecord # :nodoc:
3
3
  module Matchers # :nodoc:
4
4
 
5
- # Ensures the database column has specified index.
6
- #
7
- # Options:
8
- # * <tt>unique</tt> -
9
- #
10
- # Example:
11
- # it { should have_index(:ssn).unique(true) }
12
- #
13
- def have_indices(*columns)
14
- IndexMatcher.new(*columns)
15
- end
16
- alias_method :have_index, :have_indices
17
-
18
5
  class IndexMatcher < Remarkable::Matcher::Base
19
6
  INDEX_TYPES = { true => "unique", false => "non-unique" }
20
-
21
- def initialize(*columns)
22
- load_options(columns)
23
- @columns = columns
24
- end
25
7
 
26
- def unique(value = true)
27
- @options[:unique] = value
28
- self
29
- end
8
+ arguments :columns
9
+ optional :unique, :default => true
10
+
11
+ assertions :index_exists?, :correct_unique?
30
12
 
31
13
  def table_name=(table_name)
32
14
  @table_name = table_name
33
15
  end
34
16
 
35
- def matches?(subject)
36
- @subject = subject
37
- @expected_uniqueness = @options[:unique] ? 'unique' : 'non-unique'
38
-
39
- assert_matcher_for(@columns) do |column|
40
- @column = column
41
- index_exists? && correct_unique?
42
- end
43
- end
44
-
45
17
  def failure_message
46
18
  "Expected to #{expectation} (#{@missing})"
47
19
  end
@@ -56,6 +28,10 @@ module Remarkable # :nodoc:
56
28
 
57
29
  protected
58
30
 
31
+ def after_initialize!
32
+ @expected_uniqueness = @options[:unique] ? 'unique' : 'non-unique'
33
+ end
34
+
59
35
  def index_exists?
60
36
  return true if matched_index
61
37
 
@@ -91,13 +67,22 @@ module Remarkable # :nodoc:
91
67
  def expectation
92
68
  "have #{index_type} index on #{table_name} for #{@column.inspect}"
93
69
  end
94
-
95
- def load_options(options)
96
- @options = {
97
- :unique => nil
98
- }.merge(options.extract_options!)
99
- end
70
+
71
+ end
72
+
73
+ # Ensures the database column has specified index.
74
+ #
75
+ # Options:
76
+ # * <tt>unique</tt> - when supplied, tests if the index is unique or not
77
+ #
78
+ # Example:
79
+ # it { should have_index(:ssn).unique(true) }
80
+ #
81
+ def have_indices(*columns)
82
+ IndexMatcher.new(*columns)
100
83
  end
84
+ alias_method :have_index, :have_indices
85
+
101
86
  end
102
87
  end
103
88
  end
@@ -4,30 +4,10 @@ module Remarkable # :nodoc:
4
4
  class EnsureValueInListMatcher < Remarkable::Matcher::Base
5
5
  include Remarkable::ActiveRecord::Helpers
6
6
 
7
- def initialize(attribute, behavior, *good_values)
8
- @behavior = behavior
9
- load_options(good_values.extract_options!)
7
+ arguments :attribute, :behavior, :good_values
8
+ assertions :value_valid?
10
9
 
11
- @attribute = attribute
12
- @good_values = good_values
13
- end
14
-
15
- def matches?(subject)
16
- @subject = subject
17
-
18
- assert_matcher_for(@good_values) do |good_value|
19
- @good_value = good_value
20
- value_valid?
21
- end &&
22
- assert_matcher do
23
- @good_value = 'nil'
24
- allow_nil?
25
- end &&
26
- assert_matcher do
27
- @good_value = 'blank'
28
- allow_blank?
29
- end
30
- end
10
+ single_assertions :allow_blank?, :allow_nil?
31
11
 
32
12
  def description
33
13
  values = @good_values.dup
@@ -51,10 +31,8 @@ module Remarkable # :nodoc:
51
31
 
52
32
  private
53
33
 
54
- def load_options(options = {})
55
- @options = {
56
- :message => @behavior
57
- }.merge(options)
34
+ def default_options
35
+ { :message => @behavior }
58
36
  end
59
37
 
60
38
  def value_valid?
@@ -4,13 +4,8 @@ module Remarkable # :nodoc:
4
4
  class EnsureValueInRangeMatcher < Remarkable::Matcher::Base
5
5
  include Remarkable::ActiveRecord::Helpers
6
6
 
7
- def initialize(attribute, behavior, range, *options)
8
- @attribute = attribute
9
- @range = range
10
- @behavior = behavior
11
- load_options(options.extract_options!)
12
- end
13
-
7
+ arguments :attribute, :behavior, :ranges
8
+
14
9
  def low_message(message)
15
10
  warn "[DEPRECATION] should_ensure_value_in_range.low_message is deprecated. " <<
16
11
  "Use should_validate_inclusion_of.message instead."
@@ -34,14 +29,8 @@ module Remarkable # :nodoc:
34
29
  self
35
30
  end
36
31
 
37
- def matches?(subject)
38
- @subject = subject
39
-
40
- assert_matcher do
41
- less_than_minimum? && accepts_minimum? && more_than_minimum? && allow_nil? &&
42
- more_than_maximum? && accepts_maximum? && less_than_maximum? && allow_blank?
43
- end
44
- end
32
+ assertions :less_than_minimum?, :accepts_minimum?, :more_than_minimum?, :allow_nil?,
33
+ :more_than_maximum?, :accepts_maximum?, :less_than_maximum?, :allow_blank?
45
34
 
46
35
  def description
47
36
  "ensure #{expectation}"
@@ -144,27 +133,26 @@ module Remarkable # :nodoc:
144
133
  end
145
134
  end
146
135
 
147
- def load_options(options = {})
148
- warn "[DEPRECATION] should_ensure_value_in_range with :low_message is deprecated. " <<
149
- "Use should_validate_inclusion_of with :message instead." if options[:low_message]
150
-
151
- warn "[DEPRECATION] should_ensure_value_in_range with :high_message is deprecated. " <<
152
- "Use should_validate_inclusion_of with :message instead." if options[:high_message]
153
-
154
- warn "[DEPRECATION] should_ensure_value_in_range is deprecated. " <<
155
- "Use should_validate_inclusion_of instead." if options[:low_message].blank? && options[:high_message].blank?
156
-
157
- @options = {
158
- :low_message => @behavior,
136
+ def default_options
137
+ { :low_message => @behavior,
159
138
  :high_message => @behavior,
160
- :message => @behavior
161
- }.merge(options)
139
+ :message => @behavior }
162
140
  end
163
141
  end
164
142
 
165
-
166
143
  # TODO Deprecate this method, but not the matcher.
167
144
  def ensure_value_in_range(attribute, range, *options) #:nodoc:
145
+ hash_options = options.extract_options!
146
+
147
+ warn "[DEPRECATION] should_ensure_value_in_range with :low_message is deprecated. " <<
148
+ "Use should_validate_inclusion_of with :message instead." if hash_options[:low_message]
149
+
150
+ warn "[DEPRECATION] should_ensure_value_in_range with :high_message is deprecated. " <<
151
+ "Use should_validate_inclusion_of with :message instead." if hash_options[:high_message]
152
+
153
+ warn "[DEPRECATION] should_ensure_value_in_range is deprecated. " <<
154
+ "Use should_validate_inclusion_of instead." if hash_options[:low_message].blank? && hash_options[:high_message].blank?
155
+
168
156
  EnsureValueInRangeMatcher.new(attribute, :inclusion, range, *options)
169
157
  end
170
158
  end
@@ -34,10 +34,8 @@ module Remarkable # :nodoc:
34
34
  end
35
35
 
36
36
  # Receives a Hash
37
- def load_options(options = {})
38
- @options = {
39
- :message => :accepted
40
- }.merge(options)
37
+ def default_options
38
+ { :message => :accepted }
41
39
  end
42
40
 
43
41
  def expectation
@@ -6,24 +6,10 @@ module Remarkable # :nodoc:
6
6
 
7
7
  undef_method :allow_nil, :allow_nil?, :allow_blank, :allow_blank?
8
8
 
9
- def initialize(*associations)
10
- load_options(associations.extract_options!)
11
- @associations = associations
12
- end
13
-
14
- def builder(value)
15
- @options[:builder] = value
16
- self
17
- end
9
+ arguments :associations
10
+ optional :builder
18
11
 
19
- def matches?(subject)
20
- @subject = get_instance_of(subject)
21
-
22
- assert_matcher_for(@associations) do |association|
23
- @association = association
24
- build_association? && valid?
25
- end
26
- end
12
+ assertions :build_association?, :valid?
27
13
 
28
14
  def description
29
15
  "require association #{@associations.to_sentence} to be valid"
@@ -103,11 +89,15 @@ module Remarkable # :nodoc:
103
89
  false
104
90
  end
105
91
 
106
- # Receives a Hash
107
- def load_options(options = {})
108
- @options = {
109
- :message => :invalid
110
- }.merge(options)
92
+ # Before make the assertions, convert the subject into a instance, if
93
+ # it's not already.
94
+ #
95
+ def before_assert!
96
+ @subject = get_instance_of(@subject)
97
+ end
98
+
99
+ def default_options
100
+ { :message => :invalid }
111
101
  end
112
102
 
113
103
  def plural?
@@ -6,19 +6,8 @@ module Remarkable # :nodoc:
6
6
 
7
7
  undef_method :allow_nil?, :allow_nil, :allow_blank?, :allow_blank
8
8
 
9
- def initialize(*attributes)
10
- load_options(attributes.extract_options!)
11
- @attributes = attributes
12
- end
13
-
14
- def matches?(subject)
15
- @subject = get_instance_of(subject)
16
-
17
- assert_matcher_for(@attributes) do |attribute|
18
- @attribute = attribute
19
- confirmed?
20
- end
21
- end
9
+ arguments :attributes
10
+ assertions :confirmed?
22
11
 
23
12
  def description
24
13
  "validate confirmation of #{@attributes.to_sentence}"
@@ -26,6 +15,17 @@ module Remarkable # :nodoc:
26
15
 
27
16
  private
28
17
 
18
+ # Before make the assertions, convert the subject into a instance, if
19
+ # it's not already.
20
+ #
21
+ def before_assert!
22
+ @subject = get_instance_of(@subject)
23
+ end
24
+
25
+ def default_options
26
+ { :message => :confirmation }
27
+ end
28
+
29
29
  def confirmed?
30
30
  confirmation_assignment = "#{@attribute}_confirmation="
31
31
 
@@ -41,12 +41,6 @@ module Remarkable # :nodoc:
41
41
  end
42
42
  end
43
43
 
44
- def load_options(options = {})
45
- @options = {
46
- :message => :confirmation
47
- }.merge(options)
48
- end
49
-
50
44
  def expectation
51
45
  "#{@attribute} to be confirmed"
52
46
  end
@@ -4,18 +4,11 @@ module Remarkable # :nodoc:
4
4
  class ValidateLengthOfMatcher < Remarkable::Matcher::Base
5
5
  include Remarkable::ActiveRecord::Helpers
6
6
 
7
- def initialize(attributes, range, behavior, options = {})
8
- @attributes = attributes
9
- @behavior = behavior
7
+ arguments :behavior, :range, :attributes
8
+ optional :minimum, :maximum, :short_message, :long_message
10
9
 
11
- # Set the values, for example:
12
- #
13
- # send(:within, 0..10)
14
- #
15
- send(@behavior, range)
16
-
17
- load_options(options)
18
- end
10
+ assertions :less_than_min_length?, :exactly_min_length?, :allow_nil?,
11
+ :more_than_max_length?, :exactly_max_length?, :allow_blank?
19
12
 
20
13
  # If message is supplied, reassign it properly to :short_message
21
14
  # and :long_message. This is ActiveRecord default behavior when
@@ -31,127 +24,102 @@ module Remarkable # :nodoc:
31
24
 
32
25
  def within(range)
33
26
  @behavior = :within
34
- @minimum = range.first
35
- @maximum = range.last
27
+ @options[:minimum] = range.first
28
+ @options[:maximum] = range.last
36
29
  self
37
30
  end
38
31
  alias :in :within
39
32
 
40
- def minimum(value)
41
- @minimum = value
42
- self
43
- end
44
-
45
- def maximum(value)
46
- @maximum = value
47
- self
48
- end
49
-
50
33
  def is(value)
51
- @minimum = value
52
- @maximum = value
34
+ @options[:minimum] = value
35
+ @options[:maximum] = value
53
36
  self
54
37
  end
55
38
 
56
- def short_message(message)
57
- @options[:short_message] = message
58
- @options[:message] = message # make a copy in @options[:message], for
59
- # allow_blank and allow_nil work properly.
60
- self
39
+ def description
40
+ "ensure #{expectation}"
61
41
  end
62
42
 
63
- def long_message(message)
64
- @options[:long_message] = message
65
- self
43
+ def failure_message
44
+ "Expected #{expectation} (#{@missing})"
66
45
  end
67
46
 
68
- def matches?(subject)
69
- @subject = subject
47
+ def negative_failure_message
48
+ "Did not expect #{expectation}"
49
+ end
70
50
 
71
- assert_matcher_for(@attributes) do |attribute|
72
- @attribute = attribute
51
+ private
73
52
 
74
- less_than_min_length? && exactly_min_length? && allow_nil?(:message, @minimum) &&
75
- more_than_max_length? && exactly_max_length? && allow_blank?(:message, @minimum)
53
+ def default_options
54
+ if @behavior == :is
55
+ { :short_message => :wrong_length, :long_message => :wrong_length }
56
+ else
57
+ { :short_message => :too_short, :long_message => :too_long }
76
58
  end
77
59
  end
78
60
 
79
- def description
80
- "ensure #{expectation}"
81
- end
61
+ # Reassign messages properly
62
+ def after_initialize!
63
+ # Set the values, for example:
64
+ # send(:within, 0..10)
65
+ send(@behavior, @range)
82
66
 
83
- def failure_message
84
- "Expected #{expectation} (#{@missing})"
67
+ message(@options.delete(:message)) if @options[:message]
68
+ long_message(@options[:long_message])
69
+ short_message(@options[:short_message])
85
70
  end
86
71
 
87
- def negative_failure_message
88
- "Did not expect #{expectation}"
72
+ def allow_nil?
73
+ super(:short_message, @options[:minimum])
89
74
  end
90
75
 
91
- private
76
+ def allow_blank?
77
+ super(:short_message, @options[:minimum])
78
+ end
92
79
 
93
80
  def less_than_min_length?
94
- return true if @behavior == :maximum || @minimum <= 0
95
- return true if bad?(value_for_length(@minimum - 1), :short_message, @minimum)
81
+ return true if @behavior == :maximum || @options[:minimum] <= 0
82
+ return true if bad?(value_for_length(@options[:minimum] - 1), :short_message, @options[:minimum])
96
83
 
97
- @missing = "allow #{@attribute} to be less than #{@minimum} chars long"
84
+ @missing = "allow #{@attribute} to be less than #{@options[:minimum]} chars long"
98
85
  return false
99
86
  end
100
87
 
101
88
  def exactly_min_length?
102
- return true if @behavior == :maximum || @minimum <= 0
103
- return true if good?(value_for_length(@minimum), :short_message, @minimum)
89
+ return true if @behavior == :maximum || @options[:minimum] <= 0
90
+ return true if good?(value_for_length(@options[:minimum]), :short_message, @options[:minimum])
104
91
 
105
- @missing = "not allow #{@attribute} to be exactly #{@minimum} chars long"
92
+ @missing = "not allow #{@attribute} to be exactly #{@options[:minimum]} chars long"
106
93
  return false
107
94
  end
108
95
 
109
96
  def more_than_max_length?
110
97
  return true if @behavior == :minimum
111
- return true if bad?(value_for_length(@maximum + 1), :long_message, @maximum)
98
+ return true if bad?(value_for_length(@options[:maximum] + 1), :long_message, @options[:maximum])
112
99
 
113
- @missing = "allow #{@attribute} to be more than #{@maximum} chars long"
100
+ @missing = "allow #{@attribute} to be more than #{@options[:maximum]} chars long"
114
101
  return false
115
102
  end
116
103
 
117
104
  def exactly_max_length?
118
- return true if @behavior == :minimum || @minimum == @maximum
119
- return true if good?(value_for_length(@maximum), :long_message, @maximum)
105
+ return true if @behavior == :minimum || @options[:minimum] == @options[:maximum]
106
+ return true if good?(value_for_length(@options[:maximum]), :long_message, @options[:maximum])
120
107
 
121
- @missing = "not allow #{@attribute} to be exactly #{@maximum} chars long"
108
+ @missing = "not allow #{@attribute} to be exactly #{@options[:maximum]} chars long"
122
109
  return false
123
110
  end
124
111
 
125
- def load_options(options)
126
- if @behavior == :is
127
- @options = {
128
- :short_message => :wrong_length,
129
- :long_message => :wrong_length
130
- }.merge(options)
131
- else
132
- @options = {
133
- :short_message => :too_short,
134
- :long_message => :too_long
135
- }.merge(options)
136
- end
137
-
138
- # Reassign messages properly
139
- message(@options[:message]) if @options[:message]
140
- long_message(@options[:long_message])
141
- short_message(@options[:short_message])
142
- end
143
-
144
112
  def expectation
145
113
  message = "that the length of the #{@attribute} is "
146
114
 
147
115
  message << if @behavior == :within
148
- "between #{@minimum} and #{@maximum}"
116
+ "between #{@options[:minimum]} and #{@options[:maximum]}"
149
117
  elsif @behavior == :minimum
150
- "more than #{@minimum}"
118
+ "more than #{@options[:minimum]}"
151
119
  elsif @behavior == :maximum
152
- "less than #{@maximum}"
120
+ "less than #{@options[:maximum]}"
153
121
  else #:is
154
- "equal to #{@minimum}"
122
+ "equal to #{@options[:minimum]}"
155
123
  end
156
124
 
157
125
  message << " or nil" if @options[:allow_nil]
@@ -207,7 +175,7 @@ module Remarkable # :nodoc:
207
175
 
208
176
  [:within, :in, :maximum, :minimum, :is].each do |behavior|
209
177
  if options.key? behavior
210
- matcher ||= ValidateLengthOfMatcher.new(attributes, options.delete(behavior), behavior, options)
178
+ matcher ||= ValidateLengthOfMatcher.new(behavior, options.delete(behavior), *(attributes << options))
211
179
  end
212
180
  end
213
181
 
@@ -227,21 +195,21 @@ module Remarkable # :nodoc:
227
195
  def ensure_length_in_range(attribute, range, options = {}) #:nodoc:
228
196
  warn "[DEPRECATION] should_ensure_length_in_range is deprecated. " <<
229
197
  "Use should_validate_length_of(#{attribute.inspect}, :in => #{range.inspect}) instead."
230
- ValidateLengthOfMatcher.new([attribute], range, :within, options)
198
+ ValidateLengthOfMatcher.new(:within, range, attribute, options)
231
199
  end
232
200
 
233
201
  # TODO Deprecate me
234
202
  def ensure_length_at_least(attribute, range, options = {}) #:nodoc:
235
203
  warn "[DEPRECATION] should_ensure_length_at_least is deprecated. " <<
236
204
  "Use should_validate_length_of(#{attribute.inspect}, :minimum => #{range.inspect}) instead."
237
- ValidateLengthOfMatcher.new([attribute], range, :minimum, options)
205
+ ValidateLengthOfMatcher.new(:minimum, range, attribute, options)
238
206
  end
239
207
 
240
208
  # TODO Deprecate me
241
209
  def ensure_length_is(attribute, range, options = {}) #:nodoc:
242
210
  warn "[DEPRECATION] should_ensure_length_is is deprecated. " <<
243
211
  "Use should_validate_length_of(#{attribute.inspect}, :is => #{range.inspect}) instead."
244
- ValidateLengthOfMatcher.new([attribute], range, :is, options)
212
+ ValidateLengthOfMatcher.new(:is, range, attribute, options)
245
213
  end
246
214
  end
247
215
  end
@@ -6,29 +6,14 @@ module Remarkable # :nodoc:
6
6
 
7
7
  NUMERIC_COMPARISIONS = [:equal_to, :less_than, :greater_than, :less_than_or_equal_to, :greater_than_or_equal_to]
8
8
 
9
- def initialize(*attributes)
10
- load_options(attributes.extract_options!)
11
- @attributes = attributes
12
- end
9
+ arguments :attributes
13
10
 
14
11
  optional :only_integer, :odd, :even, :default => true
15
12
  optional :equal_to, :less_than, :greater_than, :less_than_or_equal_to, :greater_than_or_equal_to
16
13
 
17
- def matches?(subject)
18
- @subject = subject
19
-
20
- assert_matcher_for(@attributes) do |attribute|
21
- @attribute = attribute
22
-
23
- only_allow_numeric_values? && allow_blank? && allow_nil? &&
24
- only_integer? && allow_odd? && allow_even? && equal_to?(:equal_to) &&
25
- equal_to?(:less_than, -1) && equal_to?(:greater_than, +1) &&
26
- equal_to?(:less_than_or_equal_to) && equal_to?(:greater_than_or_equal_to) &&
27
- more_than_maximum?(:equal_to, +1) && less_than_minimum?(:equal_to, -1) &&
28
- more_than_maximum?(:less_than) && less_than_minimum?(:greater_than) &&
29
- more_than_maximum?(:less_than_or_equal_to, +1) && less_than_minimum?(:greater_than_or_equal_to, -1)
30
- end
31
- end
14
+ assertions :only_allow_numeric_values?, :allow_blank?, :allow_nil?,
15
+ :only_integer?, :allow_odd?, :allow_even?, :equal_to_for_each_option?,
16
+ :less_than_maximum_for_each_option?, :more_than_maximum_for_each_option?
32
17
 
33
18
  def description
34
19
  default_message + "for #{@attributes.to_sentence}"
@@ -36,6 +21,27 @@ module Remarkable # :nodoc:
36
21
 
37
22
  private
38
23
 
24
+ # Check equal_to? for each given option
25
+ #
26
+ def equal_to_for_each_option?
27
+ equal_to?(:equal_to) && equal_to?(:less_than, -1) && equal_to?(:greater_than, +1) &&
28
+ equal_to?(:less_than_or_equal_to) && equal_to?(:greater_than_or_equal_to)
29
+ end
30
+
31
+ # Check more_than_maximum? for each given option
32
+ #
33
+ def more_than_maximum_for_each_option?
34
+ more_than_maximum?(:equal_to, +1) && more_than_maximum?(:less_than) &&
35
+ more_than_maximum?(:less_than_or_equal_to, +1)
36
+ end
37
+
38
+ # Check less_than_maximum? for each given option
39
+ #
40
+ def less_than_maximum_for_each_option?
41
+ less_than_minimum?(:equal_to, -1) && less_than_minimum?(:greater_than) &&
42
+ less_than_minimum?(:greater_than_or_equal_to, -1)
43
+ end
44
+
39
45
  def only_allow_numeric_values?
40
46
  return true if bad?("abcd")
41
47
 
@@ -111,16 +117,18 @@ module Remarkable # :nodoc:
111
117
  (valid_value_for_test / 2) * 2
112
118
  end
113
119
 
114
- def load_options(options = {})
115
- @options = {
120
+ def default_options
121
+ options = {
116
122
  :message => :not_a_number,
117
123
  :odd_message => :odd,
118
124
  :even_message => :even
119
- }.merge(options)
125
+ }
120
126
 
121
- NUMERIC_COMPARISIONS.map do |key|
122
- @options[:"#{key}_message"] = key
127
+ NUMERIC_COMPARISIONS.each do |key|
128
+ options[:"#{key}_message"] = key
123
129
  end
130
+
131
+ options
124
132
  end
125
133
 
126
134
  # Returns the default message for each key (:odd, :even, :equal_to, ...).
@@ -6,24 +6,9 @@ module Remarkable # :nodoc:
6
6
 
7
7
  undef_method :allow_blank?, :allow_blank, :allow_nil
8
8
 
9
- def initialize(*attributes)
10
- load_options(attributes.extract_options!)
11
- @attributes = attributes
12
- end
13
-
14
- def message(message)
15
- @options[:message] = message
16
- self
17
- end
18
-
19
- def matches?(subject)
20
- @subject = subject
21
-
22
- assert_matcher_for(@attributes) do |attribute|
23
- @attribute = attribute
24
- allow_nil?
25
- end
26
- end
9
+ arguments :attributes
10
+ optional :message
11
+ assertions :allow_nil?
27
12
 
28
13
  def description
29
14
  "require #{@attributes.to_sentence} to be set"
@@ -31,11 +16,8 @@ module Remarkable # :nodoc:
31
16
 
32
17
  private
33
18
 
34
- def load_options(options)
35
- @options = {
36
- :message => :blank,
37
- :allow_nil => false
38
- }.merge(options)
19
+ def default_options
20
+ { :message => :blank, :allow_nil => false }
39
21
  end
40
22
 
41
23
  def expectation
@@ -4,40 +4,23 @@ module Remarkable # :nodoc:
4
4
  class ValidateUniquenessOfMatcher < Remarkable::Matcher::Base
5
5
  include Remarkable::ActiveRecord::Helpers
6
6
 
7
- def initialize(*attributes)
8
- load_options(attributes.extract_options!)
9
- @attributes = attributes
10
- end
7
+ arguments :attributes
8
+ optional :case_sensitive, :default => true
9
+
10
+ assertions :find_first_object?, :have_attribute?, :case_sensitive?,
11
+ :valid_when_changing_scoped_attribute?, :find_nil_object?,
12
+ :allow_nil?, :find_blank_object?, :allow_blank?
11
13
 
12
14
  def scope(scope)
13
15
  @options[:scope] = [*scope].compact
14
16
  self
15
17
  end
16
18
 
17
- def case_sensitive(value = true)
18
- @options[:case_sensitive] = value
19
- self
20
- end
21
-
22
19
  # TODO Deprecate this
23
20
  #
24
21
  def scoped_to(scoped)
25
- warn "[DEPRECATION] should_require_unique_attributes.scoped_to is deprecated. " <<
26
- "Use should_validate_uniqueness_of.scope instead."
27
- @options[:scope] = [*scoped].compact
28
- self
29
- end
30
-
31
- def matches?(subject)
32
- @subject = get_instance_of(subject)
33
-
34
- assert_matcher_for(@attributes) do |attribute|
35
- @attribute = attribute
36
-
37
- find_first_object? && have_attribute? && case_sensitive? &&
38
- valid_when_changing_scoped_attribute? && find_nil_object? &&
39
- allow_nil? && find_blank_object? && allow_blank?
40
- end
22
+ warn "[DEPRECATION] scoped_to is deprecated. Use only scope instead."
23
+ scope(scoped)
41
24
  end
42
25
 
43
26
  def description
@@ -54,6 +37,26 @@ module Remarkable # :nodoc:
54
37
 
55
38
  private
56
39
 
40
+ # Before make the assertions, convert the subject into a instance, if
41
+ # it's not already.
42
+ #
43
+ def before_assert!
44
+ @subject = get_instance_of(@subject)
45
+ end
46
+
47
+ def default_options
48
+ { :message => :taken }
49
+ end
50
+
51
+ def after_initialize!
52
+ if @options[:scoped_to] # TODO Deprecate scoped_to
53
+ warn "[DEPRECATION] :scoped_to is deprecated. Use :scope instead."
54
+ @options[:scope] = [*@options.delete(:scoped_to)].compact
55
+ else
56
+ @options[:scope] = [*@options[:scope]].compact
57
+ end
58
+ end
59
+
57
60
  # Tries to find an object in the database.
58
61
  #
59
62
  # If allow_nil and/or allow_blank is given, we must find a record which
@@ -121,13 +124,17 @@ module Remarkable # :nodoc:
121
124
  return false
122
125
  end
123
126
 
124
- # If :case_sensitive is given and it's true, we swap the case of the
125
- # value used in have_attribute? and see if the test object is valid.
127
+ # If :case_sensitive is given and it's false, we swap the case of the
128
+ # value used in have_attribute? and see if the test object remains valid.
126
129
  #
127
130
  # If :case_sensitive is given and it's true, we swap the case of the
128
131
  # value used in have_attribute? and see if the test object is not valid.
129
132
  #
133
+ # This validation will only occur if the test object is a String.
134
+ #
130
135
  def case_sensitive?
136
+ return true unless @value.is_a?(String)
137
+
131
138
  message = "case sensitive when attribute is #{@attribute}"
132
139
  assert_good_or_bad_if_key(:case_sensitive, @value.swapcase, message)
133
140
  end
@@ -155,22 +162,6 @@ module Remarkable # :nodoc:
155
162
  (@existing.send(scope) || 999).next
156
163
  end
157
164
 
158
- def load_options(options)
159
- @options = {
160
- :message => :taken
161
- }.merge(options)
162
-
163
- if options[:scoped_to] # TODO Deprecate scoped_to
164
- warn "[DEPRECATION] should_require_unique_attributes with :scoped_to is deprecated. " <<
165
- "Use should_validate_uniqueness_of with :scope instead."
166
- @options[:scope] = [*options[:scoped_to]].compact
167
- else
168
- warn "[DEPRECATION] should_require_unique_attributes is deprecated. " <<
169
- "Use should_validate_uniqueness_of instead."
170
- @options[:scope] = [*options[:scope]].compact
171
- end
172
- end
173
-
174
165
  def expectation
175
166
  message = "that the #{subject_name} can be saved if "
176
167
 
@@ -215,8 +206,13 @@ module Remarkable # :nodoc:
215
206
  def validate_uniqueness_of(*attributes)
216
207
  ValidateUniquenessOfMatcher.new(*attributes)
217
208
  end
209
+
218
210
  #TODO Deprecate this alias, the deprecation warning is the matcher
219
- alias :require_unique_attributes :validate_uniqueness_of
211
+ def require_unique_attributes(*attributes)
212
+ warn "[DEPRECATION] should_require_unique_attributes is deprecated. " <<
213
+ "Use should_validate_uniqueness_of instead."
214
+ validate_uniqueness_of(*attributes)
215
+ end
220
216
  end
221
217
  end
222
218
  end
@@ -87,7 +87,7 @@ END
87
87
  #
88
88
  # class ValidatePresenceOfMatcher < Remarkable::Matcher::Base
89
89
  # def initialize(*attributes)
90
- # load_options(attributes.extract_options!)
90
+ # @options = default_options.merge(attributes.extract_options!)
91
91
  # @attributes = attributes
92
92
  # end
93
93
  # end
@@ -134,7 +134,7 @@ END
134
134
  # class AllowValuesForMatcher < Remarkable::Matcher::Base
135
135
  # def initialize(attribute, *good_values)
136
136
  # @attribute = attribute
137
- # load_options(good_values.extract_options!)
137
+ # @options = default_options.merge(good_values.extract_options!)
138
138
  # @good_values = good_values
139
139
  # end
140
140
  # end
@@ -152,22 +152,10 @@ END
152
152
  "@#{name} = #{name}"
153
153
  end.join("\n")
154
154
 
155
- # TODO:
156
- #
157
- # Do:
158
- #
159
- # @options = default_options.merge(#{self.loop_argument}.extract_options!)
160
- #
161
- # Instead of:
162
- #
163
- # load_options(#{self.loop_argument}.extract_options!)
164
- #
165
- # And deprecate load_options.
166
- #
167
155
  class_eval <<-END, __FILE__, __LINE__
168
156
  def initialize(#{args})
169
157
  #{assignments}
170
- load_options(#{self.loop_argument}.extract_options!)
158
+ @options = default_options.merge(#{self.loop_argument}.extract_options!)
171
159
  @#{self.loop_argument} = #{self.loop_argument}
172
160
  after_initialize!
173
161
  end
@@ -204,12 +192,6 @@ END
204
192
 
205
193
  protected
206
194
 
207
- # Do not overwrite this method. It's going to be deprecated.
208
- #
209
- def load_options(options = {})
210
- @options = default_options.merge(options)
211
- end
212
-
213
195
  # Overwrite to provide default options.
214
196
  #
215
197
  def default_options
data/rails/init.rb CHANGED
@@ -1 +1 @@
1
- require "remarkable.rb"
1
+ require "remarkable.rb" if ENV['RAILS_ENV'] == 'test'
data/remarkable.gemspec CHANGED
@@ -2,15 +2,15 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{remarkable}
5
- s.version = "2.2.3"
5
+ s.version = "2.2.4"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Carlos Brando", "Jos\303\251 Valim", "Diego Carrion"]
9
- s.date = %q{2009-02-10}
9
+ s.date = %q{2009-02-12}
10
10
  s.description = %q{}
11
11
  s.email = ["eduardobrando@gmail.com", "jose.valim@gmail.com", "dc.rec1@gmail.com"]
12
12
  s.extra_rdoc_files = ["History.txt", "Manifest.txt", "PostInstall.txt", "README.rdoc"]
13
- s.files = ["History.txt", "Manifest.txt", "PostInstall.txt", "README.rdoc", "Rakefile", "init.rb", "lib/remarkable.rb", "lib/remarkable/active_record/README.markdown", "lib/remarkable/active_record/active_record.rb", "lib/remarkable/active_record/helpers.rb", "lib/remarkable/active_record/macros.rb", "lib/remarkable/active_record/macros/associations/association_matcher.rb", "lib/remarkable/active_record/macros/callbacks/callback_matcher.rb", "lib/remarkable/active_record/macros/database/column_matcher.rb", "lib/remarkable/active_record/macros/database/index_matcher.rb", "lib/remarkable/active_record/macros/validations/allow_mass_assignment_of_matcher.rb", "lib/remarkable/active_record/macros/validations/ensure_value_in_list_matcher.rb", "lib/remarkable/active_record/macros/validations/ensure_value_in_range_matcher.rb", "lib/remarkable/active_record/macros/validations/have_class_methods_matcher.rb", "lib/remarkable/active_record/macros/validations/have_instance_methods_matcher.rb", "lib/remarkable/active_record/macros/validations/have_named_scope_matcher.rb", "lib/remarkable/active_record/macros/validations/have_readonly_attributes_matcher.rb", "lib/remarkable/active_record/macros/validations/protect_attributes_matcher.rb", "lib/remarkable/active_record/macros/validations/validate_acceptance_of_matcher.rb", "lib/remarkable/active_record/macros/validations/validate_associated_matcher.rb", "lib/remarkable/active_record/macros/validations/validate_confirmation_of_matcher.rb", "lib/remarkable/active_record/macros/validations/validate_exclusion_of_matcher.rb", "lib/remarkable/active_record/macros/validations/validate_format_of_matcher.rb", "lib/remarkable/active_record/macros/validations/validate_inclusion_of_matcher.rb", "lib/remarkable/active_record/macros/validations/validate_length_of_matcher.rb", "lib/remarkable/active_record/macros/validations/validate_numericality_of_matcher.rb", "lib/remarkable/active_record/macros/validations/validate_presence_of_matcher.rb", "lib/remarkable/active_record/macros/validations/validate_uniqueness_of_matcher.rb", "lib/remarkable/assertions.rb", "lib/remarkable/controller/README.markdown", "lib/remarkable/controller/controller.rb", "lib/remarkable/controller/helpers.rb", "lib/remarkable/controller/macros.rb", "lib/remarkable/controller/macros/assign_matcher.rb", "lib/remarkable/controller/macros/filter_params_matcher.rb", "lib/remarkable/controller/macros/metadata_matcher.rb", "lib/remarkable/controller/macros/render_with_layout_matcher.rb", "lib/remarkable/controller/macros/respond_with_content_type_matcher.rb", "lib/remarkable/controller/macros/respond_with_matcher.rb", "lib/remarkable/controller/macros/return_from_session_matcher.rb", "lib/remarkable/controller/macros/route_matcher.rb", "lib/remarkable/controller/macros/set_the_flash_to_matcher.rb", "lib/remarkable/dsl.rb", "lib/remarkable/example/example_methods.rb", "lib/remarkable/helpers.rb", "lib/remarkable/matcher_base.rb", "lib/remarkable/private_helpers.rb", "lib/remarkable/rails.rb", "rails/init.rb", "remarkable.gemspec", "script/console", "script/destroy", "script/generate", "tasks/rspec.rake"]
13
+ s.files = ["History.txt", "Manifest.txt", "PostInstall.txt", "README.rdoc", "Rakefile", "init.rb", "lib/remarkable.rb", "lib/remarkable/active_record/README.markdown", "lib/remarkable/active_record/active_record.rb", "lib/remarkable/active_record/helpers.rb", "lib/remarkable/active_record/macros.rb", "lib/remarkable/active_record/macros/associations/association_matcher.rb", "lib/remarkable/active_record/macros/callbacks/callback_matcher.rb", "lib/remarkable/active_record/macros/database/have_db_column_matcher.rb", "lib/remarkable/active_record/macros/database/index_matcher.rb", "lib/remarkable/active_record/macros/validations/allow_mass_assignment_of_matcher.rb", "lib/remarkable/active_record/macros/validations/ensure_value_in_list_matcher.rb", "lib/remarkable/active_record/macros/validations/ensure_value_in_range_matcher.rb", "lib/remarkable/active_record/macros/validations/have_class_methods_matcher.rb", "lib/remarkable/active_record/macros/validations/have_instance_methods_matcher.rb", "lib/remarkable/active_record/macros/validations/have_named_scope_matcher.rb", "lib/remarkable/active_record/macros/validations/have_readonly_attributes_matcher.rb", "lib/remarkable/active_record/macros/validations/protect_attributes_matcher.rb", "lib/remarkable/active_record/macros/validations/validate_acceptance_of_matcher.rb", "lib/remarkable/active_record/macros/validations/validate_associated_matcher.rb", "lib/remarkable/active_record/macros/validations/validate_confirmation_of_matcher.rb", "lib/remarkable/active_record/macros/validations/validate_exclusion_of_matcher.rb", "lib/remarkable/active_record/macros/validations/validate_format_of_matcher.rb", "lib/remarkable/active_record/macros/validations/validate_inclusion_of_matcher.rb", "lib/remarkable/active_record/macros/validations/validate_length_of_matcher.rb", "lib/remarkable/active_record/macros/validations/validate_numericality_of_matcher.rb", "lib/remarkable/active_record/macros/validations/validate_presence_of_matcher.rb", "lib/remarkable/active_record/macros/validations/validate_uniqueness_of_matcher.rb", "lib/remarkable/assertions.rb", "lib/remarkable/controller/README.markdown", "lib/remarkable/controller/controller.rb", "lib/remarkable/controller/helpers.rb", "lib/remarkable/controller/macros.rb", "lib/remarkable/controller/macros/assign_matcher.rb", "lib/remarkable/controller/macros/filter_params_matcher.rb", "lib/remarkable/controller/macros/metadata_matcher.rb", "lib/remarkable/controller/macros/render_with_layout_matcher.rb", "lib/remarkable/controller/macros/respond_with_content_type_matcher.rb", "lib/remarkable/controller/macros/respond_with_matcher.rb", "lib/remarkable/controller/macros/return_from_session_matcher.rb", "lib/remarkable/controller/macros/route_matcher.rb", "lib/remarkable/controller/macros/set_the_flash_to_matcher.rb", "lib/remarkable/dsl.rb", "lib/remarkable/example/example_methods.rb", "lib/remarkable/helpers.rb", "lib/remarkable/matcher_base.rb", "lib/remarkable/private_helpers.rb", "lib/remarkable/rails.rb", "rails/init.rb", "remarkable.gemspec", "script/console", "script/destroy", "script/generate", "tasks/rspec.rake"]
14
14
  s.has_rdoc = true
15
15
  s.homepage = %q{http://www.nomedojogo.com/2008/11/18/shoulda-for-rspec-is-remarkable/}
16
16
  s.post_install_message = %q{PostInstall.txt}
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: carlosbrando-remarkable
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.3
4
+ version: 2.2.4
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-02-10 00:00:00 -08:00
14
+ date: 2009-02-12 00:00:00 -08:00
15
15
  default_executable:
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
@@ -78,7 +78,7 @@ files:
78
78
  - lib/remarkable/active_record/macros.rb
79
79
  - lib/remarkable/active_record/macros/associations/association_matcher.rb
80
80
  - lib/remarkable/active_record/macros/callbacks/callback_matcher.rb
81
- - lib/remarkable/active_record/macros/database/column_matcher.rb
81
+ - lib/remarkable/active_record/macros/database/have_db_column_matcher.rb
82
82
  - lib/remarkable/active_record/macros/database/index_matcher.rb
83
83
  - lib/remarkable/active_record/macros/validations/allow_mass_assignment_of_matcher.rb
84
84
  - lib/remarkable/active_record/macros/validations/ensure_value_in_list_matcher.rb