anyway_config 0.4.0 → 0.5.1.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +4 -1
- data/.rubocop.yml +38 -0
- data/.travis.yml +18 -25
- data/CHANGELOG.md +21 -0
- data/Gemfile +11 -3
- data/LICENSE.txt +1 -1
- data/README.md +82 -47
- data/Rakefile +18 -5
- data/anyway_config.gemspec +15 -11
- data/config/cool.yml +5 -0
- data/gemfiles/rails42.gemfile +1 -2
- data/gemfiles/rails5.gemfile +6 -0
- data/gemfiles/railsmaster.gemfile +6 -0
- data/lib/anyway.rb +3 -5
- data/lib/anyway/config.rb +52 -31
- data/lib/anyway/env.rb +60 -61
- data/lib/anyway/ext/class.rb +18 -0
- data/lib/anyway/ext/deep_dup.rb +34 -0
- data/lib/anyway/ext/hash.rb +34 -0
- data/lib/anyway/rails/config.rb +16 -7
- data/lib/anyway/version.rb +5 -3
- data/lib/anyway_config.rb +3 -0
- data/spec/anyway.yml +1 -1
- data/spec/config_spec.rb +30 -19
- data/spec/config_spec_norails.rb +59 -16
- data/spec/dummy/config.ru +0 -4
- data/spec/dummy/config/application.rb +3 -12
- data/spec/dummy/config/cool.yml +1 -1
- data/spec/dummy/config/environments/test.rb +0 -37
- data/spec/dummy/config/routes.rb +0 -54
- data/spec/dummy/config/secrets.yml +0 -1
- data/spec/env_spec.rb +18 -14
- data/spec/ext/deep_dup_spec.rb +38 -0
- data/spec/spec_helper.rb +21 -9
- data/spec/spec_norails_helper.rb +18 -5
- data/spec/support/cool_config.rb +9 -3
- data/spec/support/test_config.rb +14 -3
- metadata +26 -80
- data/gemfiles/rails32.gemfile +0 -7
- data/gemfiles/rails40.gemfile +0 -7
- data/gemfiles/rails41.gemfile +0 -7
- data/spec/dummy.yml +0 -0
- data/spec/dummy/README.rdoc +0 -28
- data/spec/dummy/Rakefile +0 -6
- data/spec/dummy/app/assets/images/.keep +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +0 -13
- data/spec/dummy/app/assets/stylesheets/application.css +0 -15
- data/spec/dummy/app/controllers/application_controller.rb +0 -5
- data/spec/dummy/app/controllers/concerns/.keep +0 -0
- data/spec/dummy/app/helpers/application_helper.rb +0 -2
- data/spec/dummy/app/mailers/.keep +0 -0
- data/spec/dummy/app/models/.keep +0 -0
- data/spec/dummy/app/models/concerns/.keep +0 -0
- data/spec/dummy/app/views/layouts/application.html.erb +0 -14
- data/spec/dummy/bin/bundle +0 -3
- data/spec/dummy/bin/rails +0 -4
- data/spec/dummy/bin/rake +0 -4
- data/spec/dummy/config/environments/development.rb +0 -37
- data/spec/dummy/config/environments/production.rb +0 -83
- data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
- data/spec/dummy/config/initializers/cookies_serializer.rb +0 -3
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +0 -4
- data/spec/dummy/config/initializers/inflections.rb +0 -16
- data/spec/dummy/config/initializers/mime_types.rb +0 -4
- data/spec/dummy/config/initializers/session_store.rb +0 -3
- data/spec/dummy/config/initializers/wrap_parameters.rb +0 -14
- data/spec/dummy/config/locales/en.yml +0 -23
- data/spec/dummy/db/migrate/20140730133818_add_testos.rb +0 -11
- data/spec/dummy/db/migrate/20140731162044_add_column_to_testos.rb +0 -5
- data/spec/dummy/db/schema.rb +0 -22
- data/spec/dummy/lib/assets/.keep +0 -0
- data/spec/dummy/log/.keep +0 -0
- data/spec/dummy/public/404.html +0 -67
- data/spec/dummy/public/422.html +0 -67
- data/spec/dummy/public/500.html +0 -66
- data/spec/dummy/public/favicon.ico +0 -0
data/lib/anyway/version.rb
CHANGED
data/spec/anyway.yml
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
api:
|
2
|
-
endpoint: 'localhost'
|
2
|
+
endpoint: 'localhost'
|
data/spec/config_spec.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe Anyway::Config do
|
@@ -5,14 +7,18 @@ describe Anyway::Config do
|
|
5
7
|
let(:test_conf) { Anyway::TestConfig.new }
|
6
8
|
|
7
9
|
describe "config with name" do
|
10
|
+
before(:each) do
|
11
|
+
ENV.delete_if { |var| var =~ /^(cool|anyway)_/i }
|
12
|
+
end
|
13
|
+
|
8
14
|
specify { expect(CoolConfig.config_name).to eq "cool" }
|
9
|
-
|
15
|
+
|
10
16
|
describe "defaults" do
|
11
17
|
specify { expect(CoolConfig.defaults[:port]).to eq 8080 }
|
12
18
|
specify { expect(CoolConfig.defaults[:host]).to eq 'localhost' }
|
13
19
|
end
|
14
20
|
|
15
|
-
|
21
|
+
it "generates accessors", :aggregate_failures do
|
16
22
|
expect(conf).to respond_to(:meta)
|
17
23
|
expect(conf).to respond_to(:data)
|
18
24
|
expect(conf).to respond_to(:port)
|
@@ -21,42 +27,45 @@ describe Anyway::Config do
|
|
21
27
|
end
|
22
28
|
|
23
29
|
describe "load from files" do
|
24
|
-
it "
|
30
|
+
it "set defaults" do
|
25
31
|
expect(conf.port).to eq 8080
|
26
32
|
end
|
27
33
|
|
28
|
-
it "
|
34
|
+
it "load config from YAML" do
|
29
35
|
expect(conf.host).to eq "test.host"
|
30
36
|
end
|
31
37
|
|
32
38
|
if Rails.application.respond_to?(:secrets)
|
33
|
-
it "
|
39
|
+
it "load config from secrets" do
|
34
40
|
expect(conf.user[:name]).to eq "test"
|
35
|
-
expect(conf.user[:password]).to eq "test"
|
36
41
|
end
|
37
42
|
else
|
38
|
-
it "
|
43
|
+
it "load config from file if no secrets" do
|
39
44
|
expect(conf.user[:name]).to eq "root"
|
40
|
-
expect(conf.user[:password]).to eq "root"
|
45
|
+
expect(conf.user[:password]).to eq "root"
|
41
46
|
end
|
42
47
|
end
|
43
48
|
end
|
44
49
|
|
45
50
|
describe "load from env" do
|
46
|
-
|
47
|
-
it "should work" do
|
51
|
+
it "work" do
|
48
52
|
ENV['COOL_PORT'] = '80'
|
49
53
|
ENV['COOL_USER__NAME'] = 'john'
|
50
|
-
Anyway.env.
|
54
|
+
Anyway.env.clear
|
51
55
|
expect(conf.port).to eq 80
|
52
56
|
expect(conf.user[:name]).to eq 'john'
|
53
57
|
end
|
58
|
+
|
59
|
+
it "handle ENV in YML thru ERB" do
|
60
|
+
ENV['ANYWAY_SECRET_PASSWORD'] = 'my_pass'
|
61
|
+
expect(conf.user[:password]).to eq 'my_pass'
|
62
|
+
end
|
54
63
|
end
|
55
64
|
|
56
65
|
describe "clear" do
|
57
66
|
let(:conf_cleared) { conf.clear }
|
58
67
|
|
59
|
-
|
68
|
+
it "nullifies values", :aggregate_failures do
|
60
69
|
expect(conf_cleared.meta).to be_nil
|
61
70
|
expect(conf_cleared.data).to be_nil
|
62
71
|
expect(conf_cleared.host).to be_nil
|
@@ -66,12 +75,11 @@ describe Anyway::Config do
|
|
66
75
|
end
|
67
76
|
|
68
77
|
describe "reload" do
|
69
|
-
after(:each) { Anyway.env.clear }
|
70
78
|
it do
|
71
79
|
expect(conf.port).to eq 8080
|
72
80
|
ENV['COOL_PORT'] = '80'
|
73
81
|
ENV['COOL_USER__NAME'] = 'john'
|
74
|
-
Anyway.env.
|
82
|
+
Anyway.env.clear
|
75
83
|
conf.reload
|
76
84
|
expect(conf.port).to eq 80
|
77
85
|
expect(conf.user[:name]).to eq 'john'
|
@@ -80,17 +88,20 @@ describe Anyway::Config do
|
|
80
88
|
end
|
81
89
|
|
82
90
|
describe "config for name" do
|
83
|
-
|
84
|
-
|
91
|
+
before(:each) do
|
92
|
+
ENV.delete_if { |var| var =~ /^myapp_/i }
|
93
|
+
end
|
94
|
+
|
95
|
+
it "load data by config name", :aggregate_failures do
|
85
96
|
ENV['MYAPP_TEST'] = '1'
|
86
97
|
ENV['MYAPP_NAME'] = 'my_app'
|
87
|
-
Anyway.env.
|
98
|
+
Anyway.env.clear
|
88
99
|
data = Anyway::Config.for(:my_app)
|
89
100
|
expect(data[:test]).to eq 1
|
90
101
|
expect(data[:name]).to eq 'my_app'
|
91
102
|
if Rails.application.respond_to?(:secrets)
|
92
|
-
expect(data[:secret]).to eq 'my_secret'
|
103
|
+
expect(data[:secret]).to eq 'my_secret'
|
93
104
|
end
|
94
105
|
end
|
95
106
|
end
|
96
|
-
end
|
107
|
+
end
|
data/spec/config_spec_norails.rb
CHANGED
@@ -1,43 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_norails_helper'
|
2
4
|
|
3
5
|
describe Anyway::Config do
|
4
|
-
|
5
6
|
let(:conf) { Anyway::TestConfig.new }
|
6
7
|
|
7
8
|
describe "config without Rails" do
|
8
|
-
|
9
|
+
before(:each) do
|
10
|
+
ENV.delete_if { |var| var =~ /^anyway_/i }
|
11
|
+
end
|
12
|
+
|
9
13
|
specify { expect(Anyway::TestConfig.config_name).to eq "anyway" }
|
10
14
|
|
11
|
-
|
15
|
+
it "has getters", :aggregate_failures do
|
12
16
|
expect(conf).to respond_to(:test)
|
13
17
|
expect(conf).to respond_to(:api)
|
18
|
+
expect(conf).to respond_to(:log)
|
19
|
+
expect(conf).to respond_to(:log_levels)
|
14
20
|
end
|
15
21
|
|
16
|
-
it "
|
17
|
-
ENV['ANYWAY_CONF'] = File.join(File.dirname(__FILE__),"anyway.yml")
|
22
|
+
it "works", :aggregate_failures do
|
23
|
+
ENV['ANYWAY_CONF'] = File.join(File.dirname(__FILE__), "anyway.yml")
|
18
24
|
ENV['ANYWAY_API__KEY'] = 'test1'
|
19
25
|
ENV['ANYWAY_TEST'] = 'test'
|
26
|
+
ENV['ANYWAY_LOG__FORMAT__COLOR'] = 't'
|
27
|
+
ENV['ANYWAY_LOG_LEVELS'] = 'debug,warning,info'
|
20
28
|
|
21
|
-
Anyway.env.
|
22
|
-
expect(conf.api[
|
23
|
-
expect(conf.api[
|
29
|
+
Anyway.env.clear
|
30
|
+
expect(conf.api['key']).to eq "test1"
|
31
|
+
expect(conf.api['endpoint']).to eq "localhost"
|
24
32
|
expect(conf.test).to eq "test"
|
33
|
+
expect(conf.log['format']['color']).to eq true
|
34
|
+
expect(conf.log_levels).to eq(%w[debug warning info])
|
25
35
|
end
|
26
36
|
|
27
|
-
it "
|
28
|
-
|
29
|
-
|
37
|
+
it "reloads config", :aggregate_failures do
|
38
|
+
ENV['ANYWAY_CONF'] = File.join(File.dirname(__FILE__), "anyway.yml")
|
39
|
+
|
40
|
+
expect(conf.api['key']).to eq ""
|
41
|
+
expect(conf.api['endpoint']).to eq 'localhost'
|
30
42
|
expect(conf.test).to be_nil
|
43
|
+
expect(conf.log['format']['color']).to eq false
|
31
44
|
|
32
|
-
ENV['ANYWAY_CONF'] = File.join(File.dirname(__FILE__),"anyway.yml")
|
33
45
|
ENV['ANYWAY_API__KEY'] = 'test1'
|
46
|
+
ENV['ANYWAY_API__SSL'] = 'yes'
|
34
47
|
ENV['ANYWAY_TEST'] = 'test'
|
35
|
-
|
48
|
+
ENV['ANYWAY_LOG__FORMAT__COLOR'] = 't'
|
49
|
+
Anyway.env.clear
|
36
50
|
|
37
51
|
conf.reload
|
38
|
-
expect(conf.api[
|
39
|
-
expect(conf.api[
|
52
|
+
expect(conf.api['key']).to eq "test1"
|
53
|
+
expect(conf.api['ssl']).to eq true
|
54
|
+
expect(conf.api['endpoint']).to eq "localhost"
|
40
55
|
expect(conf.test).to eq "test"
|
56
|
+
expect(conf.log['format']['color']).to eq true
|
57
|
+
end
|
58
|
+
|
59
|
+
context "config without keys" do
|
60
|
+
let(:empty_config_class) { Class.new(Anyway::Config) }
|
61
|
+
|
62
|
+
let(:conf) { empty_config_class.new }
|
63
|
+
|
64
|
+
specify { expect(conf.config_name).to be_nil }
|
65
|
+
end
|
66
|
+
|
67
|
+
context "loading from default path" do
|
68
|
+
let(:conf) { CoolConfig.new }
|
69
|
+
|
70
|
+
before(:each) do
|
71
|
+
ENV.delete_if { |var| var =~ /^cool_/i }
|
72
|
+
end
|
73
|
+
|
74
|
+
it "loads from ./config", :aggregate_failures do
|
75
|
+
expect(conf.user).to eq("name" => "root", "password" => "root")
|
76
|
+
expect(conf.host).to eq "test.host"
|
77
|
+
expect(conf.port).to eq 9292
|
78
|
+
end
|
79
|
+
|
80
|
+
it "handle ENV in YML thru ERB" do
|
81
|
+
ENV["ANYWAY_COOL_PORT"] = "1957"
|
82
|
+
expect(conf.port).to eq 1957
|
83
|
+
end
|
41
84
|
end
|
42
85
|
end
|
43
|
-
end
|
86
|
+
end
|
data/spec/dummy/config.ru
CHANGED
@@ -1,22 +1,13 @@
|
|
1
1
|
require File.expand_path('../boot', __FILE__)
|
2
2
|
|
3
|
-
require
|
3
|
+
require "rails"
|
4
4
|
|
5
5
|
Bundler.require(*Rails.groups)
|
6
6
|
|
7
7
|
module Dummy
|
8
8
|
class Application < Rails::Application
|
9
|
-
|
10
|
-
|
11
|
-
# -- all .rb files in that directory are automatically loaded.
|
12
|
-
|
13
|
-
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
|
14
|
-
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
|
15
|
-
# config.time_zone = 'Central Time (US & Canada)'
|
16
|
-
|
17
|
-
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
|
18
|
-
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
19
|
-
# config.i18n.default_locale = :de
|
9
|
+
config.logger = Logger.new('/dev/null')
|
10
|
+
config.eager_load = false
|
20
11
|
end
|
21
12
|
end
|
22
13
|
|
data/spec/dummy/config/cool.yml
CHANGED
@@ -1,39 +1,2 @@
|
|
1
1
|
Dummy::Application.configure do
|
2
|
-
# Settings specified here will take precedence over those in config/application.rb.
|
3
|
-
|
4
|
-
# The test environment is used exclusively to run your application's
|
5
|
-
# test suite. You never need to work with it otherwise. Remember that
|
6
|
-
# your test database is "scratch space" for the test suite and is wiped
|
7
|
-
# and recreated between test runs. Don't rely on the data there!
|
8
|
-
config.cache_classes = true
|
9
|
-
|
10
|
-
# Do not eager load code on boot. This avoids loading your whole application
|
11
|
-
# just for the purpose of running a single test. If you are using a tool that
|
12
|
-
# preloads Rails for running tests, you may have to set it to true.
|
13
|
-
config.eager_load = false
|
14
|
-
|
15
|
-
# Configure static asset server for tests with Cache-Control for performance.
|
16
|
-
config.serve_static_files = true
|
17
|
-
config.static_cache_control = 'public, max-age=3600'
|
18
|
-
|
19
|
-
# Show full error reports and disable caching.
|
20
|
-
config.consider_all_requests_local = true
|
21
|
-
config.action_controller.perform_caching = false
|
22
|
-
|
23
|
-
# Raise exceptions instead of rendering exception templates.
|
24
|
-
config.action_dispatch.show_exceptions = false
|
25
|
-
|
26
|
-
# Disable request forgery protection in test environment.
|
27
|
-
config.action_controller.allow_forgery_protection = false
|
28
|
-
|
29
|
-
# Tell Action Mailer not to deliver emails to the real world.
|
30
|
-
# The :test delivery method accumulates sent emails in the
|
31
|
-
# ActionMailer::Base.deliveries array.
|
32
|
-
config.action_mailer.delivery_method = :test
|
33
|
-
|
34
|
-
# Print deprecation notices to the stderr.
|
35
|
-
config.active_support.deprecation = :stderr
|
36
|
-
|
37
|
-
# Raises error for missing translations
|
38
|
-
# config.action_view.raise_on_missing_translations = true
|
39
2
|
end
|
data/spec/dummy/config/routes.rb
CHANGED
@@ -1,56 +1,2 @@
|
|
1
1
|
Dummy::Application.routes.draw do
|
2
|
-
# The priority is based upon order of creation: first created -> highest priority.
|
3
|
-
# See how all your routes lay out with "rake routes".
|
4
|
-
|
5
|
-
# You can have the root of your site routed with "root"
|
6
|
-
# root 'welcome#index'
|
7
|
-
|
8
|
-
# Example of regular route:
|
9
|
-
# get 'products/:id' => 'catalog#view'
|
10
|
-
|
11
|
-
# Example of named route that can be invoked with purchase_url(id: product.id)
|
12
|
-
# get 'products/:id/purchase' => 'catalog#purchase', as: :purchase
|
13
|
-
|
14
|
-
# Example resource route (maps HTTP verbs to controller actions automatically):
|
15
|
-
# resources :products
|
16
|
-
|
17
|
-
# Example resource route with options:
|
18
|
-
# resources :products do
|
19
|
-
# member do
|
20
|
-
# get 'short'
|
21
|
-
# post 'toggle'
|
22
|
-
# end
|
23
|
-
#
|
24
|
-
# collection do
|
25
|
-
# get 'sold'
|
26
|
-
# end
|
27
|
-
# end
|
28
|
-
|
29
|
-
# Example resource route with sub-resources:
|
30
|
-
# resources :products do
|
31
|
-
# resources :comments, :sales
|
32
|
-
# resource :seller
|
33
|
-
# end
|
34
|
-
|
35
|
-
# Example resource route with more complex sub-resources:
|
36
|
-
# resources :products do
|
37
|
-
# resources :comments
|
38
|
-
# resources :sales do
|
39
|
-
# get 'recent', on: :collection
|
40
|
-
# end
|
41
|
-
# end
|
42
|
-
|
43
|
-
# Example resource route with concerns:
|
44
|
-
# concern :toggleable do
|
45
|
-
# post 'toggle'
|
46
|
-
# end
|
47
|
-
# resources :posts, concerns: :toggleable
|
48
|
-
# resources :photos, concerns: :toggleable
|
49
|
-
|
50
|
-
# Example resource route within a namespace:
|
51
|
-
# namespace :admin do
|
52
|
-
# # Directs /admin/products/* to Admin::ProductsController
|
53
|
-
# # (app/controllers/admin/products_controller.rb)
|
54
|
-
# resources :products
|
55
|
-
# end
|
56
2
|
end
|
data/spec/env_spec.rb
CHANGED
@@ -1,32 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe Anyway::Env do
|
4
|
-
let(:env) { Anyway.env
|
6
|
+
let(:env) { Anyway.env }
|
5
7
|
|
6
|
-
it "
|
8
|
+
it "loads simple key/values by module", :aggregate_failures do
|
7
9
|
ENV['TESTO_KEY'] = 'a'
|
8
10
|
ENV['MYTEST_KEY'] = 'b'
|
9
|
-
expect(env.testo[
|
10
|
-
expect(env.my_test['key']).to eq 'b'
|
11
|
+
expect(env.fetch('testo')['key']).to eq 'a'
|
12
|
+
expect(env.fetch('my_test')['key']).to eq 'b'
|
11
13
|
end
|
12
14
|
|
13
|
-
it "
|
15
|
+
it "loads hash values", :aggregate_failures do
|
14
16
|
ENV['TESTO_DATA__ID'] = '1'
|
15
17
|
ENV['TESTO_DATA__META__NAME'] = 'meta'
|
16
18
|
ENV['TESTO_DATA__META__VAL'] = 'true'
|
17
|
-
|
18
|
-
expect(
|
19
|
-
expect(
|
19
|
+
testo_config = env.fetch('testo')
|
20
|
+
expect(testo_config['data']['id']).to eq 1
|
21
|
+
expect(testo_config['data']['meta']['name']).to eq 'meta'
|
22
|
+
expect(testo_config['data']['meta']['val']).to be_truthy
|
20
23
|
end
|
21
24
|
|
22
|
-
it "
|
25
|
+
it "loads array values", :aggregate_failures do
|
23
26
|
ENV['TESTO_DATA__IDS'] = '1,2, 3'
|
24
27
|
ENV['TESTO_DATA__META__NAMES'] = 'meta, kotleta'
|
25
28
|
ENV['TESTO_DATA__META__SIZE'] = '2'
|
26
29
|
ENV['TESTO_DATA__TEXT'] = '"C\'mon, everybody"'
|
27
|
-
|
28
|
-
expect(
|
29
|
-
expect(
|
30
|
-
expect(
|
30
|
+
testo_config = env.fetch('testo')
|
31
|
+
expect(testo_config['data']['ids']).to include(1, 2, 3)
|
32
|
+
expect(testo_config['data']['meta']['names']).to include('meta', 'kotleta')
|
33
|
+
expect(testo_config['data']['meta']['size']).to eq 2
|
34
|
+
expect(testo_config['data']['text']).to eq "C'mon, everybody"
|
31
35
|
end
|
32
|
-
end
|
36
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Anyway::Ext::DeepDup do
|
6
|
+
using Anyway::Ext::DeepDup
|
7
|
+
|
8
|
+
it "duplicates nested arrays and hashes", :aggregate_failures do
|
9
|
+
source = {
|
10
|
+
a: 1,
|
11
|
+
b: 'hello',
|
12
|
+
c: {
|
13
|
+
id: 1,
|
14
|
+
list: [1, 2, { name: 'John' }]
|
15
|
+
},
|
16
|
+
d: [{ id: 1 }, { id: 2 }]
|
17
|
+
}
|
18
|
+
|
19
|
+
dup = source.deep_dup
|
20
|
+
|
21
|
+
expect(dup[:a]).to eq 1
|
22
|
+
expect(dup[:b]).to eq 'hello'
|
23
|
+
expect(dup[:c]).to eq(
|
24
|
+
id: 1,
|
25
|
+
list: [1, 2, { name: 'John' }]
|
26
|
+
)
|
27
|
+
expect(dup[:d]).to eq(
|
28
|
+
[{ id: 1 }, { id: 2 }]
|
29
|
+
)
|
30
|
+
|
31
|
+
expect(dup[:c]).not_to be_equal(source[:c])
|
32
|
+
expect(dup[:c][:list]).not_to be_equal(source[:c][:list])
|
33
|
+
expect(dup[:c][:list].last).not_to be_equal(source[:c][:list].last)
|
34
|
+
|
35
|
+
expect(dup[:d].first).not_to be_equal(source[:d].first)
|
36
|
+
expect(dup[:d].last).not_to be_equal(source[:d].last)
|
37
|
+
end
|
38
|
+
end
|