smooth_operator 1.3.0 → 1.8.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.
- checksums.yaml +8 -8
- data/Gemfile +0 -5
- data/README.md +11 -308
- data/console.rb +3 -28
- data/lib/smooth_operator.rb +7 -75
- data/lib/smooth_operator/array_with_meta_data.rb +21 -20
- data/lib/smooth_operator/attribute_assignment.rb +53 -57
- data/lib/smooth_operator/delegation.rb +34 -15
- data/lib/smooth_operator/finder_methods.rb +17 -33
- data/lib/smooth_operator/helpers.rb +7 -37
- data/lib/smooth_operator/internal_attribute.rb +49 -0
- data/lib/smooth_operator/model_schema.rb +72 -0
- data/lib/smooth_operator/open_struct.rb +4 -7
- data/lib/smooth_operator/operator.rb +64 -102
- data/lib/smooth_operator/persistence.rb +64 -94
- data/lib/smooth_operator/remote_call.rb +70 -0
- data/lib/smooth_operator/serialization.rb +33 -89
- data/lib/smooth_operator/translation.rb +13 -26
- data/lib/smooth_operator/type_converter.rb +69 -0
- data/lib/smooth_operator/validations.rb +3 -25
- data/lib/smooth_operator/version.rb +1 -1
- data/smooth_operator.gemspec +5 -9
- data/spec/factories/user_factory.rb +4 -5
- data/spec/smooth_operator/attribute_assignment_spec.rb +11 -145
- data/spec/smooth_operator/delegation_spec.rb +54 -57
- data/spec/smooth_operator/finder_methods_spec.rb +2 -91
- data/spec/smooth_operator/{resource_name_spec.rb → model_schema_spec.rb} +2 -2
- data/spec/smooth_operator/operator_spec.rb +1 -1
- data/spec/smooth_operator/persistence_spec.rb +20 -140
- data/spec/smooth_operator/serialization_spec.rb +4 -28
- data/spec/spec_helper.rb +9 -7
- data/spec/support/models/address.rb +0 -9
- data/spec/support/models/post.rb +3 -9
- data/spec/support/models/user.rb +7 -30
- data/spec/support/models/user_with_address_and_posts.rb +12 -20
- data/spec/support/test_server.rb +7 -63
- metadata +18 -55
- data/lib/smooth_operator/associations.rb +0 -110
- data/lib/smooth_operator/associations/association_reflection.rb +0 -79
- data/lib/smooth_operator/associations/has_many_relation.rb +0 -45
- data/lib/smooth_operator/associations/reflection.rb +0 -41
- data/lib/smooth_operator/cookie_jar.rb +0 -21
- data/lib/smooth_operator/http_methods.rb +0 -17
- data/lib/smooth_operator/internal_data.rb +0 -45
- data/lib/smooth_operator/operators/connection_wrapper.rb +0 -15
- data/lib/smooth_operator/operators/faraday.rb +0 -75
- data/lib/smooth_operator/operators/typhoeus.rb +0 -87
- data/lib/smooth_operator/options.rb +0 -30
- data/lib/smooth_operator/remote_call/base.rb +0 -76
- data/lib/smooth_operator/remote_call/errors/connection_failed.rb +0 -20
- data/lib/smooth_operator/remote_call/errors/timeout.rb +0 -20
- data/lib/smooth_operator/remote_call/faraday.rb +0 -19
- data/lib/smooth_operator/remote_call/typhoeus.rb +0 -19
- data/lib/smooth_operator/resource_name.rb +0 -46
- data/lib/smooth_operator/schema.rb +0 -21
- data/lib/smooth_operator/type_casting.rb +0 -127
- data/spec/require_helper.rb +0 -11
- data/spec/smooth_operator/remote_call_spec.rb +0 -340
- data/spec/smooth_operator/validations_spec.rb +0 -42
- data/spec/support/models/comment.rb +0 -5
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MjU3NWQ2OTMyMjE4ODBjZGMzZWJmMmRlMzcxZDBmMWZjYmU5YjYwOQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
Y2E5MDEyYmYxODcwNmQ4MzY2MWFlMmViYTQ3Y2QxN2FlOWU2ZTJiOA==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NzlmOGZhNzVhYTVkOTE0YTI4OGZkMjhjNDlkYWE1NWEzZmE0YmIzY2RmMGVk
|
10
|
+
NzcyYTlmY2ZhZmNmZmU4MzIyOWY4ZjU2MmFlYTU4ZjRmNzI2OTczYmM3MGNi
|
11
|
+
ZDUyMGZkOGYwZDBkZThmNTE5ZTQxMTkxN2JjZWRiYTFlNzg4Nzk=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
YWI0YjkzNDVmN2JhMmY0MzYxMmE4NGQ1ZDAxMDM1NzZkYThiZjZhMmYxZmE2
|
14
|
+
NzIzYTQ5MzA0NDg4NzE5ZmM2ODgzOTFmYjkwNzMxYjZiMTdmZjRjZDUzYjM4
|
15
|
+
YzQzZTc3NzJkM2I2OGM5MzFhYTQ0NDc5MWU1MGI0NmE0MzkzNGM=
|
data/Gemfile
CHANGED
@@ -3,15 +3,10 @@ source 'https://rubygems.org'
|
|
3
3
|
# Specify your gem's dependencies in smooth_operator.gemspec
|
4
4
|
gemspec
|
5
5
|
|
6
|
-
gem 'simplecov', :require => false, :group => :test
|
7
|
-
|
8
6
|
group :development, :test do
|
9
7
|
gem "pry"
|
10
8
|
gem "sinatra"
|
11
|
-
gem "typhoeus"
|
12
|
-
gem "activesupport"
|
13
9
|
gem "sinatra-contrib"
|
14
10
|
gem "rspec", "~> 3.0.0.beta1"
|
15
11
|
gem "factory_girl", "~> 4.0"
|
16
|
-
gem "ethon", :git => 'https://github.com/goncalvesjoao/ethon'
|
17
12
|
end
|
data/README.md
CHANGED
@@ -1,23 +1,14 @@
|
|
1
|
-
# SmoothOperator
|
1
|
+
# SmoothOperator
|
2
2
|
|
3
3
|
Ruby gem, that mimics the ActiveRecord behaviour but through external API's.
|
4
4
|
It's a lightweight and flexible alternative to ActiveResource, that responds to a REST API like you expect it too.
|
5
5
|
|
6
|
-
|
6
|
+
Depends only on Faraday gem, no need for ActiveSupport or any other Active* gem.
|
7
7
|
|
8
|
-
|
8
|
+
Although if I18n is present it will respond to .human_attribute_name method and if ActiveModel is present it will make use of 'ActiveModel::Name' to improve .model_name method.
|
9
9
|
|
10
|
-
This micro-services example will also feature other cool stuff like:
|
11
|
-
- parallel requests;
|
12
|
-
- using HTTP PATCH verb for saving instead of PUT;
|
13
|
-
- form errors with simple_form gem;
|
14
|
-
- nested objects using cocoon gem;
|
15
|
-
- endless-pagination with kaminari gem
|
16
|
-
- and others...
|
17
10
|
|
18
|
-
|
19
|
-
|
20
|
-
## 1) Installation
|
11
|
+
## Installation
|
21
12
|
|
22
13
|
Add this line to your application's Gemfile:
|
23
14
|
|
@@ -31,303 +22,15 @@ Or install it yourself as:
|
|
31
22
|
|
32
23
|
$ gem install smooth_operator
|
33
24
|
|
34
|
-
---
|
35
|
-
|
36
|
-
## 2) Usage and Examples
|
37
|
-
|
38
|
-
```ruby
|
39
|
-
class MyBlogResource < SmoothOperator::Base
|
40
|
-
|
41
|
-
# HTTP BASIC AUTH
|
42
|
-
options endpoint_user: 'admin',
|
43
|
-
endpoint_pass: 'admin',
|
44
|
-
endpoint: 'http://myblog.com/api/v0'
|
45
|
-
|
46
|
-
# OR
|
47
|
-
# smooth_operator_options
|
48
|
-
end
|
49
|
-
|
50
|
-
class Post < MyBlogResource
|
51
|
-
end
|
52
|
-
```
|
53
|
-
|
54
|
-
---
|
55
|
-
|
56
|
-
### 2.1) Creating a .new 'Post' and #save it
|
57
|
-
|
58
|
-
```ruby
|
59
|
-
post = Post.new(body: 'my first post', author: 'John Doe')
|
60
|
-
|
61
|
-
post.new_record? # true
|
62
|
-
post.persisted? # false
|
63
|
-
post.body # 'my first post'
|
64
|
-
post.author # 'John Doe'
|
65
|
-
post.something_else # will raise NoMethodError
|
66
|
-
|
67
|
-
save_result = post.save # will make a http POST call to 'http://myblog.com/api/v0/posts'
|
68
|
-
# with `{ post: { body: 'my first post', author: 'John Doe' } }`
|
69
|
-
|
70
|
-
post.last_remote_call # will contain a SmoothOperator::RemoteCall instance containing relevant information about the save remote call.
|
71
|
-
|
72
|
-
# If the server response is positive (http code between 200 and 299):
|
73
|
-
save_result # true
|
74
|
-
post.new_record? # false
|
75
|
-
post.persisted? # true
|
76
|
-
# server response contains { id: 1 } on its body
|
77
|
-
post.id # 1
|
78
|
-
|
79
|
-
# If the server response is negative (http code between 400 and 499):
|
80
|
-
save_result # false
|
81
|
-
post.new_record? # true
|
82
|
-
post.persisted? # false
|
83
|
-
# server response contains { errors: { body: ['must be less then 10 letters'] } }
|
84
|
-
post.errors.body # Array
|
85
|
-
|
86
|
-
# If the server response is an error (http code between 500 and 599), or the connection was broke:
|
87
|
-
save_result # nil
|
88
|
-
post.new_record? # true
|
89
|
-
post.persisted? # false
|
90
|
-
# server response contains { errors: { body: ['must be less then 10 letters'] } }
|
91
|
-
post.errors # will raise NoMethodError
|
92
|
-
|
93
|
-
# In the positive and negative server response comes with a json,
|
94
|
-
# e.g. { id: 1 }, post will reflect that new data
|
95
|
-
post.id # 1
|
96
|
-
|
97
|
-
# In case of error and the server response contains a json,
|
98
|
-
# e.g. { id: 1 }, post will NOT reflect that data
|
99
|
-
post.id # raise NoMethodError
|
100
|
-
|
101
|
-
```
|
102
|
-
|
103
|
-
---
|
104
|
-
|
105
|
-
### 2.2) Editing an existing record
|
106
|
-
```ruby
|
107
|
-
post = Post.find(2)
|
108
|
-
|
109
|
-
post.body = 'editing my second page'
|
110
|
-
|
111
|
-
post.save
|
112
|
-
```
|
113
|
-
|
114
|
-
---
|
115
|
-
|
116
|
-
### 2.3) Customize #save 'url', 'params' and 'options'
|
117
|
-
```ruby
|
118
|
-
post = Post.new(id: 2, body: 'editing my second page')
|
119
|
-
|
120
|
-
post.new_record? # false
|
121
|
-
post.persisted? # true
|
122
|
-
|
123
|
-
post.save("save_and_add_to_list", { admin: true, post: { author: 'Agent Smith', list_id: 1 } }, { timeout: 1 })
|
124
|
-
# Will make a PUT to 'http://myblog.com/api/v0/posts/2/save_and_add_to_list'
|
125
|
-
# with { admin: true, post: { body: 'editing my second page', list_id: 1 } }
|
126
|
-
# and will only wait 1sec for the server to respond.
|
127
|
-
|
128
|
-
post.save('/#{post.id}/save_and_add_to_list')
|
129
|
-
# Will make a PUT to 'http://myblog.com/api/v0/posts/2/save_and_add_to_list'
|
130
|
-
|
131
|
-
post.save('/save_and_add_to_list')
|
132
|
-
# Will make a PUT to 'http://myblog.com/api/v0/posts/save_and_add_to_list'
|
133
|
-
```
|
134
|
-
|
135
|
-
---
|
136
|
-
|
137
|
-
### 2.4) Saving using HTTP Patch verb
|
138
|
-
```ruby
|
139
|
-
class Page < MyBlogResource
|
140
|
-
options update_http_verb: 'patch'
|
141
|
-
# OR
|
142
|
-
#smooth_operator_options update_http_verb: 'patch'
|
143
|
-
end
|
144
|
-
|
145
|
-
page = Page.find(2)
|
146
|
-
|
147
|
-
page.body = 'editing my second page'
|
148
|
-
|
149
|
-
page.save # will make a http PATCH call to 'http://myblog.com/api/v0/pages/2'
|
150
|
-
# with `{ page: { body: 'editing my second page' } }`
|
151
|
-
```
|
152
|
-
|
153
|
-
---
|
154
|
-
|
155
|
-
### 2.5) Retrieving remote objects - 'index' REST action
|
156
|
-
|
157
|
-
```ruby
|
158
|
-
remote_call = Page.find(:all) # Will make a GET call to 'http://myblog.com/api/v0/pages'
|
159
|
-
# and will return a SmoothOperator::RemoteCall instance
|
160
|
-
|
161
|
-
pages = remote_call.data
|
162
|
-
|
163
|
-
# If the server response is positive (http code between 200 and 299, or 304):
|
164
|
-
remote_call.ok? # true
|
165
|
-
remote_call.not_processed? # false
|
166
|
-
remote_call.error? # false
|
167
|
-
remote_call.status # true
|
168
|
-
pages = remote_call.data # array of Page instances
|
169
|
-
remote_call.http_status # server_response code
|
170
|
-
|
171
|
-
# If the server response is unprocessed entity (http code 422):
|
172
|
-
remote_call.ok? # false
|
173
|
-
remote_call.not_processed? # true
|
174
|
-
remote_call.error? # false
|
175
|
-
remote_call.status # false
|
176
|
-
remote_call.http_status # server_response code
|
177
|
-
|
178
|
-
# If the server response is client error (http code between 400..499, except 422):
|
179
|
-
remote_call.ok? # false
|
180
|
-
remote_call.not_processed? # false
|
181
|
-
remote_call.error? # true
|
182
|
-
remote_call.status # nil
|
183
|
-
remote_call.http_status # server_response code
|
184
|
-
|
185
|
-
# If the server response is server error (http code between 500 and 599), or the connection broke:
|
186
|
-
remote_call.ok? # false
|
187
|
-
remote_call.not_processed? # false
|
188
|
-
remote_call.error? # true
|
189
|
-
remote_call.status # nil
|
190
|
-
remote_call.http_status # server_response code or 0 if connection broke
|
191
|
-
```
|
192
|
-
|
193
|
-
---
|
194
|
-
|
195
|
-
### 2.6) Retrieving remote objects - 'show' REST action
|
196
|
-
|
197
|
-
```ruby
|
198
|
-
remote_call = Page.find(2) # Will make a GET call to 'http://myblog.com/api/v0/pages/2'
|
199
|
-
# and will return a SmoothOperator::RemoteCall instance
|
200
|
-
|
201
|
-
service_down = remote_call.error?
|
202
|
-
|
203
|
-
page = remote_call.data
|
204
|
-
```
|
205
|
-
|
206
|
-
---
|
207
|
-
|
208
|
-
### 2.7) Retrieving remote objects - custom query
|
209
|
-
```ruby
|
210
|
-
remote_call = Page.find('my_pages', { q: body_contains: 'link' }, { endpoint_user: 'admin', endpoint_pass: 'new_password' })
|
211
|
-
# will make a GET call to 'http://myblog.com/api/v0/pages/my_pages?q={body_contains="link"}'
|
212
|
-
# and will change the HTTP BASIC AUTH credentials to user: 'admin' and pass: 'new_password' for this connection only.
|
213
|
-
|
214
|
-
@service_down = remote_call.error?
|
215
|
-
|
216
|
-
# If the server json response is an Array [{ id: 1 }, { id: 2 }]
|
217
|
-
@pages = remote.data # will return an array with 2 Page's instances
|
218
|
-
@pages[0].id # 1
|
219
|
-
@pages[1].id # 2
|
220
|
-
|
221
|
-
# If the server json response is a Hash { id: 3 }
|
222
|
-
@page = remote.data # will return a single Page instance
|
223
|
-
@page.id # 3
|
224
|
-
|
225
|
-
# If the server json response is Hash with a key called 'pages' { current_page: 1, total_pages: 3, limit_value: 10, pages: [{ id: 4 }, { id: 5 }] }
|
226
|
-
@pages = remote.data # will return a single ArrayWithMetaData instance, that will allow you to access to both the Page's instances array and the metadata.
|
227
|
-
|
228
|
-
# @pages is now a valid object to work with kaminari
|
229
|
-
@pages.total_pages # 3
|
230
|
-
@pages.current_page # 1
|
231
|
-
@pages.limit_value # 10
|
232
|
-
|
233
|
-
@pages[0].id # 4
|
234
|
-
@pages[1].id # 5
|
235
|
-
```
|
236
|
-
|
237
|
-
### 2.8) Keeping your session alive - custom HTTP Headers
|
238
|
-
|
239
|
-
Controllers
|
240
|
-
ApplicationController
|
241
|
-
```ruby
|
242
|
-
```
|
243
|
-
|
244
|
-
Models
|
245
|
-
SmoothResource
|
246
|
-
```ruby
|
247
|
-
class SmoothResource < SmoothOperator::Rails
|
248
|
-
|
249
|
-
options headers: :custom_headers
|
250
|
-
|
251
|
-
def self.custom_headers
|
252
|
-
{
|
253
|
-
cookie: current_user.blog_cookie,
|
254
|
-
"X_CSRF_TOKEN" => current_user.blog_auth_token
|
255
|
-
}
|
256
|
-
end
|
257
|
-
|
258
|
-
protected ############## PROTECTED #################
|
259
|
-
|
260
|
-
def self.current_user
|
261
|
-
User.current_user
|
262
|
-
end
|
263
|
-
|
264
|
-
end
|
265
|
-
```
|
266
|
-
|
267
|
-
---
|
268
|
-
|
269
|
-
## 3) Methods
|
270
|
-
|
271
|
-
---
|
272
|
-
|
273
|
-
### 3.1) Persistence methods
|
274
|
-
|
275
|
-
Methods | Behaviour | Arguments | Return
|
276
|
-
------- | --------- | ------ | ---------
|
277
|
-
.create | Generates a new instance of the class with *attributes and calls #save with the rest of its arguments| Hash attributes = nil, String relative_path = nil, Hash data = {}, Hash options = {} | Class instance
|
278
|
-
#new_record? | Returns @new_record if defined, else populates it with true if #id is present or false if blank. | - | Boolean
|
279
|
-
#destroyed?| Returns @destroyed if defined, else populates it with false. | - | Boolean
|
280
|
-
#persisted?| Returns true if both #new_record? and #destroyed? return false, else returns false. | - | Boolean
|
281
|
-
#save | if #new_record? makes a HTTP POST, else a PUT call. If !#new_record? and relative_path is blank, sets relative_path = id.to_s. If the server POST response is positive, sets @new_record = false. See 4.2) for more behaviour info. | String relative_path = nil, Hash data = {}, Hash options = {} | Boolean or Nil
|
282
|
-
#save! | Executes the same behaviour as #save, but will raise RecordNotSaved if the returning value is not true | String relative_path = nil, Hash data = {}, Hash options = {} | Boolean or Nil
|
283
|
-
#destroy | Does nothing if !persisted? else makes a HTTP DELETE call. If server response it positive, sets @destroyed = true. If relative_path is blank, sets relative_path = id.to_s. See 4.2) for more behaviour info. | String relative_path = nil, Hash data = {}, Hash options = {} | Boolean or Nil
|
284
|
-
|
285
|
-
---
|
286
|
-
|
287
|
-
### 3.2) Finder methods
|
288
|
-
|
289
|
-
Methods | Behaviour | Arguments | Return
|
290
|
-
------- | --------- | ------ | ---------
|
291
|
-
.find | If relative_path == :all, sets relative_path = ''. Makes a Get call and initiates Class objects with the server's response data. See 4.3) and 4.4) for more behaviour info. | String relative_path, Hash data = {}, Hash options = {} | Class instance, Array of Class instances or an ArrayWithMetaData instance
|
292
|
-
|
293
|
-
---
|
294
|
-
|
295
|
-
### 3.3) Operator methods
|
296
|
-
...
|
297
|
-
|
298
|
-
---
|
299
|
-
|
300
|
-
### 3.3) Remote call methods
|
301
|
-
...
|
302
|
-
|
303
|
-
---
|
304
|
-
|
305
|
-
## 4) Behaviours
|
306
|
-
|
307
|
-
---
|
308
|
-
|
309
|
-
### 4.1) Delegation behaviour
|
310
|
-
...
|
311
|
-
|
312
|
-
---
|
313
|
-
|
314
|
-
### 4.2) Persistent operator behaviour
|
315
|
-
...
|
316
|
-
|
317
|
-
---
|
318
|
-
|
319
|
-
### 4.3) Operator behaviour
|
320
|
-
...
|
321
25
|
|
322
|
-
|
26
|
+
## Usage
|
323
27
|
|
324
|
-
|
325
|
-
...
|
28
|
+
TODO: Write usage instructions here
|
326
29
|
|
327
|
-
---
|
328
30
|
|
329
|
-
##
|
31
|
+
## TODO
|
330
32
|
|
331
|
-
1.
|
332
|
-
2.
|
333
|
-
3.
|
33
|
+
1. FinderMethods specs
|
34
|
+
2. serialization_specs to test the json options for nested classes
|
35
|
+
3. model_schema_specs
|
36
|
+
4. Cache
|
data/console.rb
CHANGED
@@ -3,34 +3,9 @@
|
|
3
3
|
$LOAD_PATH << './'
|
4
4
|
$LOAD_PATH << './lib'
|
5
5
|
|
6
|
-
require
|
6
|
+
require "spec/spec_helper"
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
LocalhostServer.new(TestServer.new, 4567)
|
11
|
-
|
12
|
-
# user = nil
|
13
|
-
|
14
|
-
# hydra = Typhoeus::Hydra::hydra
|
15
|
-
|
16
|
-
# user = User::Base.new(id: 1)
|
17
|
-
# user.reload(nil, nil, { hydra: hydra })
|
18
|
-
|
19
|
-
# User::Base.find(1, nil, { hydra: hydra }) do |remote_call|
|
20
|
-
# user = remote_call.data
|
21
|
-
# end
|
22
|
-
|
23
|
-
#User::Base.post('', { user: { age: 1, posts: [{ body: 'post1' }, 2] } })
|
24
|
-
|
25
|
-
#user = UserWithAddressAndPosts::Son.new(FactoryGirl.attributes_for(:user_with_address_and_posts))
|
26
|
-
#user.save('', { status: 200 })
|
27
|
-
|
28
|
-
# "[{\"patient_id\"=>33, \"messages\"=>[{\"id\"=>\"53722c20cb38247c36000003\", \"title\"=>\"Joao Goncalves\", \"created_at\"=>\"2014-05-13T14:28:48Z\"}, {\"id\"=>\"53722bfccb382485d5000002\", \"title\"=>\"Joao Goncalves\", \"created_at\"=>\"2014-05-13T14:28:12Z\"}, {\"id\"=>\"53722b91cb3824e913000001\", \"title\"=>\"Joao Goncalves\", \"created_at\"=>\"2014-05-13T14:26:25Z\"}]}]"
|
29
|
-
|
30
|
-
post = Post.new(comments: [{ id: 1, name: '1' }, { id: 2, name: '2' }], address: { id: 1, name: 'address' })
|
31
|
-
|
32
|
-
comments_attributes = { "0" => { id: 1, name: '3' }, "1" => { name: '4' } }
|
33
|
-
|
34
|
-
comments_with_errors = { "0" => { id: 1, name: '3', errors: { body: ["can't be blank"] } }, "1" => { name: '4', errors: { body: ["can't be blank"] } } }
|
8
|
+
#User.post('', { user: { age: 1, posts: [{ body: 'post1' }, 2] } })
|
35
9
|
|
36
10
|
binding.pry
|
11
|
+
|
data/lib/smooth_operator.rb
CHANGED
@@ -1,94 +1,26 @@
|
|
1
|
-
require
|
1
|
+
# require 'active_model'
|
2
|
+
|
2
3
|
require "smooth_operator/version"
|
3
4
|
require "smooth_operator/helpers"
|
4
5
|
require "smooth_operator/operator"
|
6
|
+
require "smooth_operator/remote_call"
|
5
7
|
require "smooth_operator/persistence"
|
6
8
|
require "smooth_operator/translation"
|
7
9
|
require "smooth_operator/open_struct"
|
8
|
-
require "smooth_operator/http_methods"
|
9
|
-
require "smooth_operator/associations"
|
10
10
|
require "smooth_operator/finder_methods"
|
11
11
|
|
12
12
|
module SmoothOperator
|
13
|
+
|
13
14
|
class Base < OpenStruct
|
14
15
|
|
15
|
-
extend
|
16
|
-
extend HttpMethods
|
17
|
-
extend Associations
|
16
|
+
extend Operator
|
18
17
|
extend FinderMethods
|
19
18
|
extend Translation if defined? I18n
|
20
19
|
|
21
|
-
include Operator
|
22
|
-
include HttpMethods
|
23
20
|
include Persistence
|
24
|
-
include FinderMethods
|
25
|
-
|
26
|
-
options strict_behaviour: true
|
27
|
-
|
28
|
-
def self.smooth_operator?
|
29
|
-
true
|
30
|
-
end
|
31
|
-
|
32
|
-
end
|
33
|
-
|
34
|
-
if defined?(ActiveModel)
|
35
|
-
class Rails < Base
|
36
|
-
|
37
|
-
include ActiveModel::Validations
|
38
|
-
include ActiveModel::Validations::Callbacks
|
39
|
-
include ActiveModel::Conversion
|
40
|
-
|
41
|
-
options unknown_hash_class: SmoothOperator::OpenStruct
|
42
|
-
|
43
|
-
validate :validate_induced_errors, :validate_nested_objects
|
44
|
-
|
45
|
-
def column_for_attribute(attribute_name)
|
46
|
-
type = self.class.attribute_type(attribute_name)
|
47
|
-
|
48
|
-
ActiveRecord::ConnectionAdapters::Column.new(attribute_name.to_sym, type, type)
|
49
|
-
end
|
50
|
-
|
51
|
-
def save(relative_path = nil, data = {}, options = {})
|
52
|
-
return false unless before_save
|
53
|
-
|
54
|
-
clear_induced_errors
|
55
|
-
|
56
|
-
save_result = valid? ? super : false
|
57
|
-
|
58
|
-
after_save if valid? && save_result
|
59
|
-
|
60
|
-
save_result
|
61
|
-
end
|
62
|
-
|
63
|
-
def before_save
|
64
|
-
true
|
65
|
-
end
|
66
|
-
|
67
|
-
def after_save; end
|
68
|
-
|
69
|
-
def self.model_name
|
70
|
-
smooth_model_name
|
71
|
-
end
|
72
|
-
|
73
|
-
protected ################# PROTECTED ###################
|
74
|
-
|
75
|
-
def validate_induced_errors
|
76
|
-
induced_errors.each do |key, value|
|
77
|
-
[*value].each do |_value|
|
78
|
-
self.errors.add(key, _value) unless self.errors.added?(key, _value)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
Helpers.blank?(induced_errors)
|
83
|
-
end
|
84
|
-
|
85
|
-
def validate_nested_objects
|
86
|
-
all_nested_objects = self.class.reflections.keys
|
87
|
-
.map { |association| send(association) }.flatten.compact
|
88
21
|
|
89
|
-
|
90
|
-
end
|
22
|
+
attr_reader :last_remote_call
|
91
23
|
|
92
|
-
end
|
93
24
|
end
|
25
|
+
|
94
26
|
end
|