remarkable_activerecord 3.0.1 → 3.0.2
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.
- data/CHANGELOG +46 -46
- data/LICENSE +1 -1
- data/README +64 -64
- data/lib/remarkable_activerecord.rb +1 -1
- data/lib/remarkable_activerecord/base.rb +40 -40
- data/lib/remarkable_activerecord/human_names.rb +24 -24
- data/lib/remarkable_activerecord/matchers/allow_mass_assignment_of_matcher.rb +14 -14
- data/lib/remarkable_activerecord/matchers/allow_values_for_matcher.rb +70 -70
- data/lib/remarkable_activerecord/matchers/association_matcher.rb +197 -197
- data/lib/remarkable_activerecord/matchers/have_column_matcher.rb +29 -29
- data/lib/remarkable_activerecord/matchers/have_index_matcher.rb +20 -20
- data/lib/remarkable_activerecord/matchers/have_readonly_attributes_matcher.rb +7 -7
- data/lib/remarkable_activerecord/matchers/have_scope_matcher.rb +34 -34
- data/lib/remarkable_activerecord/matchers/validate_acceptance_of_matcher.rb +37 -37
- data/lib/remarkable_activerecord/matchers/validate_associated_matcher.rb +75 -75
- data/lib/remarkable_activerecord/matchers/validate_confirmation_of_matcher.rb +44 -44
- data/lib/remarkable_activerecord/matchers/validate_exclusion_of_matcher.rb +17 -17
- data/lib/remarkable_activerecord/matchers/validate_inclusion_of_matcher.rb +20 -20
- data/lib/remarkable_activerecord/matchers/validate_numericality_of_matcher.rb +14 -14
- data/lib/remarkable_activerecord/matchers/validate_uniqueness_of_matcher.rb +80 -61
- data/locale/en.yml +253 -253
- data/spec/allow_mass_assignment_of_matcher_spec.rb +50 -50
- data/spec/allow_values_for_matcher_spec.rb +45 -45
- data/spec/association_matcher_spec.rb +612 -612
- data/spec/have_column_matcher_spec.rb +67 -67
- data/spec/have_index_matcher_spec.rb +61 -61
- data/spec/have_readonly_attributes_matcher_spec.rb +40 -40
- data/spec/have_scope_matcher_spec.rb +60 -60
- data/spec/model_builder.rb +101 -101
- data/spec/spec_helper.rb +25 -25
- data/spec/validate_acceptance_of_matcher_spec.rb +64 -64
- data/spec/validate_associated_matcher_spec.rb +118 -118
- data/spec/validate_confirmation_of_matcher_spec.rb +54 -54
- data/spec/validate_exclusion_of_matcher_spec.rb +76 -76
- data/spec/validate_inclusion_of_matcher_spec.rb +72 -72
- data/spec/validate_numericality_of_matcher_spec.rb +100 -100
- data/spec/validate_presence_of_matcher_spec.rb +40 -40
- data/spec/validate_uniqueness_of_matcher_spec.rb +158 -139
- metadata +3 -3
@@ -1,92 +1,92 @@
|
|
1
1
|
module Remarkable
|
2
2
|
module ActiveRecord
|
3
|
-
module Matchers
|
3
|
+
module Matchers
|
4
4
|
class AllowValuesForMatcher < Remarkable::ActiveRecord::Base #:nodoc:
|
5
|
-
arguments :collection => :attributes, :as => :attribute
|
6
|
-
|
7
|
-
optional :message
|
8
|
-
optional :in, :splat => true
|
5
|
+
arguments :collection => :attributes, :as => :attribute
|
6
|
+
|
7
|
+
optional :message
|
8
|
+
optional :in, :splat => true
|
9
9
|
optional :allow_nil, :allow_blank, :default => true
|
10
|
-
|
11
|
-
collection_assertions :is_valid?, :is_invalid?, :allow_nil?, :allow_blank?
|
12
|
-
|
13
|
-
default_options :message => :invalid
|
14
|
-
|
15
|
-
before_assert do
|
16
|
-
first_value = @options[:in].is_a?(Array) ? @options[:in].first : @options[:in]
|
17
|
-
@in_range = first_value.is_a?(Range)
|
18
|
-
|
19
|
-
@options[:in] = if @in_range
|
20
|
-
first_value.to_a[0,2] + first_value.to_a[-2,2]
|
21
|
-
else
|
22
|
-
[*@options[:in]].compact
|
23
|
-
end
|
24
|
-
|
25
|
-
@options[:in].uniq!
|
26
|
-
end
|
27
|
-
|
28
|
-
protected
|
29
|
-
|
30
|
-
def is_valid?
|
31
|
-
valid_values.each do |value|
|
32
|
-
return false, :value => value.inspect unless good?(value)
|
33
|
-
end
|
34
|
-
true
|
35
|
-
end
|
36
|
-
|
37
|
-
def is_invalid?
|
38
|
-
invalid_values.each do |value|
|
39
|
-
return false, :value => value.inspect unless bad?(value)
|
40
|
-
end
|
41
|
-
true
|
42
|
-
end
|
43
|
-
|
44
|
-
def valid_values
|
45
|
-
@options[:in]
|
46
|
-
end
|
47
|
-
|
48
|
-
def invalid_values
|
49
|
-
[]
|
50
|
-
end
|
51
|
-
|
52
|
-
def interpolation_options
|
53
|
-
options = if @in_range
|
54
|
-
{ :in => (@options[:in].first..@options[:in].last).inspect }
|
55
|
-
elsif @options[:in].is_a?(Array)
|
56
|
-
{ :in => @options[:in].map(&:inspect).to_sentence }
|
57
|
-
else
|
58
|
-
{ :in => @options[:in].inspect }
|
59
|
-
end
|
60
|
-
|
61
|
-
options.merge!(:behavior => @behavior.to_s)
|
62
|
-
end
|
10
|
+
|
11
|
+
collection_assertions :is_valid?, :is_invalid?, :allow_nil?, :allow_blank?
|
12
|
+
|
13
|
+
default_options :message => :invalid
|
14
|
+
|
15
|
+
before_assert do
|
16
|
+
first_value = @options[:in].is_a?(Array) ? @options[:in].first : @options[:in]
|
17
|
+
@in_range = first_value.is_a?(Range)
|
18
|
+
|
19
|
+
@options[:in] = if @in_range
|
20
|
+
first_value.to_a[0,2] + first_value.to_a[-2,2]
|
21
|
+
else
|
22
|
+
[*@options[:in]].compact
|
23
|
+
end
|
24
|
+
|
25
|
+
@options[:in].uniq!
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
def is_valid?
|
31
|
+
valid_values.each do |value|
|
32
|
+
return false, :value => value.inspect unless good?(value)
|
33
|
+
end
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
def is_invalid?
|
38
|
+
invalid_values.each do |value|
|
39
|
+
return false, :value => value.inspect unless bad?(value)
|
40
|
+
end
|
41
|
+
true
|
42
|
+
end
|
43
|
+
|
44
|
+
def valid_values
|
45
|
+
@options[:in]
|
46
|
+
end
|
47
|
+
|
48
|
+
def invalid_values
|
49
|
+
[]
|
50
|
+
end
|
51
|
+
|
52
|
+
def interpolation_options
|
53
|
+
options = if @in_range
|
54
|
+
{ :in => (@options[:in].first..@options[:in].last).inspect }
|
55
|
+
elsif @options[:in].is_a?(Array)
|
56
|
+
{ :in => @options[:in].map(&:inspect).to_sentence }
|
57
|
+
else
|
58
|
+
{ :in => @options[:in].inspect }
|
59
|
+
end
|
60
|
+
|
61
|
+
options.merge!(:behavior => @behavior.to_s)
|
62
|
+
end
|
63
63
|
|
64
64
|
end
|
65
65
|
|
66
66
|
# Ensures that the attribute can be set to the given values.
|
67
67
|
#
|
68
|
-
# Note: this matcher accepts at once just one attribute to test.
|
69
|
-
# Note: this matcher is also aliased as "validate_format_of".
|
70
|
-
#
|
71
|
-
# == Options
|
72
|
-
#
|
68
|
+
# Note: this matcher accepts at once just one attribute to test.
|
69
|
+
# Note: this matcher is also aliased as "validate_format_of".
|
70
|
+
#
|
71
|
+
# == Options
|
72
|
+
#
|
73
73
|
# * <tt>:allow_nil</tt> - when supplied, validates if it allows nil or not.
|
74
|
-
# * <tt>:allow_blank</tt> - when supplied, validates if it allows blank or not.
|
75
|
-
# * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
74
|
+
# * <tt>:allow_blank</tt> - when supplied, validates if it allows blank or not.
|
75
|
+
# * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
76
76
|
# Regexp, string or symbol. Default = <tt>I18n.translate('activerecord.errors.messages.invalid')</tt>
|
77
77
|
#
|
78
|
-
# == Examples
|
79
|
-
#
|
78
|
+
# == Examples
|
79
|
+
#
|
80
80
|
# should_allow_values_for :isbn, "isbn 1 2345 6789 0", "ISBN 1-2345-6789-0"
|
81
|
-
# should_not_allow_values_for :isbn, "bad 1", "bad 2"
|
81
|
+
# should_not_allow_values_for :isbn, "bad 1", "bad 2"
|
82
82
|
#
|
83
83
|
# it { should allow_values_for(:isbn, "isbn 1 2345 6789 0", "ISBN 1-2345-6789-0") }
|
84
84
|
# it { should_not allow_values_for(:isbn, "bad 1", "bad 2") }
|
85
85
|
#
|
86
|
-
def allow_values_for(attribute, *args)
|
86
|
+
def allow_values_for(attribute, *args)
|
87
87
|
options = args.extract_options!
|
88
88
|
AllowValuesForMatcher.new(attribute, options.merge!(:in => args)).spec(self)
|
89
|
-
end
|
89
|
+
end
|
90
90
|
alias :validate_format_of :allow_values_for
|
91
91
|
|
92
92
|
end
|
@@ -1,230 +1,230 @@
|
|
1
1
|
module Remarkable
|
2
2
|
module ActiveRecord
|
3
3
|
module Matchers
|
4
|
-
class AssociationMatcher < Remarkable::ActiveRecord::Base #:nodoc:
|
5
|
-
arguments :macro, :collection => :associations, :as => :association
|
6
|
-
|
7
|
-
optionals :through, :class_name, :foreign_key, :dependent, :join_table, :as
|
8
|
-
optionals :uniq, :readonly, :validate, :autosave, :polymorphic, :counter_cache, :default => true
|
9
|
-
|
10
|
-
# Stores optionals declared above in a CONSTANT to generate assertions
|
11
|
-
ASSOCIATION_OPTIONS = self.matcher_optionals
|
12
|
-
|
13
|
-
collection_assertions :association_exists?, :macro_matches?, :through_exists?,
|
14
|
-
:join_table_exists?, :foreign_key_exists?, :polymorphic_exists?,
|
15
|
-
:counter_cache_exists?
|
16
|
-
|
17
|
-
protected
|
18
|
-
|
19
|
-
def association_exists?
|
4
|
+
class AssociationMatcher < Remarkable::ActiveRecord::Base #:nodoc:
|
5
|
+
arguments :macro, :collection => :associations, :as => :association
|
6
|
+
|
7
|
+
optionals :through, :class_name, :foreign_key, :dependent, :join_table, :as
|
8
|
+
optionals :uniq, :readonly, :validate, :autosave, :polymorphic, :counter_cache, :default => true
|
9
|
+
|
10
|
+
# Stores optionals declared above in a CONSTANT to generate assertions
|
11
|
+
ASSOCIATION_OPTIONS = self.matcher_optionals
|
12
|
+
|
13
|
+
collection_assertions :association_exists?, :macro_matches?, :through_exists?,
|
14
|
+
:join_table_exists?, :foreign_key_exists?, :polymorphic_exists?,
|
15
|
+
:counter_cache_exists?
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def association_exists?
|
20
20
|
reflection
|
21
21
|
end
|
22
22
|
|
23
23
|
def macro_matches?
|
24
24
|
reflection.macro == @macro
|
25
|
-
end
|
26
|
-
|
27
|
-
def through_exists?
|
28
|
-
return true unless @options.key?(:through)
|
29
|
-
subject_class.reflect_on_association(@options[:through])
|
30
|
-
end
|
31
|
-
|
32
|
-
def join_table_exists?
|
33
|
-
return true unless has_join_table?
|
25
|
+
end
|
26
|
+
|
27
|
+
def through_exists?
|
28
|
+
return true unless @options.key?(:through)
|
29
|
+
subject_class.reflect_on_association(@options[:through])
|
30
|
+
end
|
31
|
+
|
32
|
+
def join_table_exists?
|
33
|
+
return true unless has_join_table?
|
34
34
|
::ActiveRecord::Base.connection.tables.include?(reflection_join_table)
|
35
35
|
end
|
36
|
-
|
37
|
-
def foreign_key_exists?
|
38
|
-
table_has_column?(foreign_key_table, reflection_foreign_key)
|
39
|
-
end
|
40
|
-
|
41
|
-
def polymorphic_exists?
|
42
|
-
return true unless @options[:polymorphic]
|
43
|
-
table_has_column?(subject_class.table_name, reflection_foreign_key.sub(/_id$/, '_type'))
|
44
|
-
end
|
45
|
-
|
46
|
-
def counter_cache_exists?
|
47
|
-
return true unless @options[:counter_cache]
|
36
|
+
|
37
|
+
def foreign_key_exists?
|
38
|
+
table_has_column?(foreign_key_table, reflection_foreign_key)
|
39
|
+
end
|
40
|
+
|
41
|
+
def polymorphic_exists?
|
42
|
+
return true unless @options[:polymorphic]
|
43
|
+
table_has_column?(subject_class.table_name, reflection_foreign_key.sub(/_id$/, '_type'))
|
44
|
+
end
|
45
|
+
|
46
|
+
def counter_cache_exists?
|
47
|
+
return true unless @options[:counter_cache]
|
48
48
|
table_has_column?(reflection.klass.table_name, reflection.counter_cache_column.to_s)
|
49
|
-
end
|
50
|
-
|
51
|
-
ASSOCIATION_OPTIONS.each do |option|
|
52
|
-
collection_assertion :"#{option}_matches?"
|
53
|
-
|
54
|
-
class_eval <<-METHOD, __FILE__, __LINE__
|
55
|
-
def #{option}_matches?
|
56
|
-
return true unless @options.key?(#{option.inspect})
|
57
|
-
actual_value = respond_to?(:reflection_#{option}, true) ? reflection_#{option} : reflection.options[#{option.inspect}].to_s
|
58
|
-
|
59
|
-
return true if @options[#{option.inspect}].to_s == actual_value
|
60
|
-
end
|
61
|
-
METHOD
|
62
|
-
end
|
63
|
-
|
64
|
-
private
|
65
|
-
|
49
|
+
end
|
50
|
+
|
51
|
+
ASSOCIATION_OPTIONS.each do |option|
|
52
|
+
collection_assertion :"#{option}_matches?"
|
53
|
+
|
54
|
+
class_eval <<-METHOD, __FILE__, __LINE__
|
55
|
+
def #{option}_matches?
|
56
|
+
return true unless @options.key?(#{option.inspect})
|
57
|
+
actual_value = respond_to?(:reflection_#{option}, true) ? reflection_#{option} : reflection.options[#{option.inspect}].to_s
|
58
|
+
|
59
|
+
return true if @options[#{option.inspect}].to_s == actual_value
|
60
|
+
end
|
61
|
+
METHOD
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
66
|
def reflection
|
67
67
|
@reflection ||= subject_class.reflect_on_association(@association.to_sym)
|
68
|
-
end
|
69
|
-
|
70
|
-
# Rescue nil to avoid raising errors in invalid through associations
|
71
|
-
def reflection_class_name
|
72
|
-
reflection.class_name.to_s rescue nil
|
73
|
-
end
|
74
|
-
|
68
|
+
end
|
69
|
+
|
70
|
+
# Rescue nil to avoid raising errors in invalid through associations
|
71
|
+
def reflection_class_name
|
72
|
+
reflection.class_name.to_s rescue nil
|
73
|
+
end
|
74
|
+
|
75
75
|
def reflection_foreign_key
|
76
76
|
reflection.primary_key_name.to_s
|
77
|
-
end
|
78
|
-
|
79
|
-
def reflection_join_table
|
80
|
-
(reflection.options[:join_table] || reflection.options[:through]).to_s
|
81
|
-
end
|
82
|
-
|
77
|
+
end
|
78
|
+
|
79
|
+
def reflection_join_table
|
80
|
+
(reflection.options[:join_table] || reflection.options[:through]).to_s
|
81
|
+
end
|
82
|
+
|
83
83
|
def has_join_table?
|
84
84
|
reflection.options.key?(:through) || reflection.macro == :has_and_belongs_to_many
|
85
|
-
end
|
86
|
-
|
87
|
-
def table_has_column?(table_name, column)
|
85
|
+
end
|
86
|
+
|
87
|
+
def table_has_column?(table_name, column)
|
88
88
|
::ActiveRecord::Base.connection.columns(table_name, 'Remarkable column retrieval').any?{|c| c.name == column }
|
89
|
-
end
|
90
|
-
|
91
|
-
# In cases a join table exists (has_and_belongs_to_many and through
|
92
|
-
# associations), we check the foreign key in the join table.
|
93
|
-
#
|
94
|
-
# On belongs to, the foreign_key is in the subject class table and in
|
95
|
-
# other cases it's on the reflection class table.
|
96
|
-
#
|
97
|
-
def foreign_key_table
|
98
|
-
if has_join_table?
|
99
|
-
reflection_join_table
|
100
|
-
elsif reflection.macro == :belongs_to
|
101
|
-
subject_class.table_name
|
102
|
-
else
|
103
|
-
reflection.klass.table_name
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
def interpolation_options
|
108
|
-
options = { :macro => Remarkable.t(@macro, :scope => matcher_i18n_scope, :default => @macro.to_s) }
|
109
|
-
|
110
|
-
if @subject && reflection
|
111
|
-
options.merge!(
|
112
|
-
:actual_macro => Remarkable.t(reflection.macro, :scope => matcher_i18n_scope, :default => reflection.macro.to_s),
|
113
|
-
:subject_table => subject_class.table_name.inspect,
|
114
|
-
:reflection_table => reflection.klass.table_name.inspect,
|
115
|
-
:foreign_key_table => foreign_key_table.inspect,
|
116
|
-
:polymorphic_column => reflection_foreign_key.sub(/_id$/, '_type').inspect,
|
117
|
-
:counter_cache_column => reflection.counter_cache_column.to_s.inspect
|
118
|
-
) rescue nil # rescue to allow specs to run properly
|
119
|
-
|
120
|
-
ASSOCIATION_OPTIONS.each do |option|
|
121
|
-
value_to_compare = respond_to?(:"reflection_#{option}", true) ? send(:"reflection_#{option}") : reflection.options[option].to_s
|
122
|
-
options[:"actual_#{option}"] = value_to_compare.inspect
|
123
|
-
end
|
124
|
-
|
125
|
-
end
|
126
|
-
|
127
|
-
options
|
89
|
+
end
|
90
|
+
|
91
|
+
# In cases a join table exists (has_and_belongs_to_many and through
|
92
|
+
# associations), we check the foreign key in the join table.
|
93
|
+
#
|
94
|
+
# On belongs to, the foreign_key is in the subject class table and in
|
95
|
+
# other cases it's on the reflection class table.
|
96
|
+
#
|
97
|
+
def foreign_key_table
|
98
|
+
if has_join_table?
|
99
|
+
reflection_join_table
|
100
|
+
elsif reflection.macro == :belongs_to
|
101
|
+
subject_class.table_name
|
102
|
+
else
|
103
|
+
reflection.klass.table_name
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def interpolation_options
|
108
|
+
options = { :macro => Remarkable.t(@macro, :scope => matcher_i18n_scope, :default => @macro.to_s) }
|
109
|
+
|
110
|
+
if @subject && reflection
|
111
|
+
options.merge!(
|
112
|
+
:actual_macro => Remarkable.t(reflection.macro, :scope => matcher_i18n_scope, :default => reflection.macro.to_s),
|
113
|
+
:subject_table => subject_class.table_name.inspect,
|
114
|
+
:reflection_table => reflection.klass.table_name.inspect,
|
115
|
+
:foreign_key_table => foreign_key_table.inspect,
|
116
|
+
:polymorphic_column => reflection_foreign_key.sub(/_id$/, '_type').inspect,
|
117
|
+
:counter_cache_column => reflection.counter_cache_column.to_s.inspect
|
118
|
+
) rescue nil # rescue to allow specs to run properly
|
119
|
+
|
120
|
+
ASSOCIATION_OPTIONS.each do |option|
|
121
|
+
value_to_compare = respond_to?(:"reflection_#{option}", true) ? send(:"reflection_#{option}") : reflection.options[option].to_s
|
122
|
+
options[:"actual_#{option}"] = value_to_compare.inspect
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
options
|
128
128
|
end
|
129
129
|
end
|
130
|
-
|
131
|
-
# Ensure that the belongs_to relationship exists. Will also test that the
|
132
|
-
# subject table has the association_id column.
|
133
|
-
#
|
134
|
-
# == Options
|
135
|
-
#
|
136
|
-
# * <tt>:class_name</tt> - the expected associted class name.
|
137
|
-
# * <tt>:foreign_key</tt> - the expected foreign key in the subject table.
|
138
|
-
# * <tt>:dependent</tt> - the expected dependent value for the association.
|
139
|
-
# * <tt>:readonly</tt> - checks wether readonly is true or false.
|
140
|
-
# * <tt>:validate</tt> - checks wether validate is true or false.
|
141
|
-
# * <tt>:autosave</tt> - checks wether autosave is true or false.
|
142
|
-
# * <tt>:counter_cache</tt> - the expected dependent value for the association.
|
143
|
-
# It also checks if the column actually exists in the table.
|
144
|
-
# * <tt>:polymorphic</tt> - if the association should be polymorphic or not.
|
145
|
-
# When true it also checks for the association_type column in the subject table.
|
146
|
-
#
|
147
|
-
# == Examples
|
148
|
-
#
|
149
|
-
# should_belong_to :parent, :polymorphic => true
|
150
|
-
# it { should belong_to(:parent) }
|
151
|
-
#
|
130
|
+
|
131
|
+
# Ensure that the belongs_to relationship exists. Will also test that the
|
132
|
+
# subject table has the association_id column.
|
133
|
+
#
|
134
|
+
# == Options
|
135
|
+
#
|
136
|
+
# * <tt>:class_name</tt> - the expected associted class name.
|
137
|
+
# * <tt>:foreign_key</tt> - the expected foreign key in the subject table.
|
138
|
+
# * <tt>:dependent</tt> - the expected dependent value for the association.
|
139
|
+
# * <tt>:readonly</tt> - checks wether readonly is true or false.
|
140
|
+
# * <tt>:validate</tt> - checks wether validate is true or false.
|
141
|
+
# * <tt>:autosave</tt> - checks wether autosave is true or false.
|
142
|
+
# * <tt>:counter_cache</tt> - the expected dependent value for the association.
|
143
|
+
# It also checks if the column actually exists in the table.
|
144
|
+
# * <tt>:polymorphic</tt> - if the association should be polymorphic or not.
|
145
|
+
# When true it also checks for the association_type column in the subject table.
|
146
|
+
#
|
147
|
+
# == Examples
|
148
|
+
#
|
149
|
+
# should_belong_to :parent, :polymorphic => true
|
150
|
+
# it { should belong_to(:parent) }
|
151
|
+
#
|
152
152
|
def belong_to(*associations)
|
153
153
|
AssociationMatcher.new(:belongs_to, *associations).spec(self)
|
154
154
|
end
|
155
|
-
|
156
|
-
# Ensures that the has_and_belongs_to_many relationship exists, if the join
|
157
|
-
# table is in place and if the foreign_key column exists.
|
158
|
-
#
|
159
|
-
# == Options
|
160
|
-
#
|
161
|
-
# * <tt>:class_name</tt> - the expected associted class name.
|
162
|
-
# * <tt>:join_table</tt> - the expected join table name.
|
163
|
-
# * <tt>:foreign_key</tt> - the expected foreign key in the association table.
|
164
|
-
# * <tt>:uniq</tt> - checks wether uniq is true or false.
|
165
|
-
# * <tt>:readonly</tt> - checks wether readonly is true or false.
|
166
|
-
# * <tt>:validate</tt> - checks wether validate is true or false.
|
167
|
-
# * <tt>:autosave</tt> - checks wether autosave is true or false.
|
168
|
-
#
|
169
|
-
# == Examples
|
170
|
-
#
|
171
|
-
# should_have_and_belong_to_many :posts, :cars
|
172
|
-
# it{ should have_and_belong_to_many :posts, :cars }
|
155
|
+
|
156
|
+
# Ensures that the has_and_belongs_to_many relationship exists, if the join
|
157
|
+
# table is in place and if the foreign_key column exists.
|
158
|
+
#
|
159
|
+
# == Options
|
160
|
+
#
|
161
|
+
# * <tt>:class_name</tt> - the expected associted class name.
|
162
|
+
# * <tt>:join_table</tt> - the expected join table name.
|
163
|
+
# * <tt>:foreign_key</tt> - the expected foreign key in the association table.
|
164
|
+
# * <tt>:uniq</tt> - checks wether uniq is true or false.
|
165
|
+
# * <tt>:readonly</tt> - checks wether readonly is true or false.
|
166
|
+
# * <tt>:validate</tt> - checks wether validate is true or false.
|
167
|
+
# * <tt>:autosave</tt> - checks wether autosave is true or false.
|
168
|
+
#
|
169
|
+
# == Examples
|
170
|
+
#
|
171
|
+
# should_have_and_belong_to_many :posts, :cars
|
172
|
+
# it{ should have_and_belong_to_many :posts, :cars }
|
173
173
|
#
|
174
174
|
def have_and_belong_to_many(*associations)
|
175
175
|
AssociationMatcher.new(:has_and_belongs_to_many, *associations).spec(self)
|
176
|
-
end
|
177
|
-
|
178
|
-
# Ensures that the has_many relationship exists. Will also test that the
|
179
|
-
# associated table has the required columns. It works by default with
|
180
|
-
# polymorphic association (:as does not have to be supplied).
|
181
|
-
#
|
182
|
-
# == Options
|
183
|
-
#
|
184
|
-
# * <tt>:class_name</tt> - the expected associted class name.
|
185
|
-
# * <tt>:through</tt> - the expected join model which to perform the query.
|
186
|
-
# It also checks if the through table exists.
|
187
|
-
# * <tt>:foreign_key</tt> - the expected foreign key in the associated table.
|
188
|
-
# When used with :through, it will check for the foreign key in the join table.
|
189
|
-
# * <tt>:dependent</tt> - the expected dependent value for the association.
|
190
|
-
# * <tt>:uniq</tt> - checks wether uniq is true or false.
|
191
|
-
# * <tt>:readonly</tt> - checks wether readonly is true or false.
|
192
|
-
# * <tt>:validate</tt> - checks wether validate is true or false.
|
193
|
-
# * <tt>:autosave</tt> - checks wether autosave is true or false.
|
194
|
-
#
|
195
|
-
# == Examples
|
196
|
-
#
|
197
|
-
# should_have_many :friends
|
198
|
-
# should_have_many :enemies, :through => :friends
|
199
|
-
# should_have_many :enemies, :dependent => :destroy
|
200
|
-
#
|
201
|
-
# it{ should have_many(:friends) }
|
202
|
-
# it{ should have_many(:enemies, :through => :friends) }
|
203
|
-
# it{ should have_many(:enemies, :dependent => :destroy) }
|
176
|
+
end
|
177
|
+
|
178
|
+
# Ensures that the has_many relationship exists. Will also test that the
|
179
|
+
# associated table has the required columns. It works by default with
|
180
|
+
# polymorphic association (:as does not have to be supplied).
|
181
|
+
#
|
182
|
+
# == Options
|
183
|
+
#
|
184
|
+
# * <tt>:class_name</tt> - the expected associted class name.
|
185
|
+
# * <tt>:through</tt> - the expected join model which to perform the query.
|
186
|
+
# It also checks if the through table exists.
|
187
|
+
# * <tt>:foreign_key</tt> - the expected foreign key in the associated table.
|
188
|
+
# When used with :through, it will check for the foreign key in the join table.
|
189
|
+
# * <tt>:dependent</tt> - the expected dependent value for the association.
|
190
|
+
# * <tt>:uniq</tt> - checks wether uniq is true or false.
|
191
|
+
# * <tt>:readonly</tt> - checks wether readonly is true or false.
|
192
|
+
# * <tt>:validate</tt> - checks wether validate is true or false.
|
193
|
+
# * <tt>:autosave</tt> - checks wether autosave is true or false.
|
194
|
+
#
|
195
|
+
# == Examples
|
196
|
+
#
|
197
|
+
# should_have_many :friends
|
198
|
+
# should_have_many :enemies, :through => :friends
|
199
|
+
# should_have_many :enemies, :dependent => :destroy
|
200
|
+
#
|
201
|
+
# it{ should have_many(:friends) }
|
202
|
+
# it{ should have_many(:enemies, :through => :friends) }
|
203
|
+
# it{ should have_many(:enemies, :dependent => :destroy) }
|
204
204
|
#
|
205
205
|
def have_many(*associations)
|
206
206
|
AssociationMatcher.new(:has_many, *associations).spec(self)
|
207
207
|
end
|
208
|
-
|
209
|
-
# Ensures that the has_many relationship exists. Will also test that the
|
210
|
-
# associated table has the required columns. It works by default with
|
211
|
-
# polymorphic association (:as does not have to be supplied).
|
212
|
-
#
|
213
|
-
# == Options
|
214
|
-
#
|
215
|
-
# * <tt>:class_name</tt> - the expected associted class name.
|
216
|
-
# * <tt>:through</tt> - the expected join model which to perform the query.
|
217
|
-
# It also checks if the through table exists.
|
218
|
-
# * <tt>:foreign_key</tt> - the expected foreign key in the associated table.
|
219
|
-
# When used with :through, it will check for the foreign key in the join table.
|
220
|
-
# * <tt>:dependent</tt> - the expected dependent value for the association.
|
221
|
-
# * <tt>:validate</tt> - checks wether validate is true or false.
|
222
|
-
# * <tt>:autosave</tt> - checks wether autosave is true or false.
|
223
|
-
#
|
224
|
-
# == Examples
|
225
|
-
#
|
226
|
-
# should_have_one :universe
|
227
|
-
# it{ should have_one(:universe) }
|
208
|
+
|
209
|
+
# Ensures that the has_many relationship exists. Will also test that the
|
210
|
+
# associated table has the required columns. It works by default with
|
211
|
+
# polymorphic association (:as does not have to be supplied).
|
212
|
+
#
|
213
|
+
# == Options
|
214
|
+
#
|
215
|
+
# * <tt>:class_name</tt> - the expected associted class name.
|
216
|
+
# * <tt>:through</tt> - the expected join model which to perform the query.
|
217
|
+
# It also checks if the through table exists.
|
218
|
+
# * <tt>:foreign_key</tt> - the expected foreign key in the associated table.
|
219
|
+
# When used with :through, it will check for the foreign key in the join table.
|
220
|
+
# * <tt>:dependent</tt> - the expected dependent value for the association.
|
221
|
+
# * <tt>:validate</tt> - checks wether validate is true or false.
|
222
|
+
# * <tt>:autosave</tt> - checks wether autosave is true or false.
|
223
|
+
#
|
224
|
+
# == Examples
|
225
|
+
#
|
226
|
+
# should_have_one :universe
|
227
|
+
# it{ should have_one(:universe) }
|
228
228
|
#
|
229
229
|
def have_one(*associations)
|
230
230
|
AssociationMatcher.new(:has_one, *associations).spec(self)
|