remarkable_activerecord 3.1.8 → 3.1.9

Sign up to get free protection for your applications and to get access to all the features.
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