friendly-attributes 0.7.1.1 → 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +45 -0
- data/.ruby-version +1 -0
- data/.travis.yml +6 -0
- data/.yardopts +1 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +45 -0
- data/README.md +3 -0
- data/Rakefile +25 -0
- data/VERSION +1 -0
- data/friendly-attributes.gemspec +30 -0
- data/spec/config.sample.yml +6 -0
- data/spec/friendly_attributes/base_spec.rb +122 -0
- data/spec/friendly_attributes/class_methods_spec.rb +124 -0
- data/spec/friendly_attributes/configuration_spec.rb +99 -0
- data/spec/friendly_attributes/details_delegator_spec.rb +210 -0
- data/spec/friendly_attributes/instance_methods_spec.rb +240 -0
- data/spec/friendly_attributes_spec.rb +152 -0
- data/spec/spec_helper.rb +81 -0
- data/spec/support/active_record_fake.rb +18 -0
- data/spec/support/database_cleaner_helpers.rb +11 -0
- data/spec/support/friendly_fake.rb +15 -0
- metadata +129 -376
@@ -0,0 +1,210 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe FriendlyAttributes::DetailsDelegator do
|
4
|
+
DetailsDelegator = FriendlyAttributes::DetailsDelegator
|
5
|
+
|
6
|
+
let(:details_delegator) { FriendlyAttributes::DetailsDelegator.new(friendly_model, ar_model, attributes, options, &initializer) }
|
7
|
+
let(:initializer) { proc {} }
|
8
|
+
let(:attributes) { {} }
|
9
|
+
let(:options) { {} }
|
10
|
+
|
11
|
+
let(:friendly_model) { mock_friendly_model }
|
12
|
+
let(:ar_model) { Class.new { include ActiveRecordFake } }
|
13
|
+
|
14
|
+
let(:ar_instance) { ar_model.new(:id => 42) }
|
15
|
+
let(:friendly_instance) { mock(friendly_model) }
|
16
|
+
|
17
|
+
describe "class methods" do
|
18
|
+
describe ".friendly_model_name" do
|
19
|
+
it { DetailsDelegator.friendly_model_name(UserDetails).should == :user_details }
|
20
|
+
end
|
21
|
+
|
22
|
+
describe ".friendly_model_ivar" do
|
23
|
+
it { DetailsDelegator.friendly_model_ivar(:user_details).should == :@user_details_ivar }
|
24
|
+
end
|
25
|
+
|
26
|
+
describe ".friendly_model_reader" do
|
27
|
+
it { DetailsDelegator.friendly_model_reader(:user_details).should == :load_user_details }
|
28
|
+
it { DetailsDelegator.friendly_model_reader(UserDetails).should == :load_user_details }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "initialization" do
|
33
|
+
shared_examples_for "DetailsDelegator initialization" do
|
34
|
+
context "DetailsDelegator attr_readers" do
|
35
|
+
subject { details_delegator }
|
36
|
+
|
37
|
+
before(:each) do
|
38
|
+
details_delegator
|
39
|
+
end
|
40
|
+
|
41
|
+
its(:active_record_model) { should == ar_model }
|
42
|
+
its(:friendly_model) { should == friendly_model }
|
43
|
+
its(:attributes) { should == attributes }
|
44
|
+
end
|
45
|
+
|
46
|
+
context "#setup_delegated_attributes" do
|
47
|
+
let(:attributes) do
|
48
|
+
{
|
49
|
+
String => :foo,
|
50
|
+
Integer => [:bar, :baz]
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
it "delegates the attributes passed in the options" do
|
55
|
+
details_delegator.should_receive(:delegated_attribute).with(:foo, String)
|
56
|
+
details_delegator.should_receive(:delegated_attribute).with(:bar, Integer)
|
57
|
+
details_delegator.should_receive(:delegated_attribute).with(:baz, Integer)
|
58
|
+
details_delegator.setup_delegated_attributes
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "the Friendly model" do
|
63
|
+
before(:each) do
|
64
|
+
details_delegator
|
65
|
+
end
|
66
|
+
|
67
|
+
it "includes Friendly::Document" do
|
68
|
+
friendly_model.ancestors.should include(Friendly::Document)
|
69
|
+
end
|
70
|
+
|
71
|
+
context "with defaults" do
|
72
|
+
it "adds the active_record_id attribute" do
|
73
|
+
friendly_model.attributes.should include(:active_record_id)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "adds an index to active_record_id" do
|
77
|
+
friendly_model.storage_proxy.index_for_fields([:active_record_id]).should be_an_instance_of(Friendly::Index)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "sets the active_record_key" do
|
81
|
+
friendly_model.active_record_key.should == :active_record_id
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "with options" do
|
86
|
+
let(:options) { { :active_record_key => :user_id } }
|
87
|
+
|
88
|
+
it "adds the active_record_id attribute" do
|
89
|
+
friendly_model.attributes.should include(:user_id)
|
90
|
+
end
|
91
|
+
|
92
|
+
it "adds an index to active_record_id" do
|
93
|
+
friendly_model.storage_proxy.index_for_fields([:user_id]).should be_an_instance_of(Friendly::Index)
|
94
|
+
end
|
95
|
+
|
96
|
+
it "sets the active_record_key" do
|
97
|
+
friendly_model.active_record_key.should == :user_id
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context "the ActiveRecord model" do
|
103
|
+
it "installs the update_friendly_models callback after_save" do
|
104
|
+
ar_model.should_receive(:after_save).with(:update_friendly_models)
|
105
|
+
details_delegator
|
106
|
+
end
|
107
|
+
|
108
|
+
it "installs the destroy_friendly_models callback after_destroy" do
|
109
|
+
ar_model.should_receive(:after_destroy).with(:destroy_friendly_models)
|
110
|
+
details_delegator
|
111
|
+
end
|
112
|
+
|
113
|
+
describe "friendly model reader method" do
|
114
|
+
before(:each) do
|
115
|
+
details_delegator
|
116
|
+
end
|
117
|
+
|
118
|
+
it "is defined" do
|
119
|
+
ar_instance.should respond_to(DetailsDelegator.friendly_model_reader(friendly_model))
|
120
|
+
end
|
121
|
+
|
122
|
+
it "finds or builds and memoizes the associated Friendly model" do
|
123
|
+
ar_instance.should_receive(:find_or_build_and_memoize_details).with(friendly_model)
|
124
|
+
ar_instance.send(DetailsDelegator.friendly_model_reader(friendly_model))
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe "cattr_accessor friendly_attributes_configuration" do
|
129
|
+
context "when no Configuration exists" do
|
130
|
+
it "creates and assigns a new Configuration with the delegator added" do
|
131
|
+
details_delegator
|
132
|
+
|
133
|
+
ar_model.friendly_attributes_configuration.should be_an_instance_of(FriendlyAttributes::Configuration)
|
134
|
+
ar_model.friendly_attributes_configuration.friendly_models.should == [friendly_model]
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
context "when Configuration already exists" do
|
139
|
+
let(:existing_details_delegator) { FriendlyAttributes::DetailsDelegator.new(other_friendly_model, ar_model, attributes, options, &initializer) }
|
140
|
+
let(:other_friendly_model) { mock_friendly_model }
|
141
|
+
|
142
|
+
before(:each) do
|
143
|
+
existing_details_delegator
|
144
|
+
end
|
145
|
+
|
146
|
+
it "adds to the existing configuration" do
|
147
|
+
existing_configuration = ar_model.friendly_attributes_configuration
|
148
|
+
|
149
|
+
expect do
|
150
|
+
details_delegator
|
151
|
+
end.to change { ar_model.friendly_attributes_configuration.friendly_models }.
|
152
|
+
from([other_friendly_model]).
|
153
|
+
to([other_friendly_model, friendly_model])
|
154
|
+
|
155
|
+
ar_model.friendly_attributes_configuration.should == existing_configuration
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
context "missing initialization block" do
|
163
|
+
let(:details_delegator) { FriendlyAttributes::DetailsDelegator.new(friendly_model, ar_model, attributes, options) }
|
164
|
+
it_should_behave_like "DetailsDelegator initialization"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
describe "#delegated_method" do
|
169
|
+
before(:each) do
|
170
|
+
details_delegator
|
171
|
+
details_delegator.delegated_method(:some_method)
|
172
|
+
ar_instance.stub(DetailsDelegator.friendly_model_reader(friendly_model) => friendly_instance)
|
173
|
+
end
|
174
|
+
|
175
|
+
it "delegates the method to Friendly model" do
|
176
|
+
bar = mock
|
177
|
+
friendly_instance.should_receive(:some_method).with(:foo).and_return(bar)
|
178
|
+
ar_instance.some_method(:foo).should == bar
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
describe "#delegated_attribute" do
|
183
|
+
before(:each) do
|
184
|
+
details_delegator
|
185
|
+
details_delegator.delegated_attribute(:some_attribute, String)
|
186
|
+
ar_instance.stub(DetailsDelegator.friendly_model_reader(friendly_model) => friendly_instance)
|
187
|
+
end
|
188
|
+
|
189
|
+
it "adds an attribute to the Friendly model" do
|
190
|
+
friendly_model.attributes.should include(:some_attribute)
|
191
|
+
friendly_model.attributes[:some_attribute].type.should == String
|
192
|
+
end
|
193
|
+
|
194
|
+
it "delegates the reader to Friendly model" do
|
195
|
+
bar = mock
|
196
|
+
friendly_instance.should_receive(:some_attribute).and_return(bar)
|
197
|
+
ar_instance.some_attribute.should == bar
|
198
|
+
end
|
199
|
+
|
200
|
+
it "delegates the writer to Friendly model" do
|
201
|
+
bar = mock
|
202
|
+
friendly_instance.should_receive(:some_attribute=).with(:value)
|
203
|
+
ar_instance.some_attribute = :value
|
204
|
+
end
|
205
|
+
|
206
|
+
it "adds the attribute to the configuration" do
|
207
|
+
ar_instance.friendly_attributes_configuration.attributes.should == { :some_attribute => friendly_model }
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
@@ -0,0 +1,240 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe FriendlyAttributes::InstanceMethods do
|
4
|
+
DetailsDelegator = FriendlyAttributes::DetailsDelegator unless defined?(DetailsDelegator)
|
5
|
+
|
6
|
+
let(:object) { klass.new.tap { |o| o.stub(:friendly_attributes_configuration => configuration) } }
|
7
|
+
let(:configuration) { mock(FriendlyAttributes::Configuration) }
|
8
|
+
let(:klass) {
|
9
|
+
Class.new {
|
10
|
+
include ActiveRecordFake
|
11
|
+
include FriendlyAttributes::InstanceMethods
|
12
|
+
}
|
13
|
+
}
|
14
|
+
let(:user_details) { double(UserDetails).as_null_object }
|
15
|
+
let(:user_second_details) { double(UserSecondDetails).as_null_object }
|
16
|
+
let(:friendly_model_instances) { [user_details, user_second_details] }
|
17
|
+
|
18
|
+
describe "reading and writing Friendly attributes" do
|
19
|
+
let(:object_details) { double(FriendlyAttributes::Base, :foo => foo, :foo= => foo) }
|
20
|
+
let(:foo) { mock("object_details.foo") }
|
21
|
+
|
22
|
+
before(:each) do
|
23
|
+
object.stub(:friendly_instance_for_attribute => object_details)
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#read_friendly_attribute" do
|
27
|
+
it "finds the FriendlyAttributes instance for the specified attribute" do
|
28
|
+
object.
|
29
|
+
should_receive(:friendly_instance_for_attribute).
|
30
|
+
with(:foo).
|
31
|
+
and_return(object_details)
|
32
|
+
|
33
|
+
object.read_friendly_attribute(:foo)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "reads the attribute from the FriendlyAttributes instance" do
|
37
|
+
object_details.should_receive(:foo).and_return(foo)
|
38
|
+
object.read_friendly_attribute(:foo).should == foo
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#write_friendly_attribute" do
|
43
|
+
it "finds the FriendlyAttributes instance for the specified attribute" do
|
44
|
+
object.
|
45
|
+
should_receive(:friendly_instance_for_attribute).
|
46
|
+
with(:foo).
|
47
|
+
and_return(object_details)
|
48
|
+
|
49
|
+
object.write_friendly_attribute(:foo, "bar")
|
50
|
+
end
|
51
|
+
|
52
|
+
it "writes the attribute on the FriendlyAttributes instance" do
|
53
|
+
object_details.should_receive(:foo=).with("bar").and_return(foo)
|
54
|
+
object.write_friendly_attribute(:foo, "bar").should == foo
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#friendly_instance_for_attribute" do
|
62
|
+
it "reads the value for the friendly model from the instance" do
|
63
|
+
configuration.should_receive(:model_for_attribute).with(:foo).and_return(UserDetails)
|
64
|
+
object.should_receive(DetailsDelegator.friendly_model_reader(UserDetails)).and_return(user_details)
|
65
|
+
object.friendly_instance_for_attribute(:foo).should == user_details
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "#update_friendly_models" do
|
70
|
+
it "updates each loaded friendly model instance if needed" do
|
71
|
+
object.should_receive(:present_friendly_instances).and_return(friendly_model_instances)
|
72
|
+
friendly_model_instances.each do |instance|
|
73
|
+
instance.should_receive(:update_if_changed_with_model).with(object.id)
|
74
|
+
end
|
75
|
+
object.update_friendly_models
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "#destroy_friendly_details" do
|
80
|
+
it "loads and destroys all associated friendly models" do
|
81
|
+
object.should_receive(:all_friendly_instances).and_return(friendly_model_instances)
|
82
|
+
friendly_model_instances.each do |instance|
|
83
|
+
instance.should_receive(:destroy).and_return(true)
|
84
|
+
end
|
85
|
+
object.destroy_friendly_models.should be_true
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "#friendly_instance_present?" do
|
90
|
+
subject { object.friendly_instance_present?(friendly_model) }
|
91
|
+
let(:friendly_model) { UserDetails }
|
92
|
+
|
93
|
+
context "when friendly_details ivar is present" do
|
94
|
+
before(:each) do
|
95
|
+
object.instance_variable_set(DetailsDelegator.friendly_model_ivar(friendly_model), mock)
|
96
|
+
end
|
97
|
+
|
98
|
+
it { should be_true }
|
99
|
+
end
|
100
|
+
|
101
|
+
context "when friendly_details ivar is not present" do
|
102
|
+
it { should be_false }
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe "#friendly_instance_presence" do
|
107
|
+
subject { object.friendly_instance_presence(friendly_model) }
|
108
|
+
let(:friendly_model) { UserDetails }
|
109
|
+
|
110
|
+
context "when present" do
|
111
|
+
before(:each) do
|
112
|
+
object.instance_variable_set(DetailsDelegator.friendly_model_ivar(friendly_model), mock)
|
113
|
+
end
|
114
|
+
|
115
|
+
it "returns the instance using the model reader" do
|
116
|
+
object.should_receive(DetailsDelegator.friendly_model_reader(friendly_model)).and_return(user_details)
|
117
|
+
subject.should == user_details
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context "when not present" do
|
122
|
+
it "returns nil" do
|
123
|
+
subject.should be_nil
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe "#all_friendly_instances" do
|
129
|
+
let(:friendly_models) { [UserDetails, UserSecondDetails] }
|
130
|
+
|
131
|
+
it "loads and returns all the Friendly model instances associated with the record" do
|
132
|
+
configuration.should_receive(:friendly_models).and_return(friendly_models)
|
133
|
+
object.should_receive(DetailsDelegator.friendly_model_reader(UserDetails)).and_return(user_details)
|
134
|
+
object.should_receive(DetailsDelegator.friendly_model_reader(UserSecondDetails)).and_return(user_second_details)
|
135
|
+
object.all_friendly_instances.should == [user_details, user_second_details]
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe "#present_friendly_instances" do
|
140
|
+
let(:friendly_models) { [UserDetails, UserSecondDetails] }
|
141
|
+
|
142
|
+
it "returns all the loaded Friendly model instances associated with the record" do
|
143
|
+
configuration.should_receive(:friendly_models).and_return(friendly_models)
|
144
|
+
object.should_receive(:friendly_instance_presence).with(UserDetails).and_return(user_details)
|
145
|
+
object.should_receive(:friendly_instance_presence).with(UserSecondDetails).and_return(nil)
|
146
|
+
object.present_friendly_instances.should == [user_details]
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
describe "#friendly_details_build_options" do
|
151
|
+
context "when friendly_details_build_options is not defined" do
|
152
|
+
it "returns and empty Hash" do
|
153
|
+
object.friendly_details_build_options.should == { }
|
154
|
+
object.friendly_details_build_options(UserDetails).should == { }
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
context "when friendly_details_build_options is defined" do
|
159
|
+
let(:foo) { mock("default friendly details build option") }
|
160
|
+
|
161
|
+
before(:each) do
|
162
|
+
_foo = foo
|
163
|
+
|
164
|
+
klass.class_eval do
|
165
|
+
define_method(:friendly_details_build_options) do |klass|
|
166
|
+
{ :foo => _foo }
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
it "returns the options specified by friendly_details_build_options" do
|
172
|
+
object.friendly_details_build_options(UserSecondDetails).should == { :foo => foo }
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
describe "#changed?" do
|
178
|
+
subject { active_record.changed? }
|
179
|
+
let(:active_record) { User.create(:name => "Stan", :email => "stan@example.com") }
|
180
|
+
|
181
|
+
context "when the ActiveRecord model has changed," do
|
182
|
+
before(:each) do
|
183
|
+
active_record.email = "eric@example.com"
|
184
|
+
end
|
185
|
+
|
186
|
+
context "and the Friendly model has changed," do
|
187
|
+
before(:each) do
|
188
|
+
active_record.name = "Eric"
|
189
|
+
end
|
190
|
+
|
191
|
+
it { should be_true }
|
192
|
+
end
|
193
|
+
|
194
|
+
context "and the Friendly model has not changed" do
|
195
|
+
it { should be_true }
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
context "when the ActiveRecord model has not changed," do
|
200
|
+
context "and the Friendly model has changed" do
|
201
|
+
before(:each) do
|
202
|
+
active_record.name = "Eric"
|
203
|
+
end
|
204
|
+
|
205
|
+
it { should be_true }
|
206
|
+
end
|
207
|
+
|
208
|
+
context "and the Friendly model has not changed" do
|
209
|
+
it { should be_false }
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
describe "#find_or_build_and_memoize_details" do
|
215
|
+
let(:user) { @user }
|
216
|
+
let(:build_options) { mock(Hash) }
|
217
|
+
let(:user_details) { double(UserDetails) }
|
218
|
+
|
219
|
+
before(:each) do
|
220
|
+
@user = User.find(User.create(:name => "Stan", :email => "stan@example.com").id)
|
221
|
+
end
|
222
|
+
|
223
|
+
it "finds (or builds a new instance with build options) and memoizes the associated Friendly instance" do
|
224
|
+
user.
|
225
|
+
should_receive(:friendly_details_build_options).
|
226
|
+
with(UserDetails).
|
227
|
+
once.
|
228
|
+
and_return(build_options)
|
229
|
+
|
230
|
+
UserDetails.
|
231
|
+
should_receive(:find_or_build_by_active_record_id).
|
232
|
+
with(user.id, build_options).
|
233
|
+
once.
|
234
|
+
and_return(user_details)
|
235
|
+
|
236
|
+
user.find_or_build_and_memoize_details(UserDetails).should == user_details
|
237
|
+
user.find_or_build_and_memoize_details(UserDetails).should == user_details
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe FriendlyAttributes do
|
4
|
+
use_database_cleanup
|
5
|
+
|
6
|
+
describe "definition" do
|
7
|
+
it { User.should have_friendly_attributes(String, :name, :through => UserDetails) }
|
8
|
+
it { User.should have_friendly_attributes(Integer, :second_int, :through => UserSecondDetails) }
|
9
|
+
it { User.new.should have_friendly_attributes(Integer, :shoe_size, :birth_year, :through => UserDetails) }
|
10
|
+
it { User.new.should have_friendly_attributes(Friendly::Boolean, :subscribed, :through => UserDetails) }
|
11
|
+
it { User.should_not have_friendly_attributes(String, :foo, :through => UserDetails) }
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "creating" do
|
15
|
+
context "with Friendly attributes" do
|
16
|
+
context "when using just one Friendly model" do
|
17
|
+
let(:user) { User.create!(:name => "Stan", :email => "stan@example.com", :birth_year => 1984, :subscribed => true) }
|
18
|
+
|
19
|
+
it "creates only the required Friendly model" do
|
20
|
+
expect do
|
21
|
+
expect do
|
22
|
+
user
|
23
|
+
end.to change { UserDetails.count({}) }
|
24
|
+
end.to_not change { UserSecondDetails.count({}) }
|
25
|
+
end
|
26
|
+
|
27
|
+
it "sets the appropriate attributes on the ActiveRecord model and associated Friendly model" do
|
28
|
+
user_detail = user.load_user_details
|
29
|
+
user_detail.name.should == "Stan"
|
30
|
+
user_detail.birth_year.should == 1984
|
31
|
+
user_detail.shoe_size.should == 42
|
32
|
+
user_detail.subscribed.should be_true
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "when using multiple associated Friendly models" do
|
37
|
+
let(:user) { User.create!(:name => "Stan", :email => "stan@example.com", :birth_year => 1984, :second_int => 120, :subscribed => true) }
|
38
|
+
|
39
|
+
it "creates all the required Friendly models" do
|
40
|
+
expect do
|
41
|
+
expect do
|
42
|
+
user
|
43
|
+
end.to change { UserDetails.count({}) }
|
44
|
+
end.to change { UserSecondDetails.count({}) }
|
45
|
+
end
|
46
|
+
|
47
|
+
it "sets the appropriate attributes on the ActiveRecord model and associated Friendly model" do
|
48
|
+
user_detail = user.load_user_details
|
49
|
+
user_detail.name.should == "Stan"
|
50
|
+
user_detail.birth_year.should == 1984
|
51
|
+
user_detail.shoe_size.should == 42
|
52
|
+
user_detail.subscribed.should be_true
|
53
|
+
|
54
|
+
user_second_detail = user.load_user_second_details
|
55
|
+
user_second_detail.second_int.should == 120
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context "without Friendly attributes" do
|
61
|
+
let(:user) { User.create(:email => "stan@example.com") }
|
62
|
+
|
63
|
+
it "does not create an associated Friendly model" do
|
64
|
+
expect do
|
65
|
+
user
|
66
|
+
end.to_not change { UserDetails.count({}) }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "reading" do
|
72
|
+
let(:user) { User.create!(:name => "Stan", :email => "stan@example.com", :birth_year => 1984, :subscribed => true) }
|
73
|
+
|
74
|
+
it "through the attr_reader" do
|
75
|
+
user.name.should == "Stan"
|
76
|
+
end
|
77
|
+
|
78
|
+
it "through read_friendly_attribute" do
|
79
|
+
user.read_friendly_attribute(:name).should == "Stan"
|
80
|
+
user.read_friendly_attribute(:birth_year).should == 1984
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "updating" do
|
85
|
+
context "with Friendly attributes" do
|
86
|
+
let(:user) { User.create(:name => "Stan", :email => "stan@example.com", :second_int => 200) }
|
87
|
+
|
88
|
+
it "updates the attributes" do
|
89
|
+
user.update_attributes(:name => "Eric", :second_int => 123)
|
90
|
+
UserDetails.first({}).name.should == "Eric"
|
91
|
+
UserSecondDetails.first({}).second_int.should == 123
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context "without Friendly attributes" do
|
96
|
+
let(:user) { User.create(:email => "stan@example.com") }
|
97
|
+
|
98
|
+
it "does not create an associated Details model, if no delegated attributes are updated" do
|
99
|
+
expect do
|
100
|
+
user.update_attributes(:email => "eric@example.com")
|
101
|
+
end.to_not change { UserDetails.count({}) }
|
102
|
+
end
|
103
|
+
|
104
|
+
it "creates an associated Details model, if delegated attributes are updated" do
|
105
|
+
expect do
|
106
|
+
user.update_attributes(:name => "Eric")
|
107
|
+
end.to change { UserDetails.count({}) }
|
108
|
+
user.name.should == "Eric"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context "with nested attributes" do
|
113
|
+
let(:user) { User.create(:name => "Stan Marsh", :email => "smarsh@example.com") }
|
114
|
+
let(:parent) { Parent.create(:users => [user]) }
|
115
|
+
|
116
|
+
before(:each) do
|
117
|
+
parent
|
118
|
+
parent.update_attributes(:users_attributes => users_attributes)
|
119
|
+
user.reload
|
120
|
+
end
|
121
|
+
|
122
|
+
context "when only changing Friendly attributes" do
|
123
|
+
let(:users_attributes) { { "0" => { "id" => user.id, "name" => "Eric Cartman" } } }
|
124
|
+
|
125
|
+
it "updates Friendly attributes through nested association" do
|
126
|
+
user.name.should == "Eric Cartman"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
context "when changing both Friendly attributes and ActiveRecord attributes" do
|
131
|
+
let(:users_attributes) { { "0" => { "id" => user.id, "name" => "Eric Cartman", "email" => "eric@example.com" } } }
|
132
|
+
|
133
|
+
it "updates Friendly attributes through nested association" do
|
134
|
+
user.email.should == "eric@example.com"
|
135
|
+
user.name.should == "Eric Cartman"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe "destroying" do
|
142
|
+
let(:user) { User.create(:name => "Stan", :email => "stan@example.com") }
|
143
|
+
|
144
|
+
it "destroys the associated Details model" do
|
145
|
+
user # create it first
|
146
|
+
|
147
|
+
expect do
|
148
|
+
user.destroy
|
149
|
+
end.to change { UserDetails.count({}) }.by(-1)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|