shoulda-matchers 1.4.2 → 1.5.0
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/.travis.yml +11 -3
- data/Appraisals +3 -3
- data/Gemfile +1 -1
- data/Gemfile.lock +69 -70
- data/MIT-LICENSE +1 -1
- data/NEWS.md +22 -4
- data/README.md +3 -1
- data/Rakefile +9 -5
- data/features/step_definitions/rails_steps.rb +7 -7
- data/features/support/env.rb +1 -1
- data/gemfiles/3.0.gemfile +1 -1
- data/gemfiles/3.0.gemfile.lock +25 -22
- data/gemfiles/3.1.gemfile +1 -1
- data/gemfiles/3.1.gemfile.lock +27 -24
- data/gemfiles/3.2.gemfile +1 -1
- data/gemfiles/3.2.gemfile.lock +56 -52
- data/lib/shoulda/matchers/action_controller.rb +3 -2
- data/lib/shoulda/matchers/action_controller/assign_to_matcher.rb +10 -8
- data/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +2 -4
- data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +3 -4
- data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +3 -4
- data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +6 -6
- data/lib/shoulda/matchers/action_controller/respond_with_content_type_matcher.rb +5 -2
- data/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +2 -2
- data/lib/shoulda/matchers/action_controller/route_matcher.rb +12 -12
- data/lib/shoulda/matchers/action_controller/set_session_matcher.rb +3 -4
- data/lib/shoulda/matchers/action_controller/set_the_flash_matcher.rb +10 -11
- data/lib/shoulda/matchers/action_controller/strong_parameters_matcher.rb +121 -0
- data/lib/shoulda/matchers/action_mailer/have_sent_email_matcher.rb +7 -4
- data/lib/shoulda/matchers/active_model.rb +1 -1
- data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +8 -8
- data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +5 -4
- data/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +3 -3
- data/lib/shoulda/matchers/active_model/ensure_inclusion_of_matcher.rb +2 -2
- data/lib/shoulda/matchers/active_model/exception_message_finder.rb +0 -1
- data/lib/shoulda/matchers/active_model/helpers.rb +16 -7
- data/lib/shoulda/matchers/active_model/only_integer_matcher.rb +3 -3
- data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +8 -6
- data/lib/shoulda/matchers/active_model/validate_format_of_matcher.rb +19 -10
- data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +4 -4
- data/lib/shoulda/matchers/active_model/validate_uniqueness_of_matcher.rb +19 -21
- data/lib/shoulda/matchers/active_model/validation_matcher.rb +7 -7
- data/lib/shoulda/matchers/active_model/validation_message_finder.rb +1 -1
- data/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +5 -5
- data/lib/shoulda/matchers/active_record/association_matcher.rb +3 -3
- data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +11 -7
- data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +2 -2
- data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +5 -5
- data/lib/shoulda/matchers/active_record/query_the_database_matcher.rb +5 -2
- data/lib/shoulda/matchers/active_record/serialize_matcher.rb +3 -3
- data/lib/shoulda/matchers/assertion_error.rb +4 -1
- data/lib/shoulda/matchers/independent/delegate_matcher.rb +17 -7
- data/lib/shoulda/matchers/integrations/rspec.rb +19 -33
- data/lib/shoulda/matchers/version.rb +1 -1
- data/shoulda-matchers.gemspec +6 -4
- data/spec/shoulda/matchers/action_controller/assign_to_matcher_spec.rb +66 -0
- data/spec/shoulda/matchers/action_controller/filter_param_matcher_spec.rb +22 -0
- data/spec/shoulda/matchers/action_controller/redirect_to_matcher_spec.rb +42 -0
- data/spec/shoulda/matchers/action_controller/render_template_matcher_spec.rb +78 -0
- data/spec/shoulda/matchers/action_controller/render_with_layout_matcher_spec.rb +58 -0
- data/spec/shoulda/matchers/action_controller/respond_with_content_type_matcher_spec.rb +31 -0
- data/spec/shoulda/matchers/action_controller/respond_with_matcher_spec.rb +31 -0
- data/spec/shoulda/matchers/action_controller/route_matcher_spec.rb +65 -0
- data/spec/shoulda/matchers/action_controller/set_session_matcher_spec.rb +51 -0
- data/spec/shoulda/matchers/action_controller/set_the_flash_matcher_spec.rb +153 -0
- data/spec/shoulda/matchers/action_controller/strong_parameters_matcher_spec.rb +142 -0
- data/spec/shoulda/matchers/action_mailer/have_sent_email_spec.rb +324 -0
- data/spec/shoulda/matchers/active_model/allow_mass_assignment_of_matcher_spec.rb +111 -0
- data/spec/shoulda/matchers/active_model/allow_value_matcher_spec.rb +124 -0
- data/spec/shoulda/matchers/active_model/disallow_value_matcher_spec.rb +43 -0
- data/spec/shoulda/matchers/active_model/ensure_exclusion_of_matcher_spec.rb +74 -0
- data/spec/shoulda/matchers/active_model/ensure_inclusion_of_matcher_spec.rb +171 -0
- data/spec/shoulda/matchers/active_model/ensure_length_of_matcher_spec.rb +113 -0
- data/spec/shoulda/{active_model → matchers/active_model}/exception_message_finder_spec.rb +2 -2
- data/spec/shoulda/matchers/active_model/helpers_spec.rb +158 -0
- data/spec/shoulda/matchers/active_model/only_integer_matcher_spec.rb +52 -0
- data/spec/shoulda/matchers/active_model/validate_acceptance_of_matcher_spec.rb +41 -0
- data/spec/shoulda/matchers/active_model/validate_confirmation_of_matcher_spec.rb +41 -0
- data/spec/shoulda/matchers/active_model/validate_format_of_matcher_spec.rb +75 -0
- data/spec/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +73 -0
- data/spec/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +127 -0
- data/spec/shoulda/matchers/active_model/validate_uniqueness_of_matcher_spec.rb +175 -0
- data/spec/shoulda/{active_model → matchers/active_model}/validation_message_finder_spec.rb +0 -1
- data/spec/shoulda/matchers/active_record/accept_nested_attributes_for_matcher_spec.rb +106 -0
- data/spec/shoulda/matchers/active_record/association_matcher_spec.rb +534 -0
- data/spec/shoulda/matchers/active_record/have_db_column_matcher_spec.rb +111 -0
- data/spec/shoulda/matchers/active_record/have_db_index_matcher_spec.rb +78 -0
- data/spec/shoulda/matchers/active_record/have_readonly_attributes_matcher_spec.rb +41 -0
- data/spec/shoulda/{active_record → matchers/active_record}/query_the_database_matcher_spec.rb +10 -10
- data/spec/shoulda/matchers/active_record/serialize_matcher_spec.rb +86 -0
- data/spec/shoulda/{independent → matchers/independent}/delegate_matcher_spec.rb +55 -34
- data/spec/spec_helper.rb +1 -2
- data/spec/support/active_model_versions.rb +4 -0
- data/spec/support/activemodel_helpers.rb +19 -0
- data/spec/support/controller_builder.rb +38 -12
- data/spec/support/model_builder.rb +8 -2
- metadata +106 -98
- data/spec/fixtures/addresses.yml +0 -3
- data/spec/fixtures/friendships.yml +0 -0
- data/spec/fixtures/posts.yml +0 -5
- data/spec/fixtures/products.yml +0 -0
- data/spec/fixtures/taggings.yml +0 -0
- data/spec/fixtures/tags.yml +0 -9
- data/spec/fixtures/users.yml +0 -6
- data/spec/shoulda/action_controller/assign_to_matcher_spec.rb +0 -63
- data/spec/shoulda/action_controller/filter_param_matcher_spec.rb +0 -20
- data/spec/shoulda/action_controller/redirect_to_matcher_spec.rb +0 -40
- data/spec/shoulda/action_controller/render_template_matcher_spec.rb +0 -69
- data/spec/shoulda/action_controller/render_with_layout_matcher_spec.rb +0 -55
- data/spec/shoulda/action_controller/respond_with_content_type_matcher_spec.rb +0 -28
- data/spec/shoulda/action_controller/respond_with_matcher_spec.rb +0 -83
- data/spec/shoulda/action_controller/route_matcher_spec.rb +0 -65
- data/spec/shoulda/action_controller/set_session_matcher_spec.rb +0 -46
- data/spec/shoulda/action_controller/set_the_flash_matcher_spec.rb +0 -130
- data/spec/shoulda/action_mailer/have_sent_email_spec.rb +0 -333
- data/spec/shoulda/active_model/allow_mass_assignment_of_matcher_spec.rb +0 -115
- data/spec/shoulda/active_model/allow_value_matcher_spec.rb +0 -131
- data/spec/shoulda/active_model/disallow_value_matcher_spec.rb +0 -65
- data/spec/shoulda/active_model/ensure_exclusion_of_matcher_spec.rb +0 -79
- data/spec/shoulda/active_model/ensure_inclusion_of_matcher_spec.rb +0 -181
- data/spec/shoulda/active_model/ensure_length_of_matcher_spec.rb +0 -138
- data/spec/shoulda/active_model/helpers_spec.rb +0 -129
- data/spec/shoulda/active_model/only_integer_matcher_spec.rb +0 -69
- data/spec/shoulda/active_model/validate_acceptance_of_matcher_spec.rb +0 -43
- data/spec/shoulda/active_model/validate_confirmation_of_matcher_spec.rb +0 -48
- data/spec/shoulda/active_model/validate_format_of_matcher_spec.rb +0 -79
- data/spec/shoulda/active_model/validate_numericality_of_matcher_spec.rb +0 -112
- data/spec/shoulda/active_model/validate_presence_of_matcher_spec.rb +0 -135
- data/spec/shoulda/active_model/validate_uniqueness_of_matcher_spec.rb +0 -154
- data/spec/shoulda/active_record/accept_nested_attributes_for_matcher_spec.rb +0 -84
- data/spec/shoulda/active_record/association_matcher_spec.rb +0 -642
- data/spec/shoulda/active_record/have_db_column_matcher_spec.rb +0 -185
- data/spec/shoulda/active_record/have_db_index_matcher_spec.rb +0 -105
- data/spec/shoulda/active_record/have_readonly_attributes_matcher_spec.rb +0 -46
- data/spec/shoulda/active_record/serialize_matcher_spec.rb +0 -81
@@ -0,0 +1,534 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
|
4
|
+
context 'belong_to' do
|
5
|
+
it 'accepts a good association with the default foreign key' do
|
6
|
+
belonging_to_parent.should belong_to(:parent)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'rejects a nonexistent association' do
|
10
|
+
define_model(:child).new.should_not belong_to(:parent)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'rejects an association of the wrong type' do
|
14
|
+
define_model :parent, :child_id => :integer
|
15
|
+
define_model(:child) { has_one :parent }.new.should_not belong_to(:parent)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'rejects an association that has a nonexistent foreign key' do
|
19
|
+
define_model :parent
|
20
|
+
define_model(:child) { belongs_to :parent }.new.should_not belong_to(:parent)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'accepts an association with an existing custom foreign key' do
|
24
|
+
define_model :parent
|
25
|
+
define_model :child, :guardian_id => :integer do
|
26
|
+
belongs_to :parent, :foreign_key => 'guardian_id'
|
27
|
+
end
|
28
|
+
|
29
|
+
Child.new.should belong_to(:parent)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'accepts a polymorphic association' do
|
33
|
+
define_model :child, :parent_type => :string, :parent_id => :integer do
|
34
|
+
belongs_to :parent, :polymorphic => true
|
35
|
+
end
|
36
|
+
|
37
|
+
Child.new.should belong_to(:parent)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'accepts an association with a valid :dependent option' do
|
41
|
+
belonging_to_parent(:dependent => :destroy).
|
42
|
+
should belong_to(:parent).dependent(:destroy)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'rejects an association with a bad :dependent option' do
|
46
|
+
belonging_to_parent.should_not belong_to(:parent).dependent(:destroy)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'accepts an association with a valid :conditions option' do
|
50
|
+
define_model :parent, :adopter => :boolean
|
51
|
+
define_model :child, :parent_id => :integer do
|
52
|
+
belongs_to :parent, :conditions => { :adopter => true }
|
53
|
+
end
|
54
|
+
|
55
|
+
Child.new.should belong_to(:parent).conditions(:adopter => true)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'rejects an association with a bad :conditions option' do
|
59
|
+
define_model :parent, :adopter => :boolean
|
60
|
+
define_model :child, :parent_id => :integer do
|
61
|
+
belongs_to :parent
|
62
|
+
end
|
63
|
+
|
64
|
+
Child.new.should_not belong_to(:parent).conditions(:adopter => true)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'accepts an association with a valid :class_name option' do
|
68
|
+
belonging_to_parent(:class_name => 'TreeParent').
|
69
|
+
should belong_to(:parent).class_name('TreeParent')
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'rejects an association with a bad :class_name option' do
|
73
|
+
belonging_to_parent(:class_name => 'TreeParent').
|
74
|
+
should_not belong_to(:parent).class_name('TreeChild')
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'validate' do
|
78
|
+
[false, true].each do |validate_value|
|
79
|
+
context 'when the model has :validate => #{validate_value}' do
|
80
|
+
it 'accepts a matching validate option' do
|
81
|
+
belonging_to_parent(:validate => validate_value).
|
82
|
+
should belong_to(:parent).validate(validate_value)
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'rejects a non-matching validate option' do
|
86
|
+
belonging_to_parent(:validate => validate_value).
|
87
|
+
should_not belong_to(:parent).validate(!validate_value)
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'defaults to validate(true)' do
|
91
|
+
if validate_value
|
92
|
+
belonging_to_parent(:validate => validate_value).
|
93
|
+
should belong_to(:parent).validate
|
94
|
+
else
|
95
|
+
belonging_to_parent(:validate => validate_value).
|
96
|
+
should_not belong_to(:parent).validate
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context 'an association without a :validate option' do
|
104
|
+
it 'accepts validate(false)' do
|
105
|
+
belonging_to_parent.should belong_to(:parent).validate(false)
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'rejects validate(true)' do
|
109
|
+
belonging_to_parent.should_not belong_to(:parent).validate(true)
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'rejects validate()' do
|
113
|
+
belonging_to_parent.should_not belong_to(:parent).validate
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def belonging_to_parent(options = {})
|
118
|
+
define_model :parent
|
119
|
+
define_model :child, :parent_id => :integer do
|
120
|
+
belongs_to :parent, options
|
121
|
+
end.new
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context 'have_many' do
|
126
|
+
it 'accepts a valid association without any options' do
|
127
|
+
having_many_children.should have_many(:children)
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'accepts a valid association with a :through option' do
|
131
|
+
define_model :child
|
132
|
+
define_model :conception, :child_id => :integer,
|
133
|
+
:parent_id => :integer do
|
134
|
+
belongs_to :child
|
135
|
+
end
|
136
|
+
define_model :parent do
|
137
|
+
has_many :conceptions
|
138
|
+
has_many :children, :through => :conceptions
|
139
|
+
end
|
140
|
+
Parent.new.should have_many(:children)
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'accepts a valid association with an :as option' do
|
144
|
+
define_model :child, :guardian_type => :string, :guardian_id => :integer
|
145
|
+
define_model :parent do
|
146
|
+
has_many :children, :as => :guardian
|
147
|
+
end
|
148
|
+
|
149
|
+
Parent.new.should have_many(:children)
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'rejects an association that has a nonexistent foreign key' do
|
153
|
+
define_model :child
|
154
|
+
define_model :parent do
|
155
|
+
has_many :children
|
156
|
+
end
|
157
|
+
|
158
|
+
Parent.new.should_not have_many(:children)
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'rejects an association with a bad :as option' do
|
162
|
+
define_model :child, :caretaker_type => :string,
|
163
|
+
:caretaker_id => :integer
|
164
|
+
define_model :parent do
|
165
|
+
has_many :children, :as => :guardian
|
166
|
+
end
|
167
|
+
|
168
|
+
Parent.new.should_not have_many(:children)
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'rejects an association that has a bad :through option' do
|
172
|
+
matcher = have_many(:children).through(:conceptions)
|
173
|
+
|
174
|
+
matcher.matches?(having_many_children).should be_false
|
175
|
+
|
176
|
+
matcher.failure_message_for_should.should =~ /does not have any relationship to conceptions/
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'rejects an association that has the wrong :through option' do
|
180
|
+
define_model :child
|
181
|
+
define_model :conception, :child_id => :integer,
|
182
|
+
:parent_id => :integer do
|
183
|
+
belongs_to :child
|
184
|
+
end
|
185
|
+
define_model :parent do
|
186
|
+
has_many :conceptions
|
187
|
+
has_many :relationships
|
188
|
+
has_many :children, :through => :conceptions
|
189
|
+
end
|
190
|
+
|
191
|
+
matcher = have_many(:children).through(:relationships)
|
192
|
+
matcher.matches?(Parent.new).should be_false
|
193
|
+
matcher.failure_message_for_should.should =~ /through relationships, but got it through conceptions/
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'accepts an association with a valid :dependent option' do
|
197
|
+
having_many_children(:dependent => :destroy).
|
198
|
+
should have_many(:children).dependent(:destroy)
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'rejects an association with a bad :dependent option' do
|
202
|
+
having_many_children.should_not have_many(:children).dependent(:destroy)
|
203
|
+
end
|
204
|
+
|
205
|
+
it 'accepts an association with a valid :order option' do
|
206
|
+
having_many_children(:order => :id).
|
207
|
+
should have_many(:children).order(:id)
|
208
|
+
end
|
209
|
+
|
210
|
+
it 'rejects an association with a bad :order option' do
|
211
|
+
having_many_children.should_not have_many(:children).order(:id)
|
212
|
+
end
|
213
|
+
|
214
|
+
it 'accepts an association with a valid :conditions option' do
|
215
|
+
define_model :child, :parent_id => :integer, :adopted => :boolean
|
216
|
+
define_model :parent do
|
217
|
+
has_many :children, :conditions => { :adopted => true }
|
218
|
+
end
|
219
|
+
|
220
|
+
Parent.new.should have_many(:children).conditions(:adopted => true)
|
221
|
+
end
|
222
|
+
|
223
|
+
it 'rejects an association with a bad :conditions option' do
|
224
|
+
define_model :child, :parent_id => :integer, :adopted => :boolean
|
225
|
+
define_model :parent do
|
226
|
+
has_many :children
|
227
|
+
end
|
228
|
+
|
229
|
+
Parent.new.should_not have_many(:children).conditions(:adopted => true)
|
230
|
+
end
|
231
|
+
|
232
|
+
it 'accepts an association with a valid :class_name option' do
|
233
|
+
define_model :node, :parent_id => :integer
|
234
|
+
define_model :parent do
|
235
|
+
has_many :children, :class_name => 'Node'
|
236
|
+
end
|
237
|
+
|
238
|
+
Parent.new.should have_many(:children).class_name('Node')
|
239
|
+
end
|
240
|
+
|
241
|
+
it 'rejects an association with a bad :class_name option' do
|
242
|
+
having_many_children.should_not have_many(:children).class_name('Node')
|
243
|
+
end
|
244
|
+
|
245
|
+
context 'validate' do
|
246
|
+
it 'accepts when the :validate option matches' do
|
247
|
+
having_many_children(:validate => false).should have_many(:children).validate(false)
|
248
|
+
end
|
249
|
+
|
250
|
+
it 'rejects when the :validate option does not match' do
|
251
|
+
having_many_children(:validate => true).should_not have_many(:children).validate(false)
|
252
|
+
end
|
253
|
+
|
254
|
+
it 'assumes validate() means validate(true)' do
|
255
|
+
having_many_children(:validate => false).should_not have_many(:children).validate
|
256
|
+
end
|
257
|
+
|
258
|
+
it 'matches validate(false) to having no validate option specified' do
|
259
|
+
having_many_children.should have_many(:children).validate(false)
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
it 'accepts an association with a nonstandard reverse foreign key, using :inverse_of' do
|
264
|
+
define_model :child, :ancestor_id => :integer do
|
265
|
+
belongs_to :ancestor, :inverse_of => :children, :class_name => :Parent
|
266
|
+
end
|
267
|
+
define_model :parent do
|
268
|
+
has_many :children, :inverse_of => :ancestor
|
269
|
+
end
|
270
|
+
|
271
|
+
Parent.new.should have_many(:children)
|
272
|
+
end
|
273
|
+
|
274
|
+
it 'rejects an association with a nonstandard reverse foreign key, if :inverse_of is not correct' do
|
275
|
+
define_model :child, :mother_id => :integer do
|
276
|
+
belongs_to :mother, :inverse_of => :children, :class_name => :Parent
|
277
|
+
end
|
278
|
+
define_model :parent do
|
279
|
+
has_many :children, :inverse_of => :ancestor
|
280
|
+
end
|
281
|
+
|
282
|
+
Parent.new.should_not have_many(:children)
|
283
|
+
end
|
284
|
+
|
285
|
+
def having_many_children(options = {})
|
286
|
+
define_model :child, :parent_id => :integer
|
287
|
+
define_model :parent do
|
288
|
+
has_many :children, options
|
289
|
+
end.new
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
context 'have_one' do
|
294
|
+
it 'accepts a valid association without any options' do
|
295
|
+
having_one_detail.should have_one(:detail)
|
296
|
+
end
|
297
|
+
|
298
|
+
it 'accepts a valid association with an :as option' do
|
299
|
+
define_model :detail, :detailable_id => :integer,
|
300
|
+
:detailable_type => :string
|
301
|
+
define_model :person do
|
302
|
+
has_one :detail, :as => :detailable
|
303
|
+
end
|
304
|
+
|
305
|
+
Person.new.should have_one(:detail)
|
306
|
+
end
|
307
|
+
|
308
|
+
it 'rejects an association that has a nonexistent foreign key' do
|
309
|
+
define_model :detail
|
310
|
+
define_model :person do
|
311
|
+
has_one :detail
|
312
|
+
end
|
313
|
+
|
314
|
+
Person.new.should_not have_one(:detail)
|
315
|
+
end
|
316
|
+
|
317
|
+
it 'accepts an association with an existing custom foreign key' do
|
318
|
+
define_model :detail, :detailed_person_id => :integer
|
319
|
+
define_model :person do
|
320
|
+
has_one :detail, :foreign_key => :detailed_person_id
|
321
|
+
end
|
322
|
+
Person.new.should have_one(:detail).with_foreign_key(:detailed_person_id)
|
323
|
+
end
|
324
|
+
|
325
|
+
it 'rejects an association with a bad :as option' do
|
326
|
+
define_model :detail, :detailable_id => :integer,
|
327
|
+
:detailable_type => :string
|
328
|
+
define_model :person do
|
329
|
+
has_one :detail, :as => :describable
|
330
|
+
end
|
331
|
+
|
332
|
+
Person.new.should_not have_one(:detail)
|
333
|
+
end
|
334
|
+
|
335
|
+
it 'accepts an association with a valid :dependent option' do
|
336
|
+
having_one_detail(:dependent => :destroy).
|
337
|
+
should have_one(:detail).dependent(:destroy)
|
338
|
+
end
|
339
|
+
|
340
|
+
it 'rejects an association with a bad :dependent option' do
|
341
|
+
having_one_detail.should_not have_one(:detail).dependent(:destroy)
|
342
|
+
end
|
343
|
+
|
344
|
+
it 'accepts an association with a valid :order option' do
|
345
|
+
having_one_detail(:order => :id).should have_one(:detail).order(:id)
|
346
|
+
end
|
347
|
+
|
348
|
+
it 'rejects an association with a bad :order option' do
|
349
|
+
having_one_detail.should_not have_one(:detail).order(:id)
|
350
|
+
end
|
351
|
+
|
352
|
+
it 'accepts an association with a valid :conditions option' do
|
353
|
+
define_model :detail, :person_id => :integer, :disabled => :boolean
|
354
|
+
define_model :person do
|
355
|
+
has_one :detail, :conditions => { :disabled => true}
|
356
|
+
end
|
357
|
+
|
358
|
+
Person.new.should have_one(:detail).conditions(:disabled => true)
|
359
|
+
end
|
360
|
+
|
361
|
+
it 'rejects an association with a bad :conditions option' do
|
362
|
+
define_model :detail, :person_id => :integer, :disabled => :boolean
|
363
|
+
define_model :person do
|
364
|
+
has_one :detail
|
365
|
+
end
|
366
|
+
|
367
|
+
Person.new.should_not have_one(:detail).conditions(:disabled => true)
|
368
|
+
end
|
369
|
+
|
370
|
+
it 'accepts an association with a valid :class_name option' do
|
371
|
+
define_model :person_detail, :person_id => :integer
|
372
|
+
define_model :person do
|
373
|
+
has_one :detail, :class_name => 'PersonDetail'
|
374
|
+
end
|
375
|
+
|
376
|
+
Person.new.should have_one(:detail).class_name('PersonDetail')
|
377
|
+
end
|
378
|
+
|
379
|
+
it 'rejects an association with a bad :class_name option' do
|
380
|
+
having_one_detail.should_not have_one(:detail).class_name('NotSet')
|
381
|
+
end
|
382
|
+
|
383
|
+
it 'accepts an association with a through' do
|
384
|
+
define_model :detail
|
385
|
+
|
386
|
+
define_model :account do
|
387
|
+
has_one :detail
|
388
|
+
end
|
389
|
+
|
390
|
+
define_model :person do
|
391
|
+
has_one :account
|
392
|
+
has_one :detail, :through => :account
|
393
|
+
end
|
394
|
+
|
395
|
+
Person.new.should have_one(:detail).through(:account)
|
396
|
+
end
|
397
|
+
|
398
|
+
it 'rejects an association with a bad through' do
|
399
|
+
having_one_detail.should_not have_one(:detail).through(:account)
|
400
|
+
end
|
401
|
+
|
402
|
+
context 'validate' do
|
403
|
+
it 'accepts when the :validate option matches' do
|
404
|
+
having_one_detail(:validate => false).
|
405
|
+
should have_one(:detail).validate(false)
|
406
|
+
end
|
407
|
+
|
408
|
+
it 'rejects when the :validate option does not match' do
|
409
|
+
having_one_detail(:validate => true).
|
410
|
+
should_not have_one(:detail).validate(false)
|
411
|
+
end
|
412
|
+
|
413
|
+
it 'assumes validate() means validate(true)' do
|
414
|
+
having_one_detail(:validate => false).
|
415
|
+
should_not have_one(:detail).validate
|
416
|
+
end
|
417
|
+
|
418
|
+
it 'matches validate(false) to having no validate option specified' do
|
419
|
+
having_one_detail.should have_one(:detail).validate(false)
|
420
|
+
end
|
421
|
+
end
|
422
|
+
|
423
|
+
def having_one_detail(options = {})
|
424
|
+
define_model :detail, :person_id => :integer
|
425
|
+
define_model :person do
|
426
|
+
has_one :detail, options
|
427
|
+
end.new
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
context 'have_and_belong_to_many' do
|
432
|
+
it 'accepts a valid association' do
|
433
|
+
having_and_belonging_to_many_relatives.
|
434
|
+
should have_and_belong_to_many(:relatives)
|
435
|
+
end
|
436
|
+
|
437
|
+
it 'rejects a nonexistent association' do
|
438
|
+
define_model :relatives
|
439
|
+
define_model :person
|
440
|
+
define_model :people_relative, :id => false, :person_id => :integer,
|
441
|
+
:relative_id => :integer
|
442
|
+
|
443
|
+
Person.new.should_not have_and_belong_to_many(:relatives)
|
444
|
+
end
|
445
|
+
|
446
|
+
it 'rejects an association with a nonexistent join table' do
|
447
|
+
define_model :relatives
|
448
|
+
define_model :person do
|
449
|
+
has_and_belongs_to_many :relatives
|
450
|
+
end
|
451
|
+
|
452
|
+
Person.new.should_not have_and_belong_to_many(:relatives)
|
453
|
+
end
|
454
|
+
|
455
|
+
it 'rejects an association of the wrong type' do
|
456
|
+
define_model :relatives, :person_id => :integer
|
457
|
+
define_model :person do
|
458
|
+
has_many :relatives
|
459
|
+
end
|
460
|
+
|
461
|
+
Person.new.should_not have_and_belong_to_many(:relatives)
|
462
|
+
end
|
463
|
+
|
464
|
+
it 'accepts an association with a valid :conditions option' do
|
465
|
+
define_model :relatives, :adopted => :boolean
|
466
|
+
define_model :person do
|
467
|
+
has_and_belongs_to_many :relatives, :conditions => { :adopted => true }
|
468
|
+
end
|
469
|
+
define_model :people_relative, :id => false, :person_id => :integer,
|
470
|
+
:relative_id => :integer
|
471
|
+
|
472
|
+
Person.new.should have_and_belong_to_many(:relatives).conditions(:adopted => true)
|
473
|
+
end
|
474
|
+
|
475
|
+
it 'rejects an association with a bad :conditions option' do
|
476
|
+
define_model :relatives, :adopted => :boolean
|
477
|
+
define_model :person do
|
478
|
+
has_and_belongs_to_many :relatives
|
479
|
+
end
|
480
|
+
define_model :people_relative, :id => false, :person_id => :integer,
|
481
|
+
:relative_id => :integer
|
482
|
+
|
483
|
+
Person.new.should_not have_and_belong_to_many(:relatives).conditions(:adopted => true)
|
484
|
+
end
|
485
|
+
|
486
|
+
it 'accepts an association with a valid :class_name option' do
|
487
|
+
define_model :person_relatives, :adopted => :boolean
|
488
|
+
define_model :person do
|
489
|
+
has_and_belongs_to_many :relatives, :class_name => 'PersonRelatives'
|
490
|
+
end
|
491
|
+
|
492
|
+
define_model :people_person_relative, :person_id => :integer,
|
493
|
+
:person_relative_id => :integer
|
494
|
+
|
495
|
+
Person.new.should have_and_belong_to_many(:relatives).class_name('PersonRelatives')
|
496
|
+
end
|
497
|
+
|
498
|
+
it 'rejects an association with a bad :class_name option' do
|
499
|
+
having_and_belonging_to_many_relatives.
|
500
|
+
should_not have_and_belong_to_many(:relatives).class_name('PersonRelatives')
|
501
|
+
end
|
502
|
+
|
503
|
+
context 'validate' do
|
504
|
+
it 'accepts when the :validate option matches' do
|
505
|
+
having_and_belonging_to_many_relatives(:validate => false).
|
506
|
+
should have_and_belong_to_many(:relatives).validate(false)
|
507
|
+
end
|
508
|
+
|
509
|
+
it 'rejects when the :validate option does not match' do
|
510
|
+
having_and_belonging_to_many_relatives(:validate => true).
|
511
|
+
should have_and_belong_to_many(:relatives).validate(false)
|
512
|
+
end
|
513
|
+
|
514
|
+
it 'assumes validate() means validate(true)' do
|
515
|
+
having_and_belonging_to_many_relatives(:validate => false).
|
516
|
+
should_not have_and_belong_to_many(:relatives).validate
|
517
|
+
end
|
518
|
+
|
519
|
+
it 'matches validate(false) to having no validate option specified' do
|
520
|
+
having_and_belonging_to_many_relatives.
|
521
|
+
should have_and_belong_to_many(:relatives).validate(false)
|
522
|
+
end
|
523
|
+
end
|
524
|
+
|
525
|
+
def having_and_belonging_to_many_relatives(options = {})
|
526
|
+
define_model :relatives
|
527
|
+
define_model :people_relative, :id => false, :person_id => :integer,
|
528
|
+
:relative_id => :integer
|
529
|
+
define_model :person do
|
530
|
+
has_and_belongs_to_many :relatives
|
531
|
+
end.new
|
532
|
+
end
|
533
|
+
end
|
534
|
+
end
|