encore 0.0.3 → 0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|