remarkable_activerecord 3.0.1 → 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/CHANGELOG +46 -46
  2. data/LICENSE +1 -1
  3. data/README +64 -64
  4. data/lib/remarkable_activerecord.rb +1 -1
  5. data/lib/remarkable_activerecord/base.rb +40 -40
  6. data/lib/remarkable_activerecord/human_names.rb +24 -24
  7. data/lib/remarkable_activerecord/matchers/allow_mass_assignment_of_matcher.rb +14 -14
  8. data/lib/remarkable_activerecord/matchers/allow_values_for_matcher.rb +70 -70
  9. data/lib/remarkable_activerecord/matchers/association_matcher.rb +197 -197
  10. data/lib/remarkable_activerecord/matchers/have_column_matcher.rb +29 -29
  11. data/lib/remarkable_activerecord/matchers/have_index_matcher.rb +20 -20
  12. data/lib/remarkable_activerecord/matchers/have_readonly_attributes_matcher.rb +7 -7
  13. data/lib/remarkable_activerecord/matchers/have_scope_matcher.rb +34 -34
  14. data/lib/remarkable_activerecord/matchers/validate_acceptance_of_matcher.rb +37 -37
  15. data/lib/remarkable_activerecord/matchers/validate_associated_matcher.rb +75 -75
  16. data/lib/remarkable_activerecord/matchers/validate_confirmation_of_matcher.rb +44 -44
  17. data/lib/remarkable_activerecord/matchers/validate_exclusion_of_matcher.rb +17 -17
  18. data/lib/remarkable_activerecord/matchers/validate_inclusion_of_matcher.rb +20 -20
  19. data/lib/remarkable_activerecord/matchers/validate_numericality_of_matcher.rb +14 -14
  20. data/lib/remarkable_activerecord/matchers/validate_uniqueness_of_matcher.rb +80 -61
  21. data/locale/en.yml +253 -253
  22. data/spec/allow_mass_assignment_of_matcher_spec.rb +50 -50
  23. data/spec/allow_values_for_matcher_spec.rb +45 -45
  24. data/spec/association_matcher_spec.rb +612 -612
  25. data/spec/have_column_matcher_spec.rb +67 -67
  26. data/spec/have_index_matcher_spec.rb +61 -61
  27. data/spec/have_readonly_attributes_matcher_spec.rb +40 -40
  28. data/spec/have_scope_matcher_spec.rb +60 -60
  29. data/spec/model_builder.rb +101 -101
  30. data/spec/spec_helper.rb +25 -25
  31. data/spec/validate_acceptance_of_matcher_spec.rb +64 -64
  32. data/spec/validate_associated_matcher_spec.rb +118 -118
  33. data/spec/validate_confirmation_of_matcher_spec.rb +54 -54
  34. data/spec/validate_exclusion_of_matcher_spec.rb +76 -76
  35. data/spec/validate_inclusion_of_matcher_spec.rb +72 -72
  36. data/spec/validate_numericality_of_matcher_spec.rb +100 -100
  37. data/spec/validate_presence_of_matcher_spec.rb +40 -40
  38. data/spec/validate_uniqueness_of_matcher_spec.rb +158 -139
  39. metadata +3 -3
data/CHANGELOG CHANGED
@@ -1,47 +1,47 @@
1
1
  # v3.0.0
2
-
3
- [ENHANCEMENT] Added more options to associations matcher. Previously it was
4
- handling just :dependent and :through options. Now it deals with:
5
-
6
- :through, :class_name, :foreign_key, :dependent, :join_table, :uniq,
7
- :readonly, :validate, :autosave, :counter_cache, :polymorphic
8
-
9
- And they are much smarter! In :join_table and :through cases, they also test if
10
- the table exists or not. :counter_cache and :foreign_key also checks if the
11
- column exists or not.
12
-
13
- [COMPATIBILITY] Removed callback, have_instance_method and have_class_method
14
- matchers. They don't lead to a good TDD since you should test they behavior
15
- and not wether they exist or not.
16
-
17
- [COMPATIBILITY] ActiveRecord matches does not pick the instance variable from
18
- the spec environment. So we should target only rspec versions that supports
19
- subjects (>= 1.1.12).
20
-
21
- Previously, when we are doing this:
22
-
23
- describe Product
24
- before(:each){ @product = Product.new(:tangible => true) }
25
- should_validate_presence_of :size
26
- end
27
-
28
- It was validating the @product instance variable. However this might be not
29
- clear. The right way to do that (with subjects) is:
30
-
31
- describe Product
32
- subject{ Product.new(:tangible => true) }
33
- should_validate_presence_of :size
34
- end
35
-
36
- Is also valid to remember that previous versions of Remarkable were overriding
37
- subject definitions on rspec. This was also fixed.
38
-
39
- # v2.x
40
-
41
- [ENHANCEMENT] Added associations, allow_mass_assignment, allow_values_for,
42
- have_column, have_index, have_scope, have_readonly_attributes,
43
- validate_acceptance_of, validate_associate, validate_confirmation_of,
44
- validate_exclusion_of, validate_inclusion_of, validate_length_of,
45
- validate_numericality_of, validate_presence_of and validate_uniqueness_of
46
- matchers.
47
-
2
+
3
+ [ENHANCEMENT] Added more options to associations matcher. Previously it was
4
+ handling just :dependent and :through options. Now it deals with:
5
+
6
+ :through, :class_name, :foreign_key, :dependent, :join_table, :uniq,
7
+ :readonly, :validate, :autosave, :counter_cache, :polymorphic
8
+
9
+ And they are much smarter! In :join_table and :through cases, they also test if
10
+ the table exists or not. :counter_cache and :foreign_key also checks if the
11
+ column exists or not.
12
+
13
+ [COMPATIBILITY] Removed callback, have_instance_method and have_class_method
14
+ matchers. They don't lead to a good TDD since you should test they behavior
15
+ and not wether they exist or not.
16
+
17
+ [COMPATIBILITY] ActiveRecord matches does not pick the instance variable from
18
+ the spec environment. So we should target only rspec versions that supports
19
+ subjects (>= 1.1.12).
20
+
21
+ Previously, when we are doing this:
22
+
23
+ describe Product
24
+ before(:each){ @product = Product.new(:tangible => true) }
25
+ should_validate_presence_of :size
26
+ end
27
+
28
+ It was validating the @product instance variable. However this might be not
29
+ clear. The right way to do that (with subjects) is:
30
+
31
+ describe Product
32
+ subject{ Product.new(:tangible => true) }
33
+ should_validate_presence_of :size
34
+ end
35
+
36
+ Is also valid to remember that previous versions of Remarkable were overriding
37
+ subject definitions on rspec. This was also fixed.
38
+
39
+ # v2.x
40
+
41
+ [ENHANCEMENT] Added associations, allow_mass_assignment, allow_values_for,
42
+ have_column, have_index, have_scope, have_readonly_attributes,
43
+ validate_acceptance_of, validate_associate, validate_confirmation_of,
44
+ validate_exclusion_of, validate_inclusion_of, validate_length_of,
45
+ validate_numericality_of, validate_presence_of and validate_uniqueness_of
46
+ matchers.
47
+
data/LICENSE CHANGED
@@ -17,4 +17,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
17
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
18
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
19
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README CHANGED
@@ -1,82 +1,82 @@
1
- = Remarkable ActiveRecord
2
-
3
- Remarkable ActiveRecord is a collection of matchers to ActiveRecord. Why use
4
- Remarkable?
5
-
6
- * The only one with matchers for all ActiveRecord validations, with support to
7
- all options;
8
-
9
- * Matchers for all ActiveRecord associations. The only one which supports all
10
- these options:
11
-
12
- :through, :class_name, :foreign_key, :dependent, :join_table, :uniq,
13
- :readonly, :validate, :autosave, :counter_cache, :polymorphic
14
-
15
- Besides in Remarkable 3.0 matchers became much smarter. Whenever :join_table
16
- or :through is given as option, it checks if the given table exists. Whenever
17
- :foreign_key or :counter_cache is given, it checks if the given column exists;
18
-
19
- * Tests and more tests. We have a huge tests suite ready to run and tested in
20
- ActiveRecord 2.1.2, 2.2.2 and 2.3.2;
21
-
22
- * Great documentation;
23
-
24
- * I18n.
25
-
26
- == Examples
27
-
1
+ = Remarkable ActiveRecord
2
+
3
+ Remarkable ActiveRecord is a collection of matchers to ActiveRecord. Why use
4
+ Remarkable?
5
+
6
+ * The only one with matchers for all ActiveRecord validations, with support to
7
+ all options;
8
+
9
+ * Matchers for all ActiveRecord associations. The only one which supports all
10
+ these options:
11
+
12
+ :through, :class_name, :foreign_key, :dependent, :join_table, :uniq,
13
+ :readonly, :validate, :autosave, :counter_cache, :polymorphic
14
+
15
+ Besides in Remarkable 3.0 matchers became much smarter. Whenever :join_table
16
+ or :through is given as option, it checks if the given table exists. Whenever
17
+ :foreign_key or :counter_cache is given, it checks if the given column exists;
18
+
19
+ * Tests and more tests. We have a huge tests suite ready to run and tested in
20
+ ActiveRecord 2.1.2, 2.2.2 and 2.3.2;
21
+
22
+ * Great documentation;
23
+
24
+ * I18n.
25
+
26
+ == Examples
27
+
28
28
  All Remarkable macros can be accessed in two different ways. For those who prefer the Shoulda style, let’s look at some model tests:
29
29
 
30
30
  describe Post do
31
31
  should_belong_to :user
32
- should_have_many :comments
32
+ should_have_many :comments
33
33
  should_have_and_belong_to_many :tags
34
34
 
35
35
  should_validate_presence_of :body
36
- should_validate_presence_of :title
36
+ should_validate_presence_of :title
37
37
  should_validate_uniqueness_of :title, :allow_blank => true
38
38
  end
39
-
39
+
40
40
  For those who likes more the Rspec way can simply do:
41
41
 
42
42
  describe Post do
43
43
  it { should belong_to(:user) }
44
- it { should have_many(:comments) }
44
+ it { should have_many(:comments) }
45
45
  it { should have_and_belong_to_many(:tags) }
46
46
 
47
47
  it { should validate_presence_of(:body) }
48
- it { should validate_presence_of(:title) }
48
+ it { should validate_presence_of(:title) }
49
49
  it { should validate_uniqueness_of(:title, :allow_blank => true) }
50
- end
51
-
52
- == I18n
53
-
54
- All matchers come with I18n support. If you want to translate your matchers,
55
- grab make a copy of locale/en.yml and start to translate it.
56
-
57
- Then add your new locale file to Remarkable:
58
-
59
- Remarkable.add_locale 'path/to/my_locale.yml'
60
-
61
- And then:
62
-
63
- Remarkable.locale = :my_locale
64
-
65
- == Using it outside Rails
66
-
67
- If you want to use Remarkable ActiveRecord outside Rails, you have to remember
68
- a few things:
69
-
70
- 1. Internationalization is powered by the I18n gem. If you are using it with Rails,
71
- it will use the built in gem, otherwise you will have to install the gem by hand:
72
-
50
+ end
51
+
52
+ == I18n
53
+
54
+ All matchers come with I18n support. If you want to translate your matchers,
55
+ grab make a copy of locale/en.yml and start to translate it.
56
+
57
+ Then add your new locale file to Remarkable:
58
+
59
+ Remarkable.add_locale 'path/to/my_locale.yml'
60
+
61
+ And then:
62
+
63
+ Remarkable.locale = :my_locale
64
+
65
+ == Using it outside Rails
66
+
67
+ If you want to use Remarkable ActiveRecord outside Rails, you have to remember
68
+ a few things:
69
+
70
+ 1. Internationalization is powered by the I18n gem. If you are using it with Rails,
71
+ it will use the built in gem, otherwise you will have to install the gem by hand:
72
+
73
73
  gem sources -a http://gems.github.com
74
- sudo gem install svenfuchs-i18n
75
-
76
- 2. Include the matchers. Remarkable Rails gem is the responsable to add
77
- ActiveRecord matchers to rspec. If you are not using it, you have to do:
78
-
79
- Remarkable.include_matchers!(Remarkable::ActiveRecord, Spec::Example::ExampleGroup)
80
-
81
- This will make ActiveRecord matchers available in all rspec example groups.
82
-
74
+ sudo gem install svenfuchs-i18n
75
+
76
+ 2. Include the matchers. Remarkable Rails gem is the responsable to add
77
+ ActiveRecord matchers to rspec. If you are not using it, you have to do:
78
+
79
+ Remarkable.include_matchers!(Remarkable::ActiveRecord, Spec::Example::ExampleGroup)
80
+
81
+ This will make ActiveRecord matchers available in all rspec example groups.
82
+
@@ -12,7 +12,7 @@ end
12
12
  # Load Remarkable ActiveRecord files
13
13
  dir = File.dirname(__FILE__)
14
14
  require File.join(dir, 'remarkable_activerecord', 'base')
15
- require File.join(dir, 'remarkable_activerecord', 'human_names')
15
+ require File.join(dir, 'remarkable_activerecord', 'human_names')
16
16
 
17
17
  # Add locale
18
18
  Remarkable.add_locale File.join(dir, '..', 'locale', 'en.yml')
@@ -1,20 +1,20 @@
1
1
  module Remarkable
2
2
  module ActiveRecord
3
3
  class Base < Remarkable::Base
4
-
5
- # Provides a way to send options to all ActiveRecord matchers.
6
- #
7
- # validates_presence_of(:name).with_options(:allow_nil => false)
8
- #
9
- # Is equivalent to:
10
- #
11
- # validates_presence_of(:name, :allow_nil => false)
12
- #
4
+
5
+ # Provides a way to send options to all ActiveRecord matchers.
6
+ #
7
+ # validates_presence_of(:name).with_options(:allow_nil => false)
8
+ #
9
+ # Is equivalent to:
10
+ #
11
+ # validates_presence_of(:name, :allow_nil => false)
12
+ #
13
13
  def with_options(opts={})
14
14
  @options.merge!(opts)
15
15
  self
16
- end
17
-
16
+ end
17
+
18
18
  protected
19
19
 
20
20
  # Checks for the given key in @options, if it exists and it's true,
@@ -63,7 +63,7 @@ module Remarkable
63
63
  valid, options = assert_good_or_bad_if_key(:allow_nil, nil, message_key)
64
64
 
65
65
  unless valid
66
- default = Remarkable.t "remarkable.active_record.allow_nil", default_i18n_options.except(:scope).merge(options)
66
+ default = Remarkable.t "remarkable.active_record.allow_nil", default_i18n_options.except(:scope).merge(options)
67
67
  return false, options.merge(:default => default)
68
68
  end
69
69
 
@@ -181,7 +181,7 @@ module Remarkable
181
181
  # Using the underlying mechanism inside ActiveRecord makes us free from
182
182
  # all thos errors.
183
183
  #
184
- # We replace {{count}} interpolation for 12345 which later is replaced
184
+ # We replace {{count}} interpolation for 12345 which later is replaced
185
185
  # by a regexp which contains \d+.
186
186
  #
187
187
  def error_message_from_model(model, attribute, message) #:nodoc:
@@ -208,37 +208,37 @@ module Remarkable
208
208
  #
209
209
  def assert_does_not_contain(collection, x) #:nodoc:
210
210
  !assert_contains(collection, x)
211
- end
212
-
213
- # Changes how collection are interpolated to provide localized names
214
- # whenever is possible.
215
- #
216
- def collection_interpolation #:nodoc:
217
- described_class = if @subject
218
- subject_class
219
- elsif @spec
220
- @spec.send(:described_class)
221
- end
222
-
223
- if RAILS_I18N && described_class.respond_to?(:human_attribute_name) && self.class.matcher_arguments[:collection]
224
- options = {}
225
-
226
- collection_name = self.class.matcher_arguments[:collection].to_sym
227
- if collection = instance_variable_get("@#{collection_name}")
211
+ end
212
+
213
+ # Changes how collection are interpolated to provide localized names
214
+ # whenever is possible.
215
+ #
216
+ def collection_interpolation #:nodoc:
217
+ described_class = if @subject
218
+ subject_class
219
+ elsif @spec
220
+ @spec.send(:described_class)
221
+ end
222
+
223
+ if RAILS_I18N && described_class.respond_to?(:human_attribute_name) && self.class.matcher_arguments[:collection]
224
+ options = {}
225
+
226
+ collection_name = self.class.matcher_arguments[:collection].to_sym
227
+ if collection = instance_variable_get("@#{collection_name}")
228
228
  collection.map!{|attr| described_class.human_attribute_name(attr.to_s, :locale => Remarkable.locale).downcase }
229
- options[collection_name] = array_to_sentence(collection)
229
+ options[collection_name] = array_to_sentence(collection)
230
230
  end
231
-
231
+
232
232
  object_name = self.class.matcher_arguments[:as]
233
- if object = instance_variable_get("@#{object_name}")
233
+ if object = instance_variable_get("@#{object_name}")
234
234
  object = described_class.human_attribute_name(object.to_s, :locale => Remarkable.locale).downcase
235
- options[object_name] = object
236
- end
237
-
238
- options
239
- else
240
- super
241
- end
235
+ options[object_name] = object
236
+ end
237
+
238
+ options
239
+ else
240
+ super
241
+ end
242
242
  end
243
243
 
244
244
  end
@@ -1,37 +1,37 @@
1
- if defined?(Spec)
1
+ if defined?(Spec)
2
2
  module Spec #:nodoc:
3
3
  module Example #:nodoc:
4
4
  module ExampleGroupMethods #:nodoc:
5
5
 
6
- # This allows "describe User" to use the I18n human name of User.
7
- #
8
- def self.build_description_with_i18n(*args)
6
+ # This allows "describe User" to use the I18n human name of User.
7
+ #
8
+ def self.build_description_with_i18n(*args)
9
9
  args.inject("") do |description, arg|
10
- arg = if RAILS_I18N && arg.respond_to?(:human_name)
11
- arg.human_name(:locale => Remarkable.locale)
12
- else
13
- arg.to_s
14
- end
10
+ arg = if RAILS_I18N && arg.respond_to?(:human_name)
11
+ arg.human_name(:locale => Remarkable.locale)
12
+ else
13
+ arg.to_s
14
+ end
15
15
 
16
16
  description << " " unless (description == "" || arg =~ /^(\s|\.|#)/)
17
17
  description << arg
18
- end
19
- end
20
-
21
- # This is for rspec <= 1.1.12.
18
+ end
19
+ end
20
+
21
+ # This is for rspec <= 1.1.12.
22
22
  #
23
- def self.description_text(*args)
23
+ def self.description_text(*args)
24
24
  self.build_description_with_i18n(*args)
25
- end
26
-
27
- # This is for rspec >= 1.2.0.
28
- #
29
- def build_description_from(*args)
30
- text = ExampleGroupMethods.build_description_with_i18n(*args)
31
- text == "" ? nil : text
32
- end
25
+ end
26
+
27
+ # This is for rspec >= 1.2.0.
28
+ #
29
+ def build_description_from(*args)
30
+ text = ExampleGroupMethods.build_description_with_i18n(*args)
31
+ text == "" ? nil : text
32
+ end
33
33
 
34
34
  end
35
35
  end
36
- end
37
- end
36
+ end
37
+ end
@@ -1,31 +1,31 @@
1
1
  module Remarkable
2
2
  module ActiveRecord
3
3
  module Matchers
4
- class AllowMassAssignmentOfMatcher < Remarkable::ActiveRecord::Base #:nodoc:
5
- arguments :collection => :attributes, :as => :attribute
6
-
4
+ class AllowMassAssignmentOfMatcher < Remarkable::ActiveRecord::Base #:nodoc:
5
+ arguments :collection => :attributes, :as => :attribute
6
+
7
7
  collection_assertions :is_protected?, :is_accessible?
8
8
 
9
9
  protected
10
10
 
11
- def is_protected?
12
- protected = subject_class.protected_attributes || []
13
- protected.empty? || !protected.include?(@attribute.to_s)
14
- end
15
-
11
+ def is_protected?
12
+ protected = subject_class.protected_attributes || []
13
+ protected.empty? || !protected.include?(@attribute.to_s)
14
+ end
15
+
16
16
  def is_accessible?
17
17
  accessible = subject_class.accessible_attributes || []
18
- accessible.empty? || accessible.include?(@attribute.to_s)
19
- end
18
+ accessible.empty? || accessible.include?(@attribute.to_s)
19
+ end
20
20
  end
21
21
 
22
- # Ensures that the attribute can be set on mass update.
23
- #
22
+ # Ensures that the attribute can be set on mass update.
23
+ #
24
24
  # == Examples
25
25
  #
26
- # should_allow_mass_assignment_of :email, :name
26
+ # should_allow_mass_assignment_of :email, :name
27
27
  # it { should allow_mass_assignment_of(:email, :name) }
28
- #
28
+ #
29
29
  def allow_mass_assignment_of(*attributes)
30
30
  AllowMassAssignmentOfMatcher.new(*attributes).spec(self)
31
31
  end