cardiac 0.2.0.pre2

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.
Files changed (115) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +2 -0
  3. data/LICENSE +22 -0
  4. data/Rakefile +66 -0
  5. data/cardiac-0.2.0.pre2.gem +0 -0
  6. data/cardiac.gemspec +48 -0
  7. data/lib/cardiac/declarations.rb +70 -0
  8. data/lib/cardiac/errors.rb +65 -0
  9. data/lib/cardiac/log_subscriber.rb +55 -0
  10. data/lib/cardiac/model/attributes.rb +146 -0
  11. data/lib/cardiac/model/base.rb +161 -0
  12. data/lib/cardiac/model/callbacks.rb +47 -0
  13. data/lib/cardiac/model/declarations.rb +106 -0
  14. data/lib/cardiac/model/dirty.rb +117 -0
  15. data/lib/cardiac/model/locale/en.yml +7 -0
  16. data/lib/cardiac/model/operations.rb +49 -0
  17. data/lib/cardiac/model/persistence.rb +171 -0
  18. data/lib/cardiac/model/querying.rb +129 -0
  19. data/lib/cardiac/model/validations.rb +124 -0
  20. data/lib/cardiac/model.rb +17 -0
  21. data/lib/cardiac/operation_builder.rb +75 -0
  22. data/lib/cardiac/operation_handler.rb +215 -0
  23. data/lib/cardiac/railtie.rb +20 -0
  24. data/lib/cardiac/reflections.rb +85 -0
  25. data/lib/cardiac/representation.rb +124 -0
  26. data/lib/cardiac/resource/adapter.rb +178 -0
  27. data/lib/cardiac/resource/builder.rb +107 -0
  28. data/lib/cardiac/resource/codec_methods.rb +58 -0
  29. data/lib/cardiac/resource/config_methods.rb +39 -0
  30. data/lib/cardiac/resource/extension_methods.rb +115 -0
  31. data/lib/cardiac/resource/request_methods.rb +138 -0
  32. data/lib/cardiac/resource/subresource.rb +88 -0
  33. data/lib/cardiac/resource/uri_methods.rb +176 -0
  34. data/lib/cardiac/resource.rb +77 -0
  35. data/lib/cardiac/util.rb +120 -0
  36. data/lib/cardiac/version.rb +3 -0
  37. data/lib/cardiac.rb +61 -0
  38. data/spec/rails-3.2/Gemfile +9 -0
  39. data/spec/rails-3.2/Gemfile.lock +136 -0
  40. data/spec/rails-3.2/Rakefile +10 -0
  41. data/spec/rails-3.2/app_root/app/assets/javascripts/application.js +15 -0
  42. data/spec/rails-3.2/app_root/app/assets/stylesheets/application.css +13 -0
  43. data/spec/rails-3.2/app_root/app/controllers/application_controller.rb +3 -0
  44. data/spec/rails-3.2/app_root/app/helpers/application_helper.rb +2 -0
  45. data/spec/rails-3.2/app_root/app/views/layouts/application.html.erb +14 -0
  46. data/spec/rails-3.2/app_root/config/application.rb +29 -0
  47. data/spec/rails-3.2/app_root/config/boot.rb +13 -0
  48. data/spec/rails-3.2/app_root/config/database.yml +25 -0
  49. data/spec/rails-3.2/app_root/config/environment.rb +5 -0
  50. data/spec/rails-3.2/app_root/config/environments/development.rb +10 -0
  51. data/spec/rails-3.2/app_root/config/environments/production.rb +11 -0
  52. data/spec/rails-3.2/app_root/config/environments/test.rb +11 -0
  53. data/spec/rails-3.2/app_root/config/initializers/backtrace_silencers.rb +7 -0
  54. data/spec/rails-3.2/app_root/config/initializers/inflections.rb +15 -0
  55. data/spec/rails-3.2/app_root/config/initializers/mime_types.rb +5 -0
  56. data/spec/rails-3.2/app_root/config/initializers/secret_token.rb +7 -0
  57. data/spec/rails-3.2/app_root/config/initializers/session_store.rb +8 -0
  58. data/spec/rails-3.2/app_root/config/initializers/wrap_parameters.rb +14 -0
  59. data/spec/rails-3.2/app_root/config/locales/en.yml +5 -0
  60. data/spec/rails-3.2/app_root/config/routes.rb +2 -0
  61. data/spec/rails-3.2/app_root/db/test.sqlite3 +0 -0
  62. data/spec/rails-3.2/app_root/log/test.log +2403 -0
  63. data/spec/rails-3.2/app_root/public/404.html +26 -0
  64. data/spec/rails-3.2/app_root/public/422.html +26 -0
  65. data/spec/rails-3.2/app_root/public/500.html +25 -0
  66. data/spec/rails-3.2/app_root/public/favicon.ico +0 -0
  67. data/spec/rails-3.2/app_root/script/rails +6 -0
  68. data/spec/rails-3.2/spec/spec_helper.rb +25 -0
  69. data/spec/rails-4.0/Gemfile +9 -0
  70. data/spec/rails-4.0/Gemfile.lock +132 -0
  71. data/spec/rails-4.0/Rakefile +10 -0
  72. data/spec/rails-4.0/app_root/app/assets/javascripts/application.js +15 -0
  73. data/spec/rails-4.0/app_root/app/assets/stylesheets/application.css +13 -0
  74. data/spec/rails-4.0/app_root/app/controllers/application_controller.rb +3 -0
  75. data/spec/rails-4.0/app_root/app/helpers/application_helper.rb +2 -0
  76. data/spec/rails-4.0/app_root/app/views/layouts/application.html.erb +14 -0
  77. data/spec/rails-4.0/app_root/config/application.rb +28 -0
  78. data/spec/rails-4.0/app_root/config/boot.rb +13 -0
  79. data/spec/rails-4.0/app_root/config/database.yml +25 -0
  80. data/spec/rails-4.0/app_root/config/environment.rb +5 -0
  81. data/spec/rails-4.0/app_root/config/environments/development.rb +9 -0
  82. data/spec/rails-4.0/app_root/config/environments/production.rb +11 -0
  83. data/spec/rails-4.0/app_root/config/environments/test.rb +10 -0
  84. data/spec/rails-4.0/app_root/config/initializers/backtrace_silencers.rb +7 -0
  85. data/spec/rails-4.0/app_root/config/initializers/inflections.rb +15 -0
  86. data/spec/rails-4.0/app_root/config/initializers/mime_types.rb +5 -0
  87. data/spec/rails-4.0/app_root/config/initializers/secret_token.rb +7 -0
  88. data/spec/rails-4.0/app_root/config/initializers/session_store.rb +8 -0
  89. data/spec/rails-4.0/app_root/config/initializers/wrap_parameters.rb +14 -0
  90. data/spec/rails-4.0/app_root/config/locales/en.yml +5 -0
  91. data/spec/rails-4.0/app_root/config/routes.rb +2 -0
  92. data/spec/rails-4.0/app_root/db/test.sqlite3 +0 -0
  93. data/spec/rails-4.0/app_root/log/development.log +50 -0
  94. data/spec/rails-4.0/app_root/log/test.log +2399 -0
  95. data/spec/rails-4.0/app_root/public/404.html +26 -0
  96. data/spec/rails-4.0/app_root/public/422.html +26 -0
  97. data/spec/rails-4.0/app_root/public/500.html +25 -0
  98. data/spec/rails-4.0/app_root/public/favicon.ico +0 -0
  99. data/spec/rails-4.0/app_root/script/rails +6 -0
  100. data/spec/rails-4.0/spec/spec_helper.rb +25 -0
  101. data/spec/shared/cardiac/declarations_spec.rb +103 -0
  102. data/spec/shared/cardiac/model/base_spec.rb +446 -0
  103. data/spec/shared/cardiac/operation_builder_spec.rb +96 -0
  104. data/spec/shared/cardiac/operation_handler_spec.rb +82 -0
  105. data/spec/shared/cardiac/representation/reflection_spec.rb +73 -0
  106. data/spec/shared/cardiac/resource/adapter_spec.rb +83 -0
  107. data/spec/shared/cardiac/resource/builder_spec.rb +52 -0
  108. data/spec/shared/cardiac/resource/codec_methods_spec.rb +63 -0
  109. data/spec/shared/cardiac/resource/config_methods_spec.rb +52 -0
  110. data/spec/shared/cardiac/resource/extension_methods_spec.rb +215 -0
  111. data/spec/shared/cardiac/resource/request_methods_spec.rb +186 -0
  112. data/spec/shared/cardiac/resource/uri_methods_spec.rb +212 -0
  113. data/spec/shared/support/client_execution.rb +28 -0
  114. data/spec/spec_helper.rb +24 -0
  115. metadata +463 -0
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The page you were looking for doesn't exist (404)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/404.html -->
21
+ <div class="dialog">
22
+ <h1>The page you were looking for doesn't exist.</h1>
23
+ <p>You may have mistyped the address or the page may have moved.</p>
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/422.html -->
21
+ <div class="dialog">
22
+ <h1>The change you wanted was rejected.</h1>
23
+ <p>Maybe you tried to change something you didn't have access to.</p>
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1,25 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>We're sorry, but something went wrong (500)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/500.html -->
21
+ <div class="dialog">
22
+ <h1>We're sorry, but something went wrong.</h1>
23
+ </div>
24
+ </body>
25
+ </html>
File without changes
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
+
4
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
5
+ require File.expand_path('../../config/boot', __FILE__)
6
+ require 'rails/commands'
@@ -0,0 +1,25 @@
1
+ # For code shared by all dummy Rails apps.
2
+ $: << File.join(File.dirname(__FILE__), "/../../lib" )
3
+
4
+ ENV['RAILS_ENV'] = 'test'
5
+ ENV['RAILS_ROOT'] = 'app_root'
6
+
7
+ # Load the Rails environment and testing framework
8
+ require "#{File.dirname(__FILE__)}/../app_root/config/environment"
9
+ require 'rspec/rails'
10
+
11
+ # Load dependencies
12
+ # require 'has_defaults'
13
+
14
+ # Require support code
15
+ Dir["../shared/support/**/*.rb"].each {|f| require f}
16
+
17
+ # Run the migrations
18
+ #print "\033[30m" # dark gray text
19
+ ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate")
20
+ #print "\033[0m"
21
+
22
+ RSpec.configure do |config|
23
+ config.use_transactional_fixtures = true
24
+ config.use_instantiated_fixtures = false
25
+ end
@@ -0,0 +1,103 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cardiac::DeclarationMethods do
4
+ let!(:target) { double().extend(described_class) }
5
+
6
+ let! :foobar_extensions do
7
+ Proc.new do
8
+ https.path('/foo/bar').headers(content_type: 'application/octet-stream')
9
+
10
+ def foobar
11
+ path('/foobar').reset_headers
12
+ end
13
+ end
14
+ end
15
+
16
+ shared_examples 'a resource declaration' do |base,mock|
17
+ if mock.present?
18
+ let(:extensions) { send(:"#{mock}_extensions") }
19
+ end
20
+
21
+ subject { target.resource(base, &extensions) }
22
+
23
+ if Cardiac::Resource === base
24
+ it { is_expected.to be_a(Cardiac::Subresource) }
25
+ else
26
+ it { is_expected.to be_a(Cardiac::Resource) }
27
+ end
28
+ end
29
+
30
+ describe '#resource()' do
31
+ let(:default_headers) { {:accepts => Cardiac::RequestMethods::DEFAULT_ACCEPTS } }
32
+
33
+ it_behaves_like 'a resource declaration', 'http://localhost/', :foobar do
34
+ describe '#to_url' do
35
+ subject { super().to_url }
36
+ it { is_expected.to eq('https://localhost/foo/bar') }
37
+ end
38
+
39
+ describe '#build_headers' do
40
+ subject { super().send(:build_headers) }
41
+ it { is_expected.to eq(default_headers.merge(:content_type => 'application/octet-stream')) }
42
+ end
43
+
44
+ it { is_expected.not_to respond_to(:foobar) }
45
+
46
+ describe '#__extension_module__' do
47
+ subject { super().__extension_module__ }
48
+ it { is_expected.to be_method_defined(:foobar) }
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ describe Cardiac::Declarations do
55
+ let(:base) { 'http://example.com' }
56
+
57
+ shared_examples 'a declared resource' do |klass|
58
+ subject! { klass.tap{|x| x.send(:include,described_class) } }
59
+
60
+ before :example do
61
+ klass.resource(base) do
62
+ https.option(:timeout, 6)
63
+
64
+ def foobar
65
+ :barfoo
66
+ end
67
+ end
68
+ end
69
+
70
+ it { is_expected.to respond_to(:base_resource) }
71
+ it { is_expected.not_to be_method_defined(:base_resource) }
72
+
73
+ describe '#base_resource' do
74
+ subject { super().base_resource }
75
+ it { is_expected.to be_present }
76
+ end
77
+
78
+ describe '#base_resource' do
79
+ subject { super().base_resource }
80
+ describe '#to_url' do
81
+ subject { super().to_url }
82
+ it { is_expected.to eq('https://example.com/') }
83
+ end
84
+ end
85
+
86
+ describe '#base_resource' do
87
+ subject { super().base_resource }
88
+ describe '#options_values' do
89
+ subject { super().options_values }
90
+ it { is_expected.to eq([{timeout: 6}]) }
91
+ end
92
+ end
93
+ end
94
+
95
+ describe 'when mixed into a class' do
96
+ include_examples 'a declared resource', Class.new
97
+ end
98
+
99
+ describe 'when mixed into a module' do
100
+ include_examples 'a declared resource', Module.new
101
+ end
102
+
103
+ end
@@ -0,0 +1,446 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cardiac::Model::Base do
4
+
5
+ include_context 'Client responses'
6
+
7
+ let! :klass do
8
+ Class.new(Cardiac::Model::Base).class_eval do
9
+ self.base_resource = 'http://localhost/dummy'
10
+
11
+ attribute :id, type: Integer
12
+ attribute :name, type: String
13
+
14
+ def self.name; 'Dummy' end
15
+
16
+ self
17
+ end
18
+ end
19
+
20
+ subject { klass }
21
+
22
+ describe '#base_resource' do
23
+ subject { super().base_resource }
24
+ it { is_expected.to be_a(::Cardiac::Resource) }
25
+ end
26
+
27
+ describe '#base_resource' do
28
+ subject { super().base_resource }
29
+ describe '#to_url' do
30
+ subject { super().to_url }
31
+ it { is_expected.to eq('http://localhost/dummy') }
32
+ end
33
+ end
34
+
35
+ it { is_expected.to respond_to(:find_instances) }
36
+ it { is_expected.to respond_to(:create_instance) }
37
+ it { is_expected.to respond_to(:identify) }
38
+ it { is_expected.not_to respond_to(:find_instance) }
39
+ it { is_expected.not_to respond_to(:update_instance) }
40
+ it { is_expected.not_to respond_to(:delete_instance) }
41
+
42
+ shared_examples 'new records' do
43
+ it { is_expected.not_to be_persisted }
44
+ it { is_expected.to be_new_record }
45
+
46
+ describe '#id' do
47
+ subject { super().id }
48
+ it { is_expected.to be_nil }
49
+ end
50
+
51
+ describe '#to_key' do
52
+ subject { super().to_key }
53
+ it { is_expected.to be_nil }
54
+ end
55
+
56
+ describe '#to_param' do
57
+ subject { super().to_param }
58
+ it { is_expected.to be_nil }
59
+ end
60
+
61
+ describe '#remote_attributes' do
62
+ subject { super().remote_attributes }
63
+ it { is_expected.to be_empty }
64
+ end
65
+ end
66
+
67
+ shared_examples 'administering records' do
68
+ describe '#id' do
69
+ subject { super().id }
70
+ it { is_expected.to eq(1) }
71
+ end
72
+
73
+ describe '#to_key' do
74
+ subject { super().to_key }
75
+ it { is_expected.to eq([1]) }
76
+ end
77
+
78
+ describe '#name' do
79
+ subject { super().name }
80
+ it { is_expected.to eq('Jane Doe') }
81
+ end
82
+
83
+ describe '#remote_attributes' do
84
+ subject { super().remote_attributes }
85
+ it { is_expected.to eq('id' => 1, 'name' => 'John Doe') }
86
+ end
87
+
88
+ describe '#changed' do
89
+ subject { super().changed }
90
+ it { is_expected.to be_empty }
91
+ end
92
+ end
93
+
94
+ shared_examples 'read-only models prohibit modification' do
95
+ before(:each) { klass.readonly = true }
96
+ after(:each) { klass.readonly = false }
97
+ it('raises an error') { expect{ subject }.to raise_error }
98
+ end
99
+
100
+ shared_examples 'finding all instances' do
101
+
102
+ # Require that the class itself receives the operation call.
103
+ before(:each) { expect(klass).to receive(:find_instances).and_call_original }
104
+
105
+ describe 'when an Array is returned' do
106
+ let(:mock_index_success) { mock_response_klass.new("[ #{mock_success.body} ]", mock_success.code, mock_success.headers) }
107
+
108
+ # Mock the REST execution, using the :mock_success stubbed out response...
109
+ include_context 'Client execution', :get, :index_success
110
+
111
+ describe '#first' do
112
+ subject { super().first }
113
+ it { is_expected.to be_persisted }
114
+ end
115
+
116
+ describe '#first' do
117
+ subject { super().first }
118
+ it { is_expected.not_to be_new_record }
119
+ end
120
+
121
+ describe '#first' do
122
+ subject { super().first }
123
+ describe '#id' do
124
+ subject { super().id }
125
+ it { is_expected.to eq(1) }
126
+ end
127
+ end
128
+
129
+ describe '#first' do
130
+ subject { super().first }
131
+ describe '#to_key' do
132
+ subject { super().to_key }
133
+ it { is_expected.to eq([1]) }
134
+ end
135
+ end
136
+
137
+ describe '#first' do
138
+ subject { super().first }
139
+ describe '#to_param' do
140
+ subject { super().to_param }
141
+ it { is_expected.to eq('1') }
142
+ end
143
+ end
144
+
145
+ describe '#first' do
146
+ subject { super().first }
147
+ describe '#name' do
148
+ subject { super().name }
149
+ it { is_expected.to eq('John Doe') }
150
+ end
151
+ end
152
+
153
+ describe '#first' do
154
+ subject { super().first }
155
+ describe '#remote_attributes' do
156
+ subject { super().remote_attributes }
157
+ it { is_expected.to be_empty }
158
+ end
159
+ end
160
+
161
+ describe '#first' do
162
+ subject { super().first }
163
+ describe '#changed' do
164
+ subject { super().changed }
165
+ it { is_expected.to be_empty }
166
+ end
167
+ end
168
+ end
169
+
170
+ describe 'when an Array is not returned' do
171
+
172
+ # Mock the REST execution, using the :mock_success stubbed out response...
173
+ include_context 'Client execution', :get, :success
174
+
175
+ it 'should raise an exception' do
176
+ expect { subject.first }.to raise_error
177
+ end
178
+ end
179
+ end
180
+
181
+ describe '#identify' do
182
+ subject { klass.identify(1) }
183
+
184
+ it { is_expected.not_to respond_to(:find_instances) }
185
+ it { is_expected.not_to respond_to(:create_instance) }
186
+ it { is_expected.not_to respond_to(:identify) }
187
+ it { is_expected.to respond_to(:find_instance) }
188
+ it { is_expected.to respond_to(:update_instance) }
189
+ it { is_expected.to respond_to(:delete_instance) }
190
+ end
191
+
192
+ describe '#with_resource()' do
193
+ subject { klass.with_resource{|x| x.get } }
194
+
195
+ # Mock the REST execution, using the :mock_success stubbed out response...
196
+ include_context 'Client execution', :get, :success
197
+
198
+ it { is_expected.to be_a(Hash) }
199
+
200
+ describe "['segment']" do
201
+ subject { super()['segment'] }
202
+ it { is_expected.to eq({'id'=>1, 'name'=>'John Doe'}) }
203
+ end
204
+ end
205
+
206
+ describe '#new' do
207
+ subject { klass.new }
208
+
209
+ include_examples 'new records'
210
+
211
+ it { is_expected.not_to be_name_changed }
212
+
213
+ describe '#name' do
214
+ subject { super().name }
215
+ it { is_expected.to be_nil }
216
+ end
217
+
218
+ describe '#changed' do
219
+ subject { super().changed }
220
+ it { is_expected.to be_empty }
221
+ end
222
+
223
+ describe '(specifying initial attributes)' do
224
+ subject { klass.new(name: 'Jane Doe') }
225
+
226
+ include_examples 'new records'
227
+
228
+ it { is_expected.to be_name_changed }
229
+
230
+ describe '#name' do
231
+ subject { super().name }
232
+ it { is_expected.to eq('Jane Doe') }
233
+ end
234
+
235
+ describe '#changed' do
236
+ subject { super().changed }
237
+ it { is_expected.to eq(%w(name)) }
238
+ end
239
+ end
240
+
241
+ describe '(changing initial attributes)' do
242
+ subject { klass.new.tap{|r| r.name= 'Jane Doe'} }
243
+
244
+ include_examples 'new records'
245
+
246
+ it { is_expected.to be_name_changed }
247
+
248
+ describe '#name' do
249
+ subject { super().name }
250
+ it { is_expected.to eq('Jane Doe') }
251
+ end
252
+
253
+ describe '#changed' do
254
+ subject { super().changed }
255
+ it { is_expected.to eq(%w(name)) }
256
+ end
257
+ end
258
+ end
259
+
260
+ describe '#create' do
261
+ subject { klass.create }
262
+
263
+ context do
264
+ # Mock the REST execution, using the :mock_success stubbed out response...
265
+ include_context 'Client execution', :post, :success
266
+
267
+ it { is_expected.to be_persisted }
268
+ it { is_expected.not_to be_destroyed }
269
+ it { is_expected.not_to be_new_record }
270
+
271
+ describe '#id' do
272
+ subject { super().id }
273
+ it { is_expected.to eq(1) }
274
+ end
275
+
276
+ describe '#to_key' do
277
+ subject { super().to_key }
278
+ it { is_expected.to eq([1]) }
279
+ end
280
+
281
+ describe '#to_param' do
282
+ subject { super().to_param }
283
+ it { is_expected.to eq('1') }
284
+ end
285
+
286
+ describe '#name' do
287
+ subject { super().name }
288
+ it { is_expected.to be_nil }
289
+ end # remote attributes ignored by default on creation.
290
+
291
+ describe '#remote_attributes' do
292
+ subject { super().remote_attributes }
293
+ it { is_expected.not_to be_empty }
294
+ end
295
+
296
+ describe '#changed' do
297
+ subject { super().changed }
298
+ it { is_expected.to be_empty }
299
+ end
300
+
301
+ it 'should store the remote attributes' do
302
+ expect(subject.remote_attributes['id']).to eq(1)
303
+ expect(subject.remote_attributes[:name]).to eq('John Doe')
304
+ end
305
+ end
306
+
307
+ it_behaves_like 'read-only models prohibit modification'
308
+ end
309
+
310
+ describe '#find(id)' do
311
+ subject { klass.find(1) }
312
+
313
+ # Mock the REST execution, using the :mock_success stubbed out response...
314
+ include_context 'Client execution', :get, :success
315
+
316
+ it { is_expected.to be_persisted }
317
+ it { is_expected.not_to be_new_record }
318
+
319
+ describe '#id' do
320
+ subject { super().id }
321
+ it { is_expected.to eq(1) }
322
+ end
323
+
324
+ describe '#to_key' do
325
+ subject { super().to_key }
326
+ it { is_expected.to eq([1]) }
327
+ end
328
+
329
+ describe '#to_param' do
330
+ subject { super().to_param }
331
+ it { is_expected.to eq('1') }
332
+ end
333
+
334
+ describe '#name' do
335
+ subject { super().name }
336
+ it { is_expected.to eq('John Doe') }
337
+ end
338
+
339
+ describe '#remote_attributes' do
340
+ subject { super().remote_attributes }
341
+ it { is_expected.to be_empty }
342
+ end
343
+
344
+ describe '#changed' do
345
+ subject { super().changed }
346
+ it { is_expected.to be_empty }
347
+ end
348
+ end
349
+
350
+ describe '#find(:all)' do
351
+ include_examples 'finding all instances' do
352
+ subject { klass.find(:all) }
353
+ end
354
+ end
355
+
356
+ describe '#all' do
357
+ include_examples 'finding all instances' do
358
+ subject { klass.all }
359
+ end
360
+ end
361
+
362
+ describe '#reload' do
363
+ subject { klass.send(:instantiate, id: 1, name: 'Johnny Doe').tap{|r| r.name = 'Jane Doe' }.reload }
364
+
365
+ # Mock the REST execution, using the :mock_success stubbed out response...
366
+ include_context 'Client execution', :get, :success
367
+
368
+ it { is_expected.to be_persisted }
369
+ it { is_expected.not_to be_destroyed }
370
+ it { is_expected.not_to be_new_record }
371
+
372
+ describe '#id' do
373
+ subject { super().id }
374
+ it { is_expected.to eq(1) }
375
+ end
376
+
377
+ describe '#to_key' do
378
+ subject { super().to_key }
379
+ it { is_expected.to eq([1]) }
380
+ end
381
+
382
+ describe '#to_param' do
383
+ subject { super().to_param }
384
+ it { is_expected.to eq('1') }
385
+ end
386
+
387
+ describe '#name' do
388
+ subject { super().name }
389
+ it { is_expected.to eq('John Doe') }
390
+ end
391
+
392
+ describe '#remote_attributes' do
393
+ subject { super().remote_attributes }
394
+ it { is_expected.to be_empty }
395
+ end
396
+
397
+ describe '#changed' do
398
+ subject { super().changed }
399
+ it { is_expected.to be_empty }
400
+ end
401
+ end
402
+
403
+ describe '#update' do
404
+ subject { klass.send(:instantiate, id: 1, name: 'John Doe').tap{|r| r.update(name: 'Jane Doe') } }
405
+
406
+ context do
407
+ # Mock the REST execution, using the :mock_success stubbed out response...
408
+ include_context 'Client execution', :put, :success
409
+ include_context 'administering records'
410
+
411
+ it { is_expected.to be_persisted }
412
+ it { is_expected.not_to be_destroyed }
413
+ it { is_expected.not_to be_new_record }
414
+ it { is_expected.not_to be_name_changed }
415
+
416
+ describe '#to_param' do
417
+ subject { super().to_param }
418
+ it { is_expected.to eq('1') }
419
+ end
420
+ end
421
+
422
+ it_behaves_like 'read-only models prohibit modification'
423
+ end
424
+
425
+ describe '#delete' do
426
+ subject { klass.send(:instantiate, id: 1, name: 'Jane Doe').tap(&:destroy) }
427
+
428
+ context do
429
+ # Mock the REST execution, using the :mock_success stubbed out response...
430
+ include_context 'Client execution', :delete, :success
431
+ include_context 'administering records'
432
+
433
+ it { is_expected.to be_destroyed }
434
+ it { is_expected.not_to be_new_record }
435
+ it { is_expected.not_to be_name_changed }
436
+ it { is_expected.not_to be_name_changed }
437
+
438
+ describe '#to_param' do
439
+ subject { super().to_param }
440
+ it { is_expected.to be_nil }
441
+ end
442
+ end
443
+
444
+ it_behaves_like 'read-only models prohibit modification'
445
+ end
446
+ end