encore 0.0.3 → 0.1
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 +4 -4
- data/.gitignore +0 -16
- data/.rubocop.yml +53 -0
- data/.travis.yml +10 -2
- data/LICENSE.md +1 -1
- data/README.md +105 -153
- data/Rakefile +10 -0
- data/encore.gemspec +16 -13
- data/gemfiles/{Gemfile.activerecord-3.2.x → Gemfile.activerecord-4.1} +1 -1
- data/lib/encore/config.rb +2 -0
- data/lib/encore/persister/errors_parser.rb +17 -0
- data/lib/encore/persister/instance.rb +85 -0
- data/lib/encore/persister/key_mapping.rb +15 -0
- data/lib/encore/persister/links_parser.rb +57 -0
- data/lib/encore/persister/param_injection.rb +15 -0
- data/lib/encore/serializer/base.rb +48 -0
- data/lib/encore/serializer/eager_loading_manager.rb +11 -0
- data/lib/encore/serializer/instance.rb +56 -0
- data/lib/encore/serializer/linked_resource_manager.rb +19 -0
- data/lib/encore/serializer/links_reflection_includer.rb +50 -0
- data/lib/encore/serializer/main_resource_links_manager/reflection_belongs_to.rb +13 -0
- data/lib/encore/serializer/main_resource_links_manager/reflection_has_many.rb +13 -0
- data/lib/encore/serializer/main_resource_links_manager/reflection_has_one.rb +13 -0
- data/lib/encore/serializer/main_resource_links_manager.rb +45 -0
- data/lib/encore/serializer/main_resource_manager.rb +13 -0
- data/lib/encore/serializer/meta_manager.rb +29 -0
- data/lib/encore/serializer/options_parser.rb +51 -0
- data/lib/encore/serializer/utils.rb +12 -0
- data/lib/encore/version.rb +1 -1
- data/lib/encore.rb +16 -8
- data/spec/encore/persister/belongs_to_links_spec.rb +46 -0
- data/spec/encore/persister/create_resources_spec.rb +55 -0
- data/spec/encore/persister/errors_resources_spec.rb +55 -0
- data/spec/encore/persister/has_many_links_spec.rb +49 -0
- data/spec/encore/persister/has_one_links_spec.rb +49 -0
- data/spec/encore/persister/key_mappings_spec.rb +66 -0
- data/spec/encore/persister/param_injection_spec.rb +46 -0
- data/spec/encore/persister/update_resources_spec.rb +37 -0
- data/spec/encore/serializer/linked/always_include_resources_spec.rb +85 -0
- data/spec/encore/serializer/linked/can_include_resources_spec.rb +69 -0
- data/spec/encore/serializer/linked/linked_resources_spec.rb +103 -0
- data/spec/encore/serializer/links_resource_spec.rb +294 -0
- data/spec/encore/serializer/main_meta_spec.rb +66 -0
- data/spec/encore/serializer/main_resource_spec.rb +37 -0
- data/spec/encore/serializer/no_paging_spec.rb +40 -0
- data/spec/encore_spec.rb +4 -0
- data/spec/spec_helper.rb +8 -21
- data/spec/support/macros/database/database_adapter.rb +9 -0
- data/spec/support/macros/database/sqlite3_adapter.rb +14 -0
- data/spec/support/macros/database_macros.rb +5 -16
- data/spec/support/macros/model_macros.rb +7 -22
- metadata +143 -72
- data/lib/encore/association/has_many_association.rb +0 -12
- data/lib/encore/association/has_one_association.rb +0 -12
- data/lib/encore/association.rb +0 -39
- data/lib/encore/attribute.rb +0 -42
- data/lib/encore/entity/input/associations.rb +0 -27
- data/lib/encore/entity/input/errors.rb +0 -8
- data/lib/encore/entity/input/exposed_attributes.rb +0 -37
- data/lib/encore/entity/input.rb +0 -73
- data/lib/encore/entity/output/json.rb +0 -14
- data/lib/encore/entity/output.rb +0 -13
- data/lib/encore/entity.rb +0 -44
- data/lib/encore/helpers/controller_helper.rb +0 -37
- data/lib/encore/helpers.rb +0 -1
- data/lib/encore/railtie.rb +0 -11
- data/spec/encore/entity/input/associations_spec.rb +0 -48
- data/spec/encore/entity/input/exposed_attributes_spec.rb +0 -46
- data/spec/encore/entity/input_spec.rb +0 -104
- data/spec/encore/entity/output/json_spec.rb +0 -76
- data/spec/encore/entity/output_spec.rb +0 -5
- data/spec/encore/entity_spec.rb +0 -31
- data/spec/encore/helpers/controller_helper_spec.rb +0 -59
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 58e8c5a2cb80f79ec4fdf6afec91a6d67dd1108c
|
4
|
+
data.tar.gz: f45565ef1a3ae7732237728783146b8a008d4f8e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd79df1408e83a0792e7723c47fd0d7466140492ca7f10ce36e95902c3e42b992472aa96e27021e07ed9724290ab828983055e9119f79cf7b8caf4be49e2ef79
|
7
|
+
data.tar.gz: 44b77c571699964d6b3c0b5b6593d660a9e62eac44bc2d9de8e3be72315a57a7fb264a39fd83fc94151171493e53d06be94271241254049c8a5cc68e85441a7a
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
AllCops:
|
2
|
+
Include:
|
3
|
+
- encore.gemspec
|
4
|
+
|
5
|
+
Documentation:
|
6
|
+
Enabled: false
|
7
|
+
|
8
|
+
Encoding:
|
9
|
+
Enabled: false
|
10
|
+
|
11
|
+
LineLength:
|
12
|
+
Max: 200
|
13
|
+
|
14
|
+
ClassLength:
|
15
|
+
Max: 200
|
16
|
+
|
17
|
+
AccessModifierIndentation:
|
18
|
+
EnforcedStyle: outdent
|
19
|
+
|
20
|
+
IfUnlessModifier:
|
21
|
+
Enabled: false
|
22
|
+
|
23
|
+
CaseIndentation:
|
24
|
+
IndentWhenRelativeTo: case
|
25
|
+
IndentOneStep: true
|
26
|
+
|
27
|
+
MethodLength:
|
28
|
+
CountComments: false
|
29
|
+
Max: 20
|
30
|
+
|
31
|
+
SignalException:
|
32
|
+
Enabled: false
|
33
|
+
|
34
|
+
ColonMethodCall:
|
35
|
+
Enabled: false
|
36
|
+
|
37
|
+
AsciiComments:
|
38
|
+
Enabled: false
|
39
|
+
|
40
|
+
Lambda:
|
41
|
+
Enabled: false
|
42
|
+
|
43
|
+
RegexpLiteral:
|
44
|
+
Enabled: false
|
45
|
+
|
46
|
+
AssignmentInCondition:
|
47
|
+
Enabled: false
|
48
|
+
|
49
|
+
ClassAndModuleChildren:
|
50
|
+
Enabled: false
|
51
|
+
|
52
|
+
GuardClause:
|
53
|
+
Enabled: false
|
data/.travis.yml
CHANGED
@@ -1,11 +1,19 @@
|
|
1
1
|
language: ruby
|
2
2
|
|
3
3
|
rvm:
|
4
|
+
- 2.1.1
|
4
5
|
- 2.0.0
|
5
|
-
- 1.9.3
|
6
6
|
|
7
7
|
gemfile:
|
8
8
|
- gemfiles/Gemfile.activerecord-4.0
|
9
|
-
- gemfiles/Gemfile.activerecord-
|
9
|
+
- gemfiles/Gemfile.activerecord-4.1
|
10
10
|
|
11
11
|
script: "echo 'DO IT' && bundle exec rake spec"
|
12
|
+
|
13
|
+
notifications:
|
14
|
+
hipchat:
|
15
|
+
rooms:
|
16
|
+
secure: "lLUK7HuJzZiae6dSB35I/ZlTI8guiRteImGQBhj1DKe533HPGZQHnhwAdML2YY6nLzhfw1uaXHNgGDCLTkylHK2ChLROHZicoX6mCLPqspwkB2GCx4K+1neltReeOIIi5ZIg2fz6wAV9rdSSaIBpIUg1717nhbOCP3ouIf0j3X0="
|
17
|
+
template:
|
18
|
+
- '%{repository}#%{build_number} (%{branch} - %{commit} : %{author}): %{message} (<a href="%{build_url}">Build</a>/<a href="%{compare_url}">Changes</a>)'
|
19
|
+
format: 'html'
|
data/LICENSE.md
CHANGED
data/README.md
CHANGED
@@ -3,15 +3,10 @@
|
|
3
3
|
<img src="http://i.imgur.com/erXBozp.png" alt="Encore" />
|
4
4
|
</a>
|
5
5
|
<br />
|
6
|
-
Encore
|
6
|
+
Encore provides serializers and persisters to build <a href="http://jsonapi.org">JSON API</a>-compliant Web services with Ruby on Rails.
|
7
7
|
<br /><br />
|
8
|
-
<a href="https://rubygems.org/gems/encore"><img src="https://badge.fury.io/rb/encore.png" /></a>
|
9
|
-
<a href="https://codeclimate.com/github/mirego/encore"><img src="https://codeclimate.com/github/mirego/encore.png" /></a>
|
10
|
-
<a href="https://travis-ci.org/mirego/encore"><img src="https://travis-ci.org/mirego/encore.png?branch=master" /></a>
|
11
8
|
</p>
|
12
9
|
|
13
|
-
---
|
14
|
-
|
15
10
|
## Installation
|
16
11
|
|
17
12
|
Add this line to your application's Gemfile:
|
@@ -32,196 +27,153 @@ Or install it yourself as:
|
|
32
27
|
$ gem install encore
|
33
28
|
```
|
34
29
|
|
35
|
-
##
|
36
|
-
|
37
|
-
Let’s say we have the `UserEntity` entity class bound to the `User` model:
|
30
|
+
## Disclaimer
|
38
31
|
|
39
|
-
|
40
|
-
class User < ActiveRecord::Base
|
41
|
-
end
|
32
|
+
Encore is under heavy development at the moment, do not use this gem in production unless you know exactly what you're doing. **Breaking changes** are still being committed.
|
42
33
|
|
43
|
-
|
44
|
-
include Encore::Entity
|
45
|
-
|
46
|
-
expose :name
|
47
|
-
expose :email
|
48
|
-
expose :created_at, readonly: true
|
49
|
-
expose :updated_at, readonly: true
|
50
|
-
end
|
51
|
-
```
|
34
|
+
## Basic serializer usage
|
52
35
|
|
53
|
-
|
36
|
+
### Configure your serializer
|
54
37
|
|
55
38
|
```ruby
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
new_attributes = { email: 'remi+new@example.com' }
|
67
|
-
@entity.assign_attributes new_attributes
|
68
|
-
@entity.object.email # => "remi+new@example.com"
|
69
|
-
@entity.object.name # => "Rémi Prévost"
|
70
|
-
```
|
71
|
-
|
72
|
-
However, with the `:update` context, Encore will assign new attributes and set all non-provided exposed attributes to `nil`. This
|
73
|
-
makes sense in a `PUT` HTTP request context.
|
74
|
-
|
75
|
-
```ruby
|
76
|
-
new_attributes = { email: 'remi+new-again@example.com' }
|
77
|
-
@entity.assign_attributes new_attributes, context: :update
|
78
|
-
@entity.object.email # => "remi+new-again@example.com"
|
79
|
-
@entity.object.name # => nil
|
80
|
-
```
|
81
|
-
|
82
|
-
If we try to assign a value to a non-exposed or readonly attribute, Encore will raise an error.
|
83
|
-
|
84
|
-
```ruby
|
85
|
-
@entity.assign_attributes email: 'remi+new@example.com', created_at: Time.now
|
86
|
-
# => raises #<Encore::Entity::Input::InvalidAttributeError: The #<Encore::Attribute UserEntity@created_at> attribute is not exposed.>
|
39
|
+
class CommentSerializer < Encore::Serializer::Base
|
40
|
+
attributes :id, :body, :links
|
41
|
+
|
42
|
+
# By default, root_key will be the pluralized model
|
43
|
+
# name. If you want to set a custom root_key, you can
|
44
|
+
# do that:
|
45
|
+
def self.root_key
|
46
|
+
:user_comments
|
47
|
+
end
|
48
|
+
end
|
87
49
|
```
|
88
50
|
|
89
|
-
|
51
|
+
The `links` attribute is generated by Encore and will return the included associations. Read more in the [Inclusion](#inclusion) section.
|
90
52
|
|
91
|
-
|
53
|
+
### Returning serialized model
|
92
54
|
|
93
55
|
```ruby
|
94
|
-
class
|
95
|
-
|
96
|
-
end
|
56
|
+
class CommentsController < ApplicationController
|
57
|
+
before_action :fetch_comments, only: %i(index)
|
97
58
|
|
98
|
-
|
99
|
-
|
100
|
-
end
|
59
|
+
def index
|
60
|
+
render json: Encore::Serializer::Instance.new(@comments)
|
61
|
+
end
|
101
62
|
|
102
|
-
|
103
|
-
include Encore::Entity
|
63
|
+
protected
|
104
64
|
|
105
|
-
|
106
|
-
|
65
|
+
def fetch_comments
|
66
|
+
@comments = Comment.all
|
67
|
+
end
|
107
68
|
end
|
108
69
|
```
|
109
70
|
|
110
|
-
|
111
|
-
|
112
|
-
```
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
71
|
+
Will result in the following JSON output:
|
72
|
+
|
73
|
+
```json
|
74
|
+
{
|
75
|
+
"comments": [
|
76
|
+
{
|
77
|
+
"id": "1",
|
78
|
+
"body": "First!",
|
79
|
+
"links": {}
|
80
|
+
}
|
81
|
+
],
|
82
|
+
"links": {},
|
83
|
+
"linked": {},
|
84
|
+
"meta": {
|
85
|
+
"comments": {
|
86
|
+
"page": 1,
|
87
|
+
"count": 1,
|
88
|
+
"page_count": 1,
|
89
|
+
"previous_page": null,
|
90
|
+
"next_page": null
|
91
|
+
}
|
92
|
+
}
|
117
93
|
```
|
118
94
|
|
119
|
-
|
120
|
-
|
121
|
-
```ruby
|
122
|
-
@entity.save
|
123
|
-
@entity.object.organization_id # => 2
|
124
|
-
```
|
95
|
+
### Inclusion
|
125
96
|
|
126
|
-
|
127
|
-
|
128
|
-
_This is work-in-progress. There’s still missing stuff._
|
129
|
-
|
130
|
-
### Model
|
97
|
+
Encore can handle model associations. For example, let's include the `author` in the code sample above.
|
131
98
|
|
132
99
|
```ruby
|
133
|
-
|
134
|
-
class User < ActiveRecord::Base
|
135
|
-
end
|
100
|
+
Encore::Serializer::Instance.new(@comments, include: 'author')
|
136
101
|
```
|
137
102
|
|
138
|
-
|
103
|
+
Since we don't want all associations to be exposed, we also need to allow the serializer to include the association. To do so, we need to update the `CommentSerializer`.
|
139
104
|
|
140
105
|
```ruby
|
141
|
-
|
142
|
-
|
143
|
-
include Encore::Entity
|
144
|
-
|
145
|
-
expose :name
|
146
|
-
expose :email
|
147
|
-
expose :created_at, readonly: true
|
148
|
-
expose :updated_at, readonly: true
|
149
|
-
end
|
150
|
-
```
|
151
|
-
|
152
|
-
### Routes
|
106
|
+
class CommentSerializer < Encore::Serializer::Base
|
107
|
+
# ...
|
153
108
|
|
154
|
-
|
155
|
-
|
156
|
-
Rails::Application.routes.draw do
|
157
|
-
resources :users do
|
158
|
-
# This makes Rails route PUT and PATCH requests to two separate actions
|
159
|
-
patch on: :member, action: :partial_update
|
109
|
+
def self.can_include
|
110
|
+
[:author]
|
160
111
|
end
|
161
112
|
end
|
162
113
|
```
|
163
114
|
|
164
|
-
|
165
|
-
|
166
|
-
```
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
115
|
+
This will result in the following JSON output:
|
116
|
+
|
117
|
+
```json
|
118
|
+
{
|
119
|
+
"comments": [
|
120
|
+
{
|
121
|
+
"id": "1",
|
122
|
+
"body": "First!",
|
123
|
+
"links": {
|
124
|
+
"author": "1"
|
125
|
+
}
|
126
|
+
}
|
127
|
+
],
|
128
|
+
"links": {
|
129
|
+
"comments.author": {
|
130
|
+
"href": "/authors?ids={author.id}",
|
131
|
+
"type": "user"
|
132
|
+
}
|
133
|
+
},
|
134
|
+
"linked": {
|
135
|
+
"authors": [
|
136
|
+
{
|
137
|
+
"id": "1",
|
138
|
+
"name": "John Doe"
|
139
|
+
}
|
140
|
+
]
|
141
|
+
},
|
142
|
+
"meta": {
|
143
|
+
"comments": {
|
144
|
+
"page": 1,
|
145
|
+
"count": 1,
|
146
|
+
"page_count": 1,
|
147
|
+
"previous_page": null,
|
148
|
+
"next_page": null
|
149
|
+
}
|
150
|
+
}
|
151
|
+
```
|
199
152
|
|
200
|
-
|
201
|
-
end
|
153
|
+
If you want the `author` the **always** be included when you request a `comment`, update the `CommentSerializer` this way:
|
202
154
|
|
203
|
-
|
155
|
+
```ruby
|
156
|
+
class CommentSerializer < Encore::Serializer::Base
|
157
|
+
attributes :id, :body, :links
|
204
158
|
|
205
|
-
def
|
206
|
-
|
159
|
+
def self.always_include
|
160
|
+
[:author]
|
207
161
|
end
|
208
162
|
end
|
209
163
|
```
|
210
164
|
|
211
|
-
|
165
|
+
### Pagination
|
212
166
|
|
213
|
-
|
214
|
-
This is something we’ve been wanting to build for a long time and now we’re finally taking the time
|
215
|
-
do it right.
|
167
|
+
Lot more work to do here :)
|
216
168
|
|
217
169
|
## License
|
218
170
|
|
219
|
-
`Encore` is © 2013 [Mirego](http://www.mirego.com) and may be freely distributed under the [New BSD license](http://opensource.org/licenses/BSD-3-Clause). See the [`LICENSE.md`](https://github.com/mirego/encore/blob/master/LICENSE.md) file.
|
171
|
+
`Encore` is © 2013-2014 [Mirego](http://www.mirego.com) and may be freely distributed under the [New BSD license](http://opensource.org/licenses/BSD-3-Clause). See the [`LICENSE.md`](https://github.com/mirego/encore/blob/master/LICENSE.md) file.
|
220
172
|
|
221
|
-
The
|
173
|
+
The hazelnut logo is based on [this lovely icon](http://thenounproject.com/term/hazelnuts/3618/) by [Alessandro Suraci](http://thenounproject.com/alessandro.suraci/), from The Noun Project. Used under a [Creative Commons BY 3.0](http://creativecommons.org/licenses/by/3.0/) license.
|
222
174
|
|
223
175
|
## About Mirego
|
224
176
|
|
225
|
-
Mirego is a team of passionate people who believe that work is a place where you can innovate and have fun. We
|
177
|
+
[Mirego](http://mirego.com) is a team of passionate people who believe that work is a place where you can innovate and have fun. We're a team of [talented people](http://life.mirego.com) who imagine and build beautiful Web and mobile applications. We come together to share ideas and [change the world](http://mirego.org).
|
226
178
|
|
227
|
-
We also love
|
179
|
+
We also [love open-source software](http://open.mirego.com) and we try to give back to the community as much as we can.
|
data/Rakefile
CHANGED
@@ -9,3 +9,13 @@ desc 'Run all specs'
|
|
9
9
|
RSpec::Core::RakeTask.new(:spec) do |task|
|
10
10
|
task.pattern = 'spec/**/*_spec.rb'
|
11
11
|
end
|
12
|
+
|
13
|
+
desc 'Start an IRB session with the gem'
|
14
|
+
task :console do
|
15
|
+
$:.unshift File.expand_path('..', __FILE__)
|
16
|
+
require 'encore'
|
17
|
+
require 'irb'
|
18
|
+
|
19
|
+
ARGV.clear
|
20
|
+
IRB.start
|
21
|
+
end
|
data/encore.gemspec
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# coding: utf-8
|
2
|
+
|
2
3
|
lib = File.expand_path('../lib', __FILE__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'encore/version'
|
@@ -6,23 +7,25 @@ require 'encore/version'
|
|
6
7
|
Gem::Specification.new do |spec|
|
7
8
|
spec.name = 'encore'
|
8
9
|
spec.version = Encore::VERSION
|
9
|
-
spec.authors = ['
|
10
|
-
spec.email = ['
|
11
|
-
spec.description = 'Encore
|
10
|
+
spec.authors = ['Simon Prévost']
|
11
|
+
spec.email = ['sprevost@mirego.com']
|
12
|
+
spec.description = 'Encore provides serializers and persisters to build JSON API-compliant Web services with Ruby on Rails.'
|
12
13
|
spec.summary = spec.description
|
13
14
|
spec.homepage = 'https://github.com/mirego/encore'
|
14
|
-
spec.license =
|
15
|
+
spec.license = 'BSD 3-Clause'
|
15
16
|
|
16
|
-
spec.files = `git ls-files`.split(
|
17
|
-
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
-
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
17
|
+
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
19
18
|
spec.require_paths = ['lib']
|
20
19
|
|
21
|
-
spec.
|
22
|
-
spec.
|
23
|
-
spec.
|
24
|
-
spec.
|
25
|
-
spec.add_development_dependency 'rails', '>= 3.0.0'
|
20
|
+
spec.add_dependency 'activemodel', '>= 4.0.0'
|
21
|
+
spec.add_dependency 'activerecord', '>= 4.0.0'
|
22
|
+
spec.add_dependency 'active_model_serializers', '~> 0.8.0'
|
23
|
+
spec.add_dependency 'kaminari', '~> 0.15.1'
|
26
24
|
|
27
|
-
spec.
|
25
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
26
|
+
spec.add_development_dependency 'rake', '~> 10.3'
|
27
|
+
spec.add_development_dependency 'rspec', '3.0.0beta2'
|
28
|
+
spec.add_development_dependency 'sqlite3', '>= 1.3.8', '< 1.4'
|
29
|
+
spec.add_development_dependency 'rubocop', '0.22'
|
30
|
+
spec.add_development_dependency 'phare'
|
28
31
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Encore
|
2
|
+
module Persister
|
3
|
+
module ErrorsParser
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
def parse_errors(record, index)
|
7
|
+
record.errors.messages.map do |field, values|
|
8
|
+
{
|
9
|
+
field: field.to_s,
|
10
|
+
types: values,
|
11
|
+
path: "#{record.class.name.underscore}/#{index}/#{field}"
|
12
|
+
}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'encore/persister/param_injection'
|
2
|
+
require 'encore/persister/errors_parser'
|
3
|
+
require 'encore/persister/key_mapping'
|
4
|
+
require 'encore/persister/links_parser'
|
5
|
+
|
6
|
+
module Encore
|
7
|
+
module Persister
|
8
|
+
class Instance
|
9
|
+
include LinksParser
|
10
|
+
include ErrorsParser
|
11
|
+
|
12
|
+
attr_reader :errors
|
13
|
+
|
14
|
+
def initialize(model, payload, options = {})
|
15
|
+
@model = model
|
16
|
+
@payload = payload
|
17
|
+
@options = options
|
18
|
+
@errors = []
|
19
|
+
@ids = Set.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def persist!
|
23
|
+
@model.transaction do
|
24
|
+
procces_payload!(action)
|
25
|
+
|
26
|
+
if @errors.any? || @ids.empty?
|
27
|
+
raise ActiveRecord::Rollback
|
28
|
+
end
|
29
|
+
|
30
|
+
true
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def active_records
|
35
|
+
active_record_class.where(id: @ids.to_a.compact)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def procces_payload!(action)
|
41
|
+
payload = key_mapping(@payload)
|
42
|
+
payload = param_injection(payload)
|
43
|
+
|
44
|
+
payload.each_with_index do |args, i|
|
45
|
+
args = parse_links(args)
|
46
|
+
record = send("#{action}_record", args)
|
47
|
+
|
48
|
+
next unless record.present?
|
49
|
+
|
50
|
+
@ids += fetch_id(record)
|
51
|
+
@errors += parse_errors(record, i)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def active_record_class
|
56
|
+
@model.is_a?(Class) ? @model : @model.class
|
57
|
+
end
|
58
|
+
|
59
|
+
def action
|
60
|
+
@model.is_a?(Class) ? :create : :update
|
61
|
+
end
|
62
|
+
|
63
|
+
def create_record(args)
|
64
|
+
@model.create args
|
65
|
+
end
|
66
|
+
|
67
|
+
def update_record(args)
|
68
|
+
@model.update_attributes(args)
|
69
|
+
@model
|
70
|
+
end
|
71
|
+
|
72
|
+
def fetch_id(record)
|
73
|
+
[record.id]
|
74
|
+
end
|
75
|
+
|
76
|
+
def key_mapping(payload)
|
77
|
+
@model.active_model_serializer ? KeyMapping.map_keys(payload, @model.active_model_serializer) : payload
|
78
|
+
end
|
79
|
+
|
80
|
+
def param_injection(payload)
|
81
|
+
ParamInjection.inject(payload, @options[:inject_params])
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Encore
|
2
|
+
module Persister
|
3
|
+
module KeyMapping
|
4
|
+
def self.map_keys(array_params, serializer)
|
5
|
+
array_params.map do |params|
|
6
|
+
mappings = serializer.key_mappings
|
7
|
+
|
8
|
+
params.keys.each { |k| params[mappings[k]] = params.delete(k) if mappings[k] }
|
9
|
+
|
10
|
+
params
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|