ridley 0.10.2 → 0.11.0.rc1
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/README.md +147 -216
- data/lib/ridley.rb +2 -0
- data/lib/ridley/bootstrap_bindings/unix_template_binding.rb +21 -25
- data/lib/ridley/bootstrap_bindings/windows_template_binding.rb +29 -34
- data/lib/ridley/bootstrapper.rb +2 -2
- data/lib/ridley/bootstrapper/context.rb +5 -5
- data/lib/ridley/chef.rb +0 -1
- data/lib/ridley/chef/cookbook.rb +0 -9
- data/lib/ridley/chef_object.rb +128 -0
- data/lib/ridley/chef_objects.rb +3 -0
- data/lib/ridley/chef_objects/client_object.rb +55 -0
- data/lib/ridley/chef_objects/cookbook_object.rb +190 -0
- data/lib/ridley/chef_objects/data_bag_item_obect.rb +104 -0
- data/lib/ridley/chef_objects/data_bag_object.rb +31 -0
- data/lib/ridley/chef_objects/environment_object.rb +59 -0
- data/lib/ridley/chef_objects/node_object.rb +161 -0
- data/lib/ridley/chef_objects/role_object.rb +62 -0
- data/lib/ridley/chef_objects/sandbox_object.rb +58 -0
- data/lib/ridley/client.rb +76 -45
- data/lib/ridley/connection.rb +1 -1
- data/lib/ridley/errors.rb +8 -1
- data/lib/ridley/host_connector.rb +26 -6
- data/lib/ridley/host_connector/ssh.rb +3 -3
- data/lib/ridley/host_connector/ssh/worker.rb +7 -9
- data/lib/ridley/host_connector/winrm/worker.rb +4 -5
- data/lib/ridley/mixin/bootstrap_binding.rb +1 -12
- data/lib/ridley/resource.rb +51 -171
- data/lib/ridley/resources/client_resource.rb +18 -68
- data/lib/ridley/resources/cookbook_resource.rb +181 -381
- data/lib/ridley/resources/data_bag_item_resource.rb +55 -161
- data/lib/ridley/resources/data_bag_resource.rb +20 -61
- data/lib/ridley/resources/environment_resource.rb +9 -64
- data/lib/ridley/resources/node_resource.rb +135 -311
- data/lib/ridley/resources/role_resource.rb +1 -57
- data/lib/ridley/resources/sandbox_resource.rb +80 -65
- data/lib/ridley/resources/search_resource.rb +99 -0
- data/lib/ridley/sandbox_uploader.rb +12 -52
- data/lib/ridley/version.rb +1 -1
- data/spec/acceptance/bootstrapping_spec.rb +1 -1
- data/spec/acceptance/client_resource_spec.rb +15 -37
- data/spec/acceptance/data_bag_item_resource_spec.rb +8 -14
- data/spec/acceptance/data_bag_resource_spec.rb +1 -1
- data/spec/acceptance/environment_resource_spec.rb +13 -22
- data/spec/acceptance/node_resource_spec.rb +10 -29
- data/spec/acceptance/role_resource_spec.rb +14 -13
- data/spec/acceptance/sandbox_resource_spec.rb +2 -2
- data/spec/support/shared_examples/ridley_resource.rb +2 -23
- data/spec/unit/ridley/bootstrap_bindings/unix_template_binding_spec.rb +3 -4
- data/spec/unit/ridley/bootstrap_bindings/windows_template_binding_spec.rb +3 -5
- data/spec/unit/ridley/bootstrapper/context_spec.rb +2 -3
- data/spec/unit/ridley/bootstrapper_spec.rb +1 -1
- data/spec/unit/ridley/chef_object_spec.rb +240 -0
- data/spec/unit/ridley/chef_objects/client_object_spec.rb +11 -0
- data/spec/unit/ridley/chef_objects/cookbook_object_spec.rb +93 -0
- data/spec/unit/ridley/chef_objects/data_bag_item_object_spec.rb +74 -0
- data/spec/unit/ridley/chef_objects/data_bag_object_spec.rb +9 -0
- data/spec/unit/ridley/chef_objects/environment_object_spec.rb +57 -0
- data/spec/unit/ridley/chef_objects/node_object_spec.rb +252 -0
- data/spec/unit/ridley/chef_objects/role_object_spec.rb +57 -0
- data/spec/unit/ridley/chef_objects/sandbox_object_spec.rb +66 -0
- data/spec/unit/ridley/client_spec.rb +51 -51
- data/spec/unit/ridley/host_connector/ssh/worker_spec.rb +4 -4
- data/spec/unit/ridley/host_connector/ssh_spec.rb +26 -24
- data/spec/unit/ridley/host_connector/winrm/worker_spec.rb +3 -4
- data/spec/unit/ridley/host_connector/winrm_spec.rb +4 -4
- data/spec/unit/ridley/host_connector_spec.rb +40 -3
- data/spec/unit/ridley/mixin/bootstrap_binding_spec.rb +1 -1
- data/spec/unit/ridley/resource_spec.rb +81 -109
- data/spec/unit/ridley/resources/client_resource_spec.rb +18 -33
- data/spec/unit/ridley/resources/cookbook_resource_spec.rb +56 -230
- data/spec/unit/ridley/resources/data_bag_item_resource_spec.rb +2 -57
- data/spec/unit/ridley/resources/data_bag_resource_spec.rb +12 -7
- data/spec/unit/ridley/resources/environment_resource_spec.rb +10 -118
- data/spec/unit/ridley/resources/node_resource_spec.rb +83 -394
- data/spec/unit/ridley/resources/role_resource_spec.rb +2 -56
- data/spec/unit/ridley/resources/sandbox_resource_spec.rb +139 -136
- data/spec/unit/ridley/resources/search_resource_spec.rb +234 -0
- data/spec/unit/ridley/sandbox_uploader_spec.rb +13 -58
- metadata +36 -17
- data/lib/ridley/chef/chefignore.rb +0 -76
- data/lib/ridley/resources/encrypted_data_bag_item_resource.rb +0 -55
- data/lib/ridley/resources/search.rb +0 -101
- data/spec/fixtures/chefignore +0 -8
- data/spec/unit/ridley/chef/chefignore_spec.rb +0 -40
- data/spec/unit/ridley/resources/search_spec.rb +0 -221
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ridley::DataBagItemObject do
|
4
|
+
let(:resource) { double('chef-resource') }
|
5
|
+
let(:data_bag) { double('data-bag') }
|
6
|
+
subject { described_class.new(resource, data_bag) }
|
7
|
+
|
8
|
+
describe "#from_hash" do
|
9
|
+
context "when JSON has a 'raw_data' field" do
|
10
|
+
let(:response) do
|
11
|
+
{
|
12
|
+
"name" => "data_bag_item_ridley-test_appconfig",
|
13
|
+
"raw_data" => {
|
14
|
+
"id" => "appconfig",
|
15
|
+
"host" => "host.local"
|
16
|
+
},
|
17
|
+
"json_class" => "Chef::DataBagItem",
|
18
|
+
"data_bag" => "ridley-test",
|
19
|
+
"chef_type" => "data_bag_item"
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
it "returns a new object from attributes in the 'raw_data' field" do
|
24
|
+
subject.from_hash(response).attributes.should eql(response["raw_data"])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "when JSON does not contain a 'raw_data' field" do
|
29
|
+
let(:response) do
|
30
|
+
{
|
31
|
+
"id" => "appconfig",
|
32
|
+
"host" => "host.local"
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
it "returns a new object from the hash" do
|
37
|
+
subject.from_hash(response).attributes.should eql(response)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#decrypt" do
|
43
|
+
before(:each) do
|
44
|
+
resource.stub(encrypted_data_bag_secret: File.read(fixtures_path.join("encrypted_data_bag_secret").to_s))
|
45
|
+
end
|
46
|
+
|
47
|
+
it "decrypts an encrypted value" do
|
48
|
+
subject.attributes[:test] = "Xk0E8lV9r4BhZzcg4wal0X4w9ZexN3azxMjZ9r1MCZc="
|
49
|
+
subject.decrypt
|
50
|
+
subject.attributes[:test][:database][:username].should == "test"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "does not decrypt the id field" do
|
54
|
+
id = "dbi_id"
|
55
|
+
subject.attributes[:id] = id
|
56
|
+
subject.decrypt
|
57
|
+
subject.attributes[:id].should == id
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#decrypt_value" do
|
62
|
+
context "when no encrypted_data_bag_secret has been configured" do
|
63
|
+
before do
|
64
|
+
resource.stub(encrypted_data_bag_secret: nil)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "raises an EncryptedDataBagSecretNotSet error" do
|
68
|
+
expect {
|
69
|
+
subject.decrypt_value("Xk0E8lV9r4BhZzcg4wal0X4w9ZexN3azxMjZ9r1MCZc=")
|
70
|
+
}.to raise_error(Ridley::Errors::EncryptedDataBagSecretNotSet)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ridley::DataBagObject do
|
4
|
+
let(:item_resource) { double('item-resource') }
|
5
|
+
let(:resource) { double('db-resource', item_resource: item_resource) }
|
6
|
+
subject { described_class.new(resource) }
|
7
|
+
|
8
|
+
its(:item) { should be_a(Ridley::DataBagObject::DataBagItemProxy) }
|
9
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ridley::EnvironmentObject do
|
4
|
+
subject { described_class.new(double('registry')) }
|
5
|
+
|
6
|
+
describe "#set_override_attribute" do
|
7
|
+
it "sets an override node attribute at the nested path" do
|
8
|
+
subject.set_override_attribute('deep.nested.item', true)
|
9
|
+
|
10
|
+
subject.override_attributes.should have_key("deep")
|
11
|
+
subject.override_attributes["deep"].should have_key("nested")
|
12
|
+
subject.override_attributes["deep"]["nested"].should have_key("item")
|
13
|
+
subject.override_attributes["deep"]["nested"]["item"].should be_true
|
14
|
+
end
|
15
|
+
|
16
|
+
context "when the override attribute is already set" do
|
17
|
+
it "test" do
|
18
|
+
subject.override_attributes = {
|
19
|
+
deep: {
|
20
|
+
nested: {
|
21
|
+
item: false
|
22
|
+
}
|
23
|
+
}
|
24
|
+
}
|
25
|
+
subject.set_override_attribute('deep.nested.item', true)
|
26
|
+
|
27
|
+
subject.override_attributes["deep"]["nested"]["item"].should be_true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#set_default_attribute" do
|
33
|
+
it "sets an override node attribute at the nested path" do
|
34
|
+
subject.set_default_attribute('deep.nested.item', true)
|
35
|
+
|
36
|
+
subject.default_attributes.should have_key("deep")
|
37
|
+
subject.default_attributes["deep"].should have_key("nested")
|
38
|
+
subject.default_attributes["deep"]["nested"].should have_key("item")
|
39
|
+
subject.default_attributes["deep"]["nested"]["item"].should be_true
|
40
|
+
end
|
41
|
+
|
42
|
+
context "when the override attribute is already set" do
|
43
|
+
it "test" do
|
44
|
+
subject.default_attributes = {
|
45
|
+
deep: {
|
46
|
+
nested: {
|
47
|
+
item: false
|
48
|
+
}
|
49
|
+
}
|
50
|
+
}
|
51
|
+
subject.set_default_attribute('deep.nested.item', true)
|
52
|
+
|
53
|
+
subject.default_attributes["deep"]["nested"]["item"].should be_true
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,252 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ridley::NodeObject do
|
4
|
+
let(:resource) { double('resource') }
|
5
|
+
let(:instance) { described_class.new(resource) }
|
6
|
+
subject { instance }
|
7
|
+
|
8
|
+
describe "#set_chef_attribute" do
|
9
|
+
it "sets an normal node attribute at the nested path" do
|
10
|
+
subject.set_chef_attribute('deep.nested.item', true)
|
11
|
+
|
12
|
+
subject.normal.should have_key("deep")
|
13
|
+
subject.normal["deep"].should have_key("nested")
|
14
|
+
subject.normal["deep"]["nested"].should have_key("item")
|
15
|
+
subject.normal["deep"]["nested"]["item"].should be_true
|
16
|
+
end
|
17
|
+
|
18
|
+
context "when the normal attribute is already set" do
|
19
|
+
it "test" do
|
20
|
+
subject.normal = {
|
21
|
+
deep: {
|
22
|
+
nested: {
|
23
|
+
item: false
|
24
|
+
}
|
25
|
+
}
|
26
|
+
}
|
27
|
+
subject.set_chef_attribute('deep.nested.item', true)
|
28
|
+
|
29
|
+
subject.normal["deep"]["nested"]["item"].should be_true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#cloud?" do
|
35
|
+
it "returns true if the cloud automatic attribute is set" do
|
36
|
+
subject.automatic = {
|
37
|
+
"cloud" => Hash.new
|
38
|
+
}
|
39
|
+
|
40
|
+
subject.cloud?.should be_true
|
41
|
+
end
|
42
|
+
|
43
|
+
it "returns false if the cloud automatic attribute is not set" do
|
44
|
+
subject.automatic.delete(:cloud)
|
45
|
+
|
46
|
+
subject.cloud?.should be_false
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#eucalyptus?" do
|
51
|
+
it "returns true if the node is a cloud node using the eucalyptus provider" do
|
52
|
+
subject.automatic = {
|
53
|
+
"cloud" => {
|
54
|
+
"provider" => "eucalyptus"
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
subject.eucalyptus?.should be_true
|
59
|
+
end
|
60
|
+
|
61
|
+
it "returns false if the node is not a cloud node" do
|
62
|
+
subject.automatic.delete(:cloud)
|
63
|
+
|
64
|
+
subject.eucalyptus?.should be_false
|
65
|
+
end
|
66
|
+
|
67
|
+
it "returns false if the node is a cloud node but not using the eucalyptus provider" do
|
68
|
+
subject.automatic = {
|
69
|
+
"cloud" => {
|
70
|
+
"provider" => "ec2"
|
71
|
+
}
|
72
|
+
}
|
73
|
+
|
74
|
+
subject.eucalyptus?.should be_false
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "#ec2?" do
|
79
|
+
it "returns true if the node is a cloud node using the ec2 provider" do
|
80
|
+
subject.automatic = {
|
81
|
+
"cloud" => {
|
82
|
+
"provider" => "ec2"
|
83
|
+
}
|
84
|
+
}
|
85
|
+
|
86
|
+
subject.ec2?.should be_true
|
87
|
+
end
|
88
|
+
|
89
|
+
it "returns false if the node is not a cloud node" do
|
90
|
+
subject.automatic.delete(:cloud)
|
91
|
+
|
92
|
+
subject.ec2?.should be_false
|
93
|
+
end
|
94
|
+
|
95
|
+
it "returns false if the node is a cloud node but not using the ec2 provider" do
|
96
|
+
subject.automatic = {
|
97
|
+
"cloud" => {
|
98
|
+
"provider" => "rackspace"
|
99
|
+
}
|
100
|
+
}
|
101
|
+
|
102
|
+
subject.ec2?.should be_false
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe "#rackspace?" do
|
107
|
+
it "returns true if the node is a cloud node using the rackspace provider" do
|
108
|
+
subject.automatic = {
|
109
|
+
"cloud" => {
|
110
|
+
"provider" => "rackspace"
|
111
|
+
}
|
112
|
+
}
|
113
|
+
|
114
|
+
subject.rackspace?.should be_true
|
115
|
+
end
|
116
|
+
|
117
|
+
it "returns false if the node is not a cloud node" do
|
118
|
+
subject.automatic.delete(:cloud)
|
119
|
+
|
120
|
+
subject.rackspace?.should be_false
|
121
|
+
end
|
122
|
+
|
123
|
+
it "returns false if the node is a cloud node but not using the rackspace provider" do
|
124
|
+
subject.automatic = {
|
125
|
+
"cloud" => {
|
126
|
+
"provider" => "ec2"
|
127
|
+
}
|
128
|
+
}
|
129
|
+
|
130
|
+
subject.rackspace?.should be_false
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
describe "#cloud_provider" do
|
135
|
+
it "returns the cloud provider if the node is a cloud node" do
|
136
|
+
subject.automatic = {
|
137
|
+
"cloud" => {
|
138
|
+
"provider" => "ec2"
|
139
|
+
}
|
140
|
+
}
|
141
|
+
|
142
|
+
subject.cloud_provider.should eql("ec2")
|
143
|
+
end
|
144
|
+
|
145
|
+
it "returns nil if the node is not a cloud node" do
|
146
|
+
subject.automatic.delete(:cloud)
|
147
|
+
|
148
|
+
subject.cloud_provider.should be_nil
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
describe "#public_ipv4" do
|
153
|
+
it "returns the public ipv4 address if the node is a cloud node" do
|
154
|
+
subject.automatic = {
|
155
|
+
"cloud" => {
|
156
|
+
"provider" => "ec2",
|
157
|
+
"public_ipv4" => "10.0.0.1"
|
158
|
+
}
|
159
|
+
}
|
160
|
+
|
161
|
+
subject.public_ipv4.should eql("10.0.0.1")
|
162
|
+
end
|
163
|
+
|
164
|
+
it "returns the ipaddress if the node is not a cloud node" do
|
165
|
+
subject.automatic = {
|
166
|
+
"ipaddress" => "192.168.1.1"
|
167
|
+
}
|
168
|
+
subject.automatic.delete(:cloud)
|
169
|
+
|
170
|
+
subject.public_ipv4.should eql("192.168.1.1")
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
describe "#public_hostname" do
|
175
|
+
it "returns the public hostname if the node is a cloud node" do
|
176
|
+
subject.automatic = {
|
177
|
+
"cloud" => {
|
178
|
+
"public_hostname" => "reset.cloud.riotgames.com"
|
179
|
+
}
|
180
|
+
}
|
181
|
+
|
182
|
+
subject.public_hostname.should eql("reset.cloud.riotgames.com")
|
183
|
+
end
|
184
|
+
|
185
|
+
it "returns the FQDN if the node is not a cloud node" do
|
186
|
+
subject.automatic = {
|
187
|
+
"fqdn" => "reset.internal.riotgames.com"
|
188
|
+
}
|
189
|
+
subject.automatic.delete(:cloud)
|
190
|
+
|
191
|
+
subject.public_hostname.should eql("reset.internal.riotgames.com")
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
describe "#chef_run" do
|
196
|
+
it "sends the message #chef_run to the resource with the public_hostname of this instance" do
|
197
|
+
resource.should_receive(:chef_run).with(instance.public_hostname)
|
198
|
+
|
199
|
+
subject.chef_run
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
describe "#put_secret" do
|
204
|
+
it "sends the message #put_secret to the resource with the public_hostname of this instance" do
|
205
|
+
resource.should_receive(:put_secret).with(instance.public_hostname)
|
206
|
+
|
207
|
+
subject.put_secret
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
describe "#merge_data" do
|
212
|
+
before(:each) do
|
213
|
+
subject.name = "reset.riotgames.com"
|
214
|
+
subject.should_receive(:update)
|
215
|
+
end
|
216
|
+
|
217
|
+
it "appends items to the run_list" do
|
218
|
+
subject.merge_data(run_list: ["cook::one", "cook::two"])
|
219
|
+
|
220
|
+
subject.run_list.should =~ ["cook::one", "cook::two"]
|
221
|
+
end
|
222
|
+
|
223
|
+
it "ensures the run_list is unique if identical items are given" do
|
224
|
+
subject.run_list = [ "cook::one" ]
|
225
|
+
subject.merge_data(run_list: ["cook::one", "cook::two"])
|
226
|
+
|
227
|
+
subject.run_list.should =~ ["cook::one", "cook::two"]
|
228
|
+
end
|
229
|
+
|
230
|
+
it "deep merges attributes into the normal attributes" do
|
231
|
+
subject.normal = {
|
232
|
+
one: {
|
233
|
+
two: {
|
234
|
+
four: :deep
|
235
|
+
}
|
236
|
+
}
|
237
|
+
}
|
238
|
+
subject.merge_data(attributes: {
|
239
|
+
one: {
|
240
|
+
two: {
|
241
|
+
three: :deep
|
242
|
+
}
|
243
|
+
}
|
244
|
+
})
|
245
|
+
|
246
|
+
subject.normal[:one][:two].should have_key(:four)
|
247
|
+
subject.normal[:one][:two][:four].should eql(:deep)
|
248
|
+
subject.normal[:one][:two].should have_key(:three)
|
249
|
+
subject.normal[:one][:two][:three].should eql(:deep)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ridley::RoleObject do
|
4
|
+
subject { described_class.new(double('registry')) }
|
5
|
+
|
6
|
+
describe "#set_override_attribute" do
|
7
|
+
it "sets an override node attribute at the nested path" do
|
8
|
+
subject.set_override_attribute('deep.nested.item', true)
|
9
|
+
|
10
|
+
subject.override_attributes.should have_key("deep")
|
11
|
+
subject.override_attributes["deep"].should have_key("nested")
|
12
|
+
subject.override_attributes["deep"]["nested"].should have_key("item")
|
13
|
+
subject.override_attributes["deep"]["nested"]["item"].should be_true
|
14
|
+
end
|
15
|
+
|
16
|
+
context "when the override attribute is already set" do
|
17
|
+
it "test" do
|
18
|
+
subject.override_attributes = {
|
19
|
+
deep: {
|
20
|
+
nested: {
|
21
|
+
item: false
|
22
|
+
}
|
23
|
+
}
|
24
|
+
}
|
25
|
+
subject.set_override_attribute('deep.nested.item', true)
|
26
|
+
|
27
|
+
subject.override_attributes["deep"]["nested"]["item"].should be_true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#set_default_attribute" do
|
33
|
+
it "sets an override node attribute at the nested path" do
|
34
|
+
subject.set_default_attribute('deep.nested.item', true)
|
35
|
+
|
36
|
+
subject.default_attributes.should have_key("deep")
|
37
|
+
subject.default_attributes["deep"].should have_key("nested")
|
38
|
+
subject.default_attributes["deep"]["nested"].should have_key("item")
|
39
|
+
subject.default_attributes["deep"]["nested"]["item"].should be_true
|
40
|
+
end
|
41
|
+
|
42
|
+
context "when the override attribute is already set" do
|
43
|
+
it "test" do
|
44
|
+
subject.default_attributes = {
|
45
|
+
deep: {
|
46
|
+
nested: {
|
47
|
+
item: false
|
48
|
+
}
|
49
|
+
}
|
50
|
+
}
|
51
|
+
subject.set_default_attribute('deep.nested.item', true)
|
52
|
+
|
53
|
+
subject.default_attributes["deep"]["nested"]["item"].should be_true
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|