remarkable_activerecord 3.1.8 → 3.1.9

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.
Files changed (48) hide show
  1. data/CHANGELOG +140 -138
  2. data/LICENSE +20 -20
  3. data/README +80 -80
  4. data/lib/remarkable_activerecord.rb +29 -29
  5. data/lib/remarkable_activerecord/base.rb +248 -237
  6. data/lib/remarkable_activerecord/describe.rb +27 -27
  7. data/lib/remarkable_activerecord/human_names.rb +36 -36
  8. data/lib/remarkable_activerecord/matchers/accept_nested_attributes_for_matcher.rb +30 -30
  9. data/lib/remarkable_activerecord/matchers/allow_mass_assignment_of_matcher.rb +59 -59
  10. data/lib/remarkable_activerecord/matchers/allow_values_for_matcher.rb +85 -94
  11. data/lib/remarkable_activerecord/matchers/association_matcher.rb +283 -283
  12. data/lib/remarkable_activerecord/matchers/have_column_matcher.rb +68 -68
  13. data/lib/remarkable_activerecord/matchers/have_default_scope_matcher.rb +38 -38
  14. data/lib/remarkable_activerecord/matchers/have_index_matcher.rb +73 -73
  15. data/lib/remarkable_activerecord/matchers/have_readonly_attributes_matcher.rb +30 -30
  16. data/lib/remarkable_activerecord/matchers/have_scope_matcher.rb +85 -85
  17. data/lib/remarkable_activerecord/matchers/validate_acceptance_of_matcher.rb +50 -50
  18. data/lib/remarkable_activerecord/matchers/validate_associated_matcher.rb +97 -97
  19. data/lib/remarkable_activerecord/matchers/validate_confirmation_of_matcher.rb +44 -44
  20. data/lib/remarkable_activerecord/matchers/validate_exclusion_of_matcher.rb +53 -53
  21. data/lib/remarkable_activerecord/matchers/validate_inclusion_of_matcher.rb +52 -52
  22. data/lib/remarkable_activerecord/matchers/validate_length_of_matcher.rb +150 -150
  23. data/lib/remarkable_activerecord/matchers/validate_numericality_of_matcher.rb +181 -181
  24. data/lib/remarkable_activerecord/matchers/validate_presence_of_matcher.rb +29 -29
  25. data/lib/remarkable_activerecord/matchers/validate_uniqueness_of_matcher.rb +233 -233
  26. data/locale/en.yml +261 -261
  27. data/spec/accept_nested_attributes_for_matcher_spec.rb +1 -1
  28. data/spec/allow_mass_assignment_of_matcher_spec.rb +90 -82
  29. data/spec/allow_values_for_matcher_spec.rb +72 -63
  30. data/spec/association_matcher_spec.rb +612 -612
  31. data/spec/describe_spec.rb +3 -3
  32. data/spec/have_column_matcher_spec.rb +73 -73
  33. data/spec/have_default_scope_matcher_spec.rb +1 -1
  34. data/spec/have_index_matcher_spec.rb +87 -87
  35. data/spec/have_readonly_attributes_matcher_spec.rb +47 -47
  36. data/spec/have_scope_matcher_spec.rb +77 -77
  37. data/spec/model_builder.rb +101 -101
  38. data/spec/rcov.opts +1 -1
  39. data/spec/spec.opts +4 -4
  40. data/spec/spec_helper.rb +27 -27
  41. data/spec/validate_acceptance_of_matcher_spec.rb +68 -68
  42. data/spec/validate_associated_matcher_spec.rb +121 -121
  43. data/spec/validate_confirmation_of_matcher_spec.rb +58 -58
  44. data/spec/validate_length_of_matcher_spec.rb +218 -218
  45. data/spec/validate_numericality_of_matcher_spec.rb +179 -179
  46. data/spec/validate_presence_of_matcher_spec.rb +56 -56
  47. data/spec/validate_uniqueness_of_matcher_spec.rb +164 -164
  48. metadata +5 -5
@@ -1,68 +1,68 @@
1
- module Remarkable
2
- module ActiveRecord
3
- module Matchers
4
- class HaveColumnMatcher < Remarkable::ActiveRecord::Base #:nodoc:
5
- arguments :collection => :columns, :as => :column
6
-
7
- optional :type, :default, :precision, :limit, :scale, :sql_type
8
- optional :primary, :null, :default => true
9
-
10
- collection_assertions :column_exists?, :options_match?
11
-
12
- before_assert do
13
- @options.each{|k,v| @options[k] = v.to_s}
14
- end
15
-
16
- protected
17
-
18
- def column_exists?
19
- !column_type.nil?
20
- end
21
-
22
- def options_match?
23
- actual = get_column_options(column_type, @options.keys)
24
- return actual == @options, :actual => actual.inspect
25
- end
26
-
27
- def column_type
28
- subject_class.columns.detect {|c| c.name == @column.to_s }
29
- end
30
-
31
- def get_column_options(column, keys)
32
- keys.inject({}) do |hash, key|
33
- hash[key] = column.instance_variable_get("@#{key}").to_s
34
- hash
35
- end
36
- end
37
-
38
- def interpolation_options
39
- { :options => @options.inspect }
40
- end
41
-
42
- end
43
-
44
- # Ensures that a column of the database actually exists.
45
- #
46
- # == Options
47
- #
48
- # * All options available in migrations are available:
49
- #
50
- # :type, :default, :precision, :limit, :scale, :sql_type, :primary, :null
51
- #
52
- # == Examples
53
- #
54
- # should_have_column :name, :type => :string, :default => ''
55
- #
56
- # it { should have_column(:name, :type => :string) }
57
- # it { should have_column(:name).type(:string) }
58
- #
59
- def have_column(*args, &block)
60
- HaveColumnMatcher.new(*args, &block).spec(self)
61
- end
62
- alias :have_columns :have_column
63
- alias :have_db_column :have_column
64
- alias :have_db_columns :have_column
65
-
66
- end
67
- end
68
- end
1
+ module Remarkable
2
+ module ActiveRecord
3
+ module Matchers
4
+ class HaveColumnMatcher < Remarkable::ActiveRecord::Base #:nodoc:
5
+ arguments :collection => :columns, :as => :column
6
+
7
+ optional :type, :default, :precision, :limit, :scale, :sql_type
8
+ optional :primary, :null, :default => true
9
+
10
+ collection_assertions :column_exists?, :options_match?
11
+
12
+ before_assert do
13
+ @options.each{|k,v| @options[k] = v.to_s}
14
+ end
15
+
16
+ protected
17
+
18
+ def column_exists?
19
+ !column_type.nil?
20
+ end
21
+
22
+ def options_match?
23
+ actual = get_column_options(column_type, @options.keys)
24
+ return actual == @options, :actual => actual.inspect
25
+ end
26
+
27
+ def column_type
28
+ subject_class.columns.detect {|c| c.name == @column.to_s }
29
+ end
30
+
31
+ def get_column_options(column, keys)
32
+ keys.inject({}) do |hash, key|
33
+ hash[key] = column.instance_variable_get("@#{key}").to_s
34
+ hash
35
+ end
36
+ end
37
+
38
+ def interpolation_options
39
+ { :options => @options.inspect }
40
+ end
41
+
42
+ end
43
+
44
+ # Ensures that a column of the database actually exists.
45
+ #
46
+ # == Options
47
+ #
48
+ # * All options available in migrations are available:
49
+ #
50
+ # :type, :default, :precision, :limit, :scale, :sql_type, :primary, :null
51
+ #
52
+ # == Examples
53
+ #
54
+ # should_have_column :name, :type => :string, :default => ''
55
+ #
56
+ # it { should have_column(:name, :type => :string) }
57
+ # it { should have_column(:name).type(:string) }
58
+ #
59
+ def have_column(*args, &block)
60
+ HaveColumnMatcher.new(*args, &block).spec(self)
61
+ end
62
+ alias :have_columns :have_column
63
+ alias :have_db_column :have_column
64
+ alias :have_db_columns :have_column
65
+
66
+ end
67
+ end
68
+ end
@@ -1,15 +1,15 @@
1
- module Remarkable
2
- module ActiveRecord
3
- module Matchers
1
+ module Remarkable
2
+ module ActiveRecord
3
+ module Matchers
4
4
  class HaveDefaultScopeMatcher < Remarkable::ActiveRecord::Base #:nodoc:
5
- arguments
5
+ arguments
6
6
  assertions :options_match?
7
-
7
+
8
8
  optionals :conditions, :include, :joins, :limit, :offset, :order, :select,
9
9
  :readonly, :group, :having, :from, :lock
10
-
11
- protected
12
-
10
+
11
+ protected
12
+
13
13
  def options_match?
14
14
  default_scope.include?(@options)
15
15
  end
@@ -21,29 +21,29 @@ module Remarkable
21
21
  else
22
22
  []
23
23
  end
24
- end
25
-
26
- def interpolation_options
27
- { :options => @options.inspect, :actual => default_scope.inspect }
28
- end
29
-
30
- end
31
-
32
- # Ensures that the model has a default scope with the given options.
33
- #
34
- # == Options
35
- #
24
+ end
25
+
26
+ def interpolation_options
27
+ { :options => @options.inspect, :actual => default_scope.inspect }
28
+ end
29
+
30
+ end
31
+
32
+ # Ensures that the model has a default scope with the given options.
33
+ #
34
+ # == Options
35
+ #
36
36
  # All options that the default scope would pass on to find: :conditions,
37
37
  # :include, :joins, :limit, :offset, :order, :select, :readonly, :group,
38
- # :having, :from, :lock.
39
- #
40
- # == Examples
41
- #
42
- # it { should have_default_scope(:conditions => {:visible => true}) }
43
- # it { should have_default_scope.conditions(:visible => true) }
44
- #
45
- # Passes for:
46
- #
38
+ # :having, :from, :lock.
39
+ #
40
+ # == Examples
41
+ #
42
+ # it { should have_default_scope(:conditions => {:visible => true}) }
43
+ # it { should have_default_scope.conditions(:visible => true) }
44
+ #
45
+ # Passes for:
46
+ #
47
47
  # default_scope :conditions => { :visible => true }
48
48
  #
49
49
  # If you set two different default scopes, you have to spec them
@@ -58,12 +58,12 @@ module Remarkable
58
58
  # should_have_default_scope :conditions => { :published => true } # Passes
59
59
  #
60
60
  # should_have_default_scope :conditions => { :published => true,
61
- # :visible => true } # Fails
62
- #
63
- def have_default_scope(*args, &block)
64
- HaveDefaultScopeMatcher.new(*args, &block).spec(self)
65
- end
66
-
67
- end
68
- end
69
- end
61
+ # :visible => true } # Fails
62
+ #
63
+ def have_default_scope(*args, &block)
64
+ HaveDefaultScopeMatcher.new(*args, &block).spec(self)
65
+ end
66
+
67
+ end
68
+ end
69
+ end
@@ -1,73 +1,73 @@
1
- module Remarkable
2
- module ActiveRecord
3
- module Matchers
4
- class HaveIndexMatcher < Remarkable::ActiveRecord::Base #:nodoc:
5
- arguments :collection => :columns, :as => :column
6
-
7
- optional :table_name
8
- optional :unique, :default => true
9
-
10
- collection_assertions :index_exists?, :is_unique?
11
-
12
- protected
13
-
14
- def index_exists?
15
- !matched_index.nil?
16
- end
17
-
18
- def is_unique?
19
- return true unless @options.key?(:unique)
20
- return @options[:unique] == matched_index.unique, :actual => matched_index.unique
21
- end
22
-
23
- def matched_index
24
- columns = [@column].flatten.map(&:to_s)
25
- indexes.detect { |ind| ind.columns == columns }
26
- end
27
-
28
- def indexes
29
- @indexes ||= ::ActiveRecord::Base.connection.indexes(current_table_name)
30
- end
31
-
32
- def interpolation_options
33
- @subject ? { :table_name => current_table_name } : {}
34
- end
35
-
36
- private
37
-
38
- def current_table_name
39
- @options[:table_name] || subject_class.table_name
40
- end
41
-
42
- end
43
-
44
- # Ensures the database column has specified index.
45
- #
46
- # == Options
47
- #
48
- # * <tt>unique</tt> - when supplied, tests if the index is unique or not
49
- # * <tt>table_name</tt> - when supplied, tests if the index is defined for the given table
50
- #
51
- # == Examples
52
- #
53
- # it { should have_index(:ssn).unique(true) }
54
- # it { should have_index([:name, :email]).unique(true) }
55
- #
56
- # should_have_index :ssn, :unique => true, :limit => 9, :null => false
57
- #
58
- # should_have_index :ssn do |m|
59
- # m.unique
60
- # m.limit = 9
61
- # m.null = false
62
- # end
63
- #
64
- def have_index(*args, &block)
65
- HaveIndexMatcher.new(*args, &block).spec(self)
66
- end
67
- alias :have_indices :have_index
68
- alias :have_db_index :have_index
69
- alias :have_db_indices :have_index
70
-
71
- end
72
- end
73
- end
1
+ module Remarkable
2
+ module ActiveRecord
3
+ module Matchers
4
+ class HaveIndexMatcher < Remarkable::ActiveRecord::Base #:nodoc:
5
+ arguments :collection => :columns, :as => :column
6
+
7
+ optional :table_name
8
+ optional :unique, :default => true
9
+
10
+ collection_assertions :index_exists?, :is_unique?
11
+
12
+ protected
13
+
14
+ def index_exists?
15
+ !matched_index.nil?
16
+ end
17
+
18
+ def is_unique?
19
+ return true unless @options.key?(:unique)
20
+ return @options[:unique] == matched_index.unique, :actual => matched_index.unique
21
+ end
22
+
23
+ def matched_index
24
+ columns = [@column].flatten.map(&:to_s)
25
+ indexes.detect { |ind| ind.columns == columns }
26
+ end
27
+
28
+ def indexes
29
+ @indexes ||= ::ActiveRecord::Base.connection.indexes(current_table_name)
30
+ end
31
+
32
+ def interpolation_options
33
+ @subject ? { :table_name => current_table_name } : {}
34
+ end
35
+
36
+ private
37
+
38
+ def current_table_name
39
+ @options[:table_name] || subject_class.table_name
40
+ end
41
+
42
+ end
43
+
44
+ # Ensures the database column has specified index.
45
+ #
46
+ # == Options
47
+ #
48
+ # * <tt>unique</tt> - when supplied, tests if the index is unique or not
49
+ # * <tt>table_name</tt> - when supplied, tests if the index is defined for the given table
50
+ #
51
+ # == Examples
52
+ #
53
+ # it { should have_index(:ssn).unique(true) }
54
+ # it { should have_index([:name, :email]).unique(true) }
55
+ #
56
+ # should_have_index :ssn, :unique => true, :limit => 9, :null => false
57
+ #
58
+ # should_have_index :ssn do |m|
59
+ # m.unique
60
+ # m.limit = 9
61
+ # m.null = false
62
+ # end
63
+ #
64
+ def have_index(*args, &block)
65
+ HaveIndexMatcher.new(*args, &block).spec(self)
66
+ end
67
+ alias :have_indices :have_index
68
+ alias :have_db_index :have_index
69
+ alias :have_db_indices :have_index
70
+
71
+ end
72
+ end
73
+ end
@@ -1,30 +1,30 @@
1
- module Remarkable
2
- module ActiveRecord
3
- module Matchers
4
- class HaveReadonlyAttributesMatcher < Remarkable::ActiveRecord::Base #:nodoc:
5
- arguments :collection => :attributes, :as => :attribute
6
- collection_assertions :is_readonly?
7
-
8
- private
9
-
10
- def is_readonly?
11
- readonly = subject_class.readonly_attributes || []
12
- return readonly.include?(@attribute.to_s), :actual => readonly.to_a.inspect
13
- end
14
- end
15
-
16
- # Ensures that the attribute cannot be changed once the record has been
17
- # created.
18
- #
19
- # == Examples
20
- #
21
- # it { should have_readonly_attributes(:password, :admin_flag) }
22
- #
23
- def have_readonly_attributes(*attributes, &block)
24
- HaveReadonlyAttributesMatcher.new(*attributes, &block).spec(self)
25
- end
26
- alias :have_readonly_attribute :have_readonly_attributes
27
-
28
- end
29
- end
30
- end
1
+ module Remarkable
2
+ module ActiveRecord
3
+ module Matchers
4
+ class HaveReadonlyAttributesMatcher < Remarkable::ActiveRecord::Base #:nodoc:
5
+ arguments :collection => :attributes, :as => :attribute
6
+ collection_assertions :is_readonly?
7
+
8
+ private
9
+
10
+ def is_readonly?
11
+ readonly = subject_class.readonly_attributes || []
12
+ return readonly.include?(@attribute.to_s), :actual => readonly.to_a.inspect
13
+ end
14
+ end
15
+
16
+ # Ensures that the attribute cannot be changed once the record has been
17
+ # created.
18
+ #
19
+ # == Examples
20
+ #
21
+ # it { should have_readonly_attributes(:password, :admin_flag) }
22
+ #
23
+ def have_readonly_attributes(*attributes, &block)
24
+ HaveReadonlyAttributesMatcher.new(*attributes, &block).spec(self)
25
+ end
26
+ alias :have_readonly_attribute :have_readonly_attributes
27
+
28
+ end
29
+ end
30
+ end
@@ -1,85 +1,85 @@
1
- module Remarkable
2
- module ActiveRecord
3
- module Matchers
4
- class HaveScopeMatcher < Remarkable::ActiveRecord::Base #:nodoc:
5
- arguments :scope_name
6
- assertions :is_scope?, :options_match?
7
-
8
- optionals :with, :splat => true
9
- optionals :conditions, :include, :joins, :limit, :offset, :order, :select,
10
- :readonly, :group, :having, :from, :lock
11
-
12
- protected
13
-
14
- def is_scope?
15
- @scope_object = if @options.key?(:with)
16
- @options[:with] = [ @options[:with] ] unless Array === @options[:with]
17
- subject_class.send(@scope_name, *@options[:with])
18
- else
19
- subject_class.send(@scope_name)
20
- end
21
-
22
- @scope_object.class == ::ActiveRecord::NamedScope::Scope
23
- end
24
-
25
- def options_match?
26
- @options.empty? || @scope_object.proxy_options == @options.except(:with)
27
- end
28
-
29
- def interpolation_options
30
- { :options => @options.except(:with).inspect,
31
- :actual => (@scope_object ? @scope_object.proxy_options.inspect : '{}')
32
- }
33
- end
34
-
35
- end
36
-
37
- # Ensures that the model has a method named scope that returns a NamedScope
38
- # object with the supplied proxy options.
39
- #
40
- # == Options
41
- #
42
- # * <tt>with</tt> - Options to be sent to the named scope
43
- #
44
- # All options that the named scope would pass on to find: :conditions,
45
- # :include, :joins, :limit, :offset, :order, :select, :readonly, :group,
46
- # :having, :from, :lock.
47
- #
48
- # == Examples
49
- #
50
- # it { should have_scope(:visible, :conditions => {:visible => true}) }
51
- # it { should have_scope(:visible).conditions(:visible => true) }
52
- #
53
- # Passes for
54
- #
55
- # named_scope :visible, :conditions => {:visible => true}
56
- #
57
- # Or for
58
- #
59
- # def self.visible
60
- # scoped(:conditions => {:visible => true})
61
- # end
62
- #
63
- # You can test lambdas or methods that return ActiveRecord#scoped calls:
64
- #
65
- # it { should have_scope(:recent, :with => 5) }
66
- # it { should have_scope(:recent, :with => 1) }
67
- #
68
- # Passes for
69
- #
70
- # named_scope :recent, lambda {|c| {:limit => c}}
71
- #
72
- # Or for
73
- #
74
- # def self.recent(c)
75
- # scoped(:limit => c)
76
- # end
77
- #
78
- def have_scope(*args, &block)
79
- HaveScopeMatcher.new(*args, &block).spec(self)
80
- end
81
- alias :have_named_scope :have_scope
82
-
83
- end
84
- end
85
- end
1
+ module Remarkable
2
+ module ActiveRecord
3
+ module Matchers
4
+ class HaveScopeMatcher < Remarkable::ActiveRecord::Base #:nodoc:
5
+ arguments :scope_name
6
+ assertions :is_scope?, :options_match?
7
+
8
+ optionals :with, :splat => true
9
+ optionals :conditions, :include, :joins, :limit, :offset, :order, :select,
10
+ :readonly, :group, :having, :from, :lock
11
+
12
+ protected
13
+
14
+ def is_scope?
15
+ @scope_object = if @options.key?(:with)
16
+ @options[:with] = [ @options[:with] ] unless Array === @options[:with]
17
+ subject_class.send(@scope_name, *@options[:with])
18
+ else
19
+ subject_class.send(@scope_name)
20
+ end
21
+
22
+ @scope_object.class == ::ActiveRecord::NamedScope::Scope
23
+ end
24
+
25
+ def options_match?
26
+ @options.empty? || @scope_object.proxy_options == @options.except(:with)
27
+ end
28
+
29
+ def interpolation_options
30
+ { :options => @options.except(:with).inspect,
31
+ :actual => (@scope_object ? @scope_object.proxy_options.inspect : '{}')
32
+ }
33
+ end
34
+
35
+ end
36
+
37
+ # Ensures that the model has a method named scope that returns a NamedScope
38
+ # object with the supplied proxy options.
39
+ #
40
+ # == Options
41
+ #
42
+ # * <tt>with</tt> - Options to be sent to the named scope
43
+ #
44
+ # All options that the named scope would pass on to find: :conditions,
45
+ # :include, :joins, :limit, :offset, :order, :select, :readonly, :group,
46
+ # :having, :from, :lock.
47
+ #
48
+ # == Examples
49
+ #
50
+ # it { should have_scope(:visible, :conditions => {:visible => true}) }
51
+ # it { should have_scope(:visible).conditions(:visible => true) }
52
+ #
53
+ # Passes for
54
+ #
55
+ # named_scope :visible, :conditions => {:visible => true}
56
+ #
57
+ # Or for
58
+ #
59
+ # def self.visible
60
+ # scoped(:conditions => {:visible => true})
61
+ # end
62
+ #
63
+ # You can test lambdas or methods that return ActiveRecord#scoped calls:
64
+ #
65
+ # it { should have_scope(:recent, :with => 5) }
66
+ # it { should have_scope(:recent, :with => 1) }
67
+ #
68
+ # Passes for
69
+ #
70
+ # named_scope :recent, lambda {|c| {:limit => c}}
71
+ #
72
+ # Or for
73
+ #
74
+ # def self.recent(c)
75
+ # scoped(:limit => c)
76
+ # end
77
+ #
78
+ def have_scope(*args, &block)
79
+ HaveScopeMatcher.new(*args, &block).spec(self)
80
+ end
81
+ alias :have_named_scope :have_scope
82
+
83
+ end
84
+ end
85
+ end