simple_ams 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +6 -0
- data/README.md +224 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/simple_ams/adapters/ams.rb +85 -0
- data/lib/simple_ams/adapters.rb +2 -0
- data/lib/simple_ams/document/fields.rb +66 -0
- data/lib/simple_ams/document/links.rb +61 -0
- data/lib/simple_ams/document/metas.rb +15 -0
- data/lib/simple_ams/document/relations.rb +95 -0
- data/lib/simple_ams/document.rb +93 -0
- data/lib/simple_ams/dsl.rb +216 -0
- data/lib/simple_ams/methy.rb +10 -0
- data/lib/simple_ams/options/adapter.rb +9 -0
- data/lib/simple_ams/options/concerns/filterable.rb +45 -0
- data/lib/simple_ams/options/concerns/name_value_hash.rb +32 -0
- data/lib/simple_ams/options/concerns/value_hash.rb +23 -0
- data/lib/simple_ams/options/fields.rb +7 -0
- data/lib/simple_ams/options/includes.rb +7 -0
- data/lib/simple_ams/options/links.rb +11 -0
- data/lib/simple_ams/options/metas.rb +12 -0
- data/lib/simple_ams/options/primary_id.rb +7 -0
- data/lib/simple_ams/options/relation.rb +31 -0
- data/lib/simple_ams/options/type.rb +8 -0
- data/lib/simple_ams/options.rb +299 -0
- data/lib/simple_ams/renderer.rb +59 -0
- data/lib/simple_ams/version.rb +3 -0
- data/lib/simple_ams.rb +29 -0
- data/simple_ams.gemspec +29 -0
- metadata +160 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5193c4f1997cfc84c8fdf5fa90abfde7ac2a03a2
|
4
|
+
data.tar.gz: 13c6c665417899d0a73d9900144d58e8f848e370
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b6affb011516c6e9b69b829c176966305b38f7d102b874248bac63fb089c8b84b27cec6190e067364943935b26164bcc066d12ebad77c88d412edaf7db6724aa
|
7
|
+
data.tar.gz: c44a84ff86b1a0d2eb5b67670b508a3cfa6da2ded1cc0353fd0709b73a352a7a2d1bf735860cba76ae03f696e4eefab50c4704b67229be8fb1285f43376c8ea2
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,224 @@
|
|
1
|
+
# SimpleAMS
|
2
|
+
> "Simple things should be simple and complex things should be possible." Alan Kay.
|
3
|
+
|
4
|
+
If we want to interact with modern APIs we should start building modern, flexible libraries
|
5
|
+
that help developers to build such APIs. Modern Ruby serializers, as I always wanted them to be.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'simple_ams'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install simple_ams
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
The gem's interface has been inspired by ActiveModel Serializers 0.9.2, 0.10.stable, jsonapi-rb and Ember Data.
|
25
|
+
However, **it has been built for POROs, does not rely in any dependency and does not relate to Rails in any case** other than
|
26
|
+
some nostalgia for the (advanced at that time) pre-0.10 ActiveModel Serialiers.
|
27
|
+
|
28
|
+
|
29
|
+
### Simple case
|
30
|
+
|
31
|
+
You will rarely need all the advanced options. Usually you will have something like that:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
class UserSerializer
|
35
|
+
include SimpleAMS::DSL
|
36
|
+
|
37
|
+
#specify the adapter, pass some options all the way down to the adapter
|
38
|
+
adapter SimpleAMS::Adapters::JSONAPI, root: true
|
39
|
+
|
40
|
+
#specify available attributes/fields
|
41
|
+
attributes :id, :name, :email, :birth_date
|
42
|
+
|
43
|
+
#specify available relations
|
44
|
+
has_many :videos, :comments, :posts
|
45
|
+
belongs_to :organization
|
46
|
+
has_one :profile
|
47
|
+
|
48
|
+
#specify some links
|
49
|
+
link :feed, '/api/v1/me/feed'
|
50
|
+
#links can also take other options, as specified by RFC 8288
|
51
|
+
link :root, '/api/v1/', rel: :user
|
52
|
+
#link values can be dynamic as well through lambdas
|
53
|
+
link :posts, ->(obj) { "/api/v1/users/#{obj.id}/posts/" }, rel: :user
|
54
|
+
#if you also need dynamic options, you can return an array from the lambda
|
55
|
+
link :followers, ->(obj) { ["/api/v1/users/#{obj.id}/followers/", rel: obj.type] }
|
56
|
+
|
57
|
+
#same with metas: can be static, dynamic and accept arbitrary options
|
58
|
+
meta :environment, ->(obj) { Rails.env.to_s }
|
59
|
+
|
60
|
+
#collection accepts exactly the same aforementioned interface
|
61
|
+
#although you will rarely use it to full extend
|
62
|
+
#here we use only links and meta
|
63
|
+
collection do
|
64
|
+
link :root, '/api/v1/', rel: :user
|
65
|
+
type :users
|
66
|
+
meta :count, ->(collection) { collection.count }
|
67
|
+
end
|
68
|
+
|
69
|
+
#note that there is a shortcut if you just need to specify the collection name/type:
|
70
|
+
#collection :users
|
71
|
+
|
72
|
+
#override an attribute
|
73
|
+
def name
|
74
|
+
"#{object.first_name} #{object.last_name}"
|
75
|
+
end
|
76
|
+
|
77
|
+
#override a relation
|
78
|
+
def videos
|
79
|
+
Videos.where(user_id: object.id).published
|
80
|
+
end
|
81
|
+
end
|
82
|
+
```
|
83
|
+
|
84
|
+
Then you can just feed your serializer with data, along with some options:
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
SimpleAMS::Renderer.new(user, fields: [:id, :name, :email], includes: [:videos]).to_json
|
88
|
+
```
|
89
|
+
`to_json` first calls `as_json`, which creates a ruby Hash and then `to_json` is called
|
90
|
+
on top of that hash.
|
91
|
+
|
92
|
+
|
93
|
+
# Advanced usage
|
94
|
+
The DSL in the previous example is just syntactic sugar. In the basis, there is a very powerful
|
95
|
+
hash-based DSL that can be used in 3 different places:
|
96
|
+
|
97
|
+
* When initializing the `SimpleAMS::Renderer` class to render the data using specific serializer, adapter and options.
|
98
|
+
* Inside a class that has the `SimpleAMS::DSL` included, using the `with_options({})` class method
|
99
|
+
* Through the DSL, powered with some syntactic sugar
|
100
|
+
|
101
|
+
In any case, we have the following options:
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
{
|
105
|
+
#the primary id of the record(s), used mostly by the underlying adapter (like JSONAPI)
|
106
|
+
primary_id: :id,
|
107
|
+
#the type of the record, used mostly by the underlying adapter (like JSONAPI)
|
108
|
+
type: :user,
|
109
|
+
#which relations should be included
|
110
|
+
includes: [:posts, videos: [:comments]],
|
111
|
+
#which fields for each relation should be included
|
112
|
+
fields: [:id, :name, posts: [:id, :text], videos: [:id, :title, comments: [:id, :text]]] #overrides includes when association is specified
|
113
|
+
relations: [
|
114
|
+
[:belongs_to, :company, {
|
115
|
+
serializer: CompanySerializer,
|
116
|
+
fields: Company.column_names.map(&:to_sym)
|
117
|
+
}
|
118
|
+
],
|
119
|
+
[:has_many, :followers, {
|
120
|
+
serializer: UserSerializer,
|
121
|
+
fields: User.column_names.map(&:to_sym)
|
122
|
+
],
|
123
|
+
]
|
124
|
+
#the serializer that should be used
|
125
|
+
#makes sense to use it when initializing the Renderer
|
126
|
+
serializer: UserSerializer,
|
127
|
+
#can also be a lambda, in case of polymorphic records, ideal for ArrayRenderer
|
128
|
+
serializer: ->(obj){ obj.employee? ? EmployeeSerializer : UserSerializer }
|
129
|
+
#specifying the underlying adapter. This cannot be a lambda in case of ArrayRenderer,
|
130
|
+
#but can take some useful options that are passed down straight to the adapter class.
|
131
|
+
adapter: SimpleAMS::Adapters::AMS, root: true
|
132
|
+
#the links data
|
133
|
+
links: {
|
134
|
+
#can be a simple string
|
135
|
+
root: '/api/v1'
|
136
|
+
#a string with some options (relation and target attributes as defined by RFC8288
|
137
|
+
#however, you can also pass adapter-specific attributes
|
138
|
+
posts: "/api/v1/posts/", rel: :posts,
|
139
|
+
#it can also be a lambda that takes the resource to be rendered as a param
|
140
|
+
#when the lambda is called, it should return the array structure above
|
141
|
+
self: ->(obj) { ["/api/v1/users/#{obj.id}", rel: :user] }
|
142
|
+
},
|
143
|
+
#the meta data, same as the links data (available in adapters even for single records)
|
144
|
+
metas: {
|
145
|
+
type: ->(obj){ obj.employee? ? :employee : :user}
|
146
|
+
#meta can take arbitrary options as well
|
147
|
+
authorization: :oauth, type: :bearer_token
|
148
|
+
},
|
149
|
+
#collection parameters, used only in ArrayRenderer
|
150
|
+
collection: {
|
151
|
+
links: {
|
152
|
+
root: '/api/v1'
|
153
|
+
},
|
154
|
+
metas: {
|
155
|
+
pages: ->(obj) { [obj.pages, collection: true]},
|
156
|
+
current_page: ->(obj) { [obj.current_page, collection: true] },
|
157
|
+
previous_page: ->(obj) { [obj.previous_page, collection: true] },
|
158
|
+
next_page: ->(obj) { [obj.next_page, collection: true] },
|
159
|
+
max_per_page: 50,
|
160
|
+
},
|
161
|
+
}
|
162
|
+
#exposing helpers that will be available inside the seriralizer
|
163
|
+
expose: {
|
164
|
+
#a class
|
165
|
+
current_user: User.first
|
166
|
+
#or a module
|
167
|
+
helpers: CommonHelpers
|
168
|
+
},
|
169
|
+
}
|
170
|
+
```
|
171
|
+
|
172
|
+
Now let those options be `OPTIONS`. These can be fed to either the `SimpleAMS::Renderer`
|
173
|
+
or to the serializer class itself using the `with_options` class method. Let's see how:
|
174
|
+
|
175
|
+
```ruby
|
176
|
+
class UserSerializer
|
177
|
+
include SimpleAMS::DSL
|
178
|
+
|
179
|
+
with_options({ #you can pass the same options as above ;)
|
180
|
+
primary_id: :id,
|
181
|
+
# ...
|
182
|
+
# ...
|
183
|
+
# ...
|
184
|
+
})
|
185
|
+
|
186
|
+
def name
|
187
|
+
"#{object.first_name} #{object.last_name}"
|
188
|
+
end
|
189
|
+
|
190
|
+
def videos
|
191
|
+
Videos.where(user_id: object.id).published
|
192
|
+
end
|
193
|
+
end
|
194
|
+
```
|
195
|
+
|
196
|
+
The same options can be passed when calling the `Renderer`. `Renderer` can override
|
197
|
+
some properties, however in all properties that act as sets/arrays (like
|
198
|
+
attributes/fields, includes, links etc.), **specified serializer options take precedence** over
|
199
|
+
`Renderer` options.
|
200
|
+
|
201
|
+
```ruby
|
202
|
+
SimpleAMS::Renderer.new(user, {
|
203
|
+
primary_id: :id,
|
204
|
+
serializer: UserSerializer,
|
205
|
+
# ...
|
206
|
+
# ...
|
207
|
+
# ...
|
208
|
+
}).to_json
|
209
|
+
|
210
|
+
```
|
211
|
+
## Development
|
212
|
+
|
213
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
214
|
+
|
215
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
216
|
+
|
217
|
+
## Contributing
|
218
|
+
But reports are very welcome at https://github.com/vasilakisfil/SimpleAMS. Please add as much info as you can (serializer and Renderer input)
|
219
|
+
so that we can easily track down the bug.
|
220
|
+
|
221
|
+
Pull requests are also very welcome on GitHub at https://github.com/vasilakisfil/SimpleAMS.
|
222
|
+
However, to keep the code's sanity (AMS I am looking to you), **I will be very picky** on the code style and design,
|
223
|
+
to match (my) existing code characteristics.
|
224
|
+
Because at the end of the day, it's gonna be me who will maintain this thing.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "SimpleAMS"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require "simple_ams"
|
2
|
+
|
3
|
+
class SimpleAMS::Adapters::AMS
|
4
|
+
attr_reader :document, :options
|
5
|
+
|
6
|
+
def initialize(document, options = {})
|
7
|
+
@document = document
|
8
|
+
@options = options
|
9
|
+
end
|
10
|
+
|
11
|
+
def as_json
|
12
|
+
hash = {}
|
13
|
+
|
14
|
+
#TODO: I think bang method for merging is way faster ?
|
15
|
+
hash = hash.merge(fields)
|
16
|
+
hash = hash.merge(relations)
|
17
|
+
hash = hash.merge(links: links) unless links.empty?
|
18
|
+
hash = hash.merge(metas: metas) unless metas.empty?
|
19
|
+
|
20
|
+
return hash
|
21
|
+
end
|
22
|
+
|
23
|
+
def fields
|
24
|
+
@fields ||= document.fields.inject({}){ |hash, field|
|
25
|
+
_value = field.value
|
26
|
+
hash[field.key] = _value.respond_to?(:as_json) ? _value.as_json : _value
|
27
|
+
hash
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
def links
|
32
|
+
@links ||= document.links.inject({}){ |hash, link|
|
33
|
+
_value = link.value
|
34
|
+
hash[link.name] = _value.respond_to?(:as_json) ? _value.as_json : _value
|
35
|
+
hash
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
def metas
|
40
|
+
@metas ||= document.metas.inject({}){ |hash, meta|
|
41
|
+
_value = meta.value
|
42
|
+
hash[meta.name] = _value.respond_to?(:as_json) ? _value.as_json : _value
|
43
|
+
hash
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
def relations
|
48
|
+
return {} if document.relations.empty?
|
49
|
+
|
50
|
+
@relations ||= document.relations.inject({}){ |hash, relation|
|
51
|
+
if relation.folder?
|
52
|
+
value = relation.documents.map{|doc| self.class.new(doc).as_json}
|
53
|
+
else
|
54
|
+
value = self.class.new(relation).as_json
|
55
|
+
end
|
56
|
+
hash[relation.name] = value
|
57
|
+
|
58
|
+
hash
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
class Collection < self
|
63
|
+
attr_reader :folder, :adapter, :options
|
64
|
+
|
65
|
+
def initialize(folder, options = {})
|
66
|
+
@folder = folder
|
67
|
+
@adapter = folder.adapter.value
|
68
|
+
@options = options
|
69
|
+
end
|
70
|
+
|
71
|
+
def as_json
|
72
|
+
if options[:root]
|
73
|
+
{folder.name => documents}
|
74
|
+
else
|
75
|
+
documents
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def documents
|
80
|
+
return folder.documents.map{|document|
|
81
|
+
adapter.new(document).as_json
|
82
|
+
} || []
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require "simple_ams"
|
2
|
+
|
3
|
+
module SimpleAMS
|
4
|
+
class Document::Fields
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
attr_reader :members
|
8
|
+
|
9
|
+
def initialize(options)
|
10
|
+
@options = options
|
11
|
+
@members = options.fields #[:field1, :field2]
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](key)
|
15
|
+
found = members.find{|field| field == key}
|
16
|
+
return nil unless found
|
17
|
+
|
18
|
+
return with_decorator(found)
|
19
|
+
end
|
20
|
+
|
21
|
+
def each(&block)
|
22
|
+
return enum_for(:each) unless block_given?
|
23
|
+
|
24
|
+
members.each{ |key|
|
25
|
+
yield with_decorator(key)
|
26
|
+
}
|
27
|
+
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
attr_reader :options
|
33
|
+
|
34
|
+
def with_decorator(key)
|
35
|
+
Field.new(
|
36
|
+
options.resource,
|
37
|
+
options.serializer,
|
38
|
+
key,
|
39
|
+
options
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
class Field
|
44
|
+
attr_reader :key
|
45
|
+
|
46
|
+
#do we need to inject the whole options object?
|
47
|
+
def initialize(resource, serializer, key, options)
|
48
|
+
@resource = resource
|
49
|
+
@serializer = serializer
|
50
|
+
@key = key
|
51
|
+
@options = options
|
52
|
+
end
|
53
|
+
|
54
|
+
def value
|
55
|
+
return @value if defined?(@value)
|
56
|
+
|
57
|
+
return @value = serializer.send(key) if serializer.respond_to? key
|
58
|
+
binding.pry if resource.is_a?(Array)
|
59
|
+
return resource.send(key)
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
attr_reader :resource, :serializer
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require "simple_ams"
|
2
|
+
|
3
|
+
module SimpleAMS
|
4
|
+
class Document::Links
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
attr_reader :members
|
8
|
+
|
9
|
+
def initialize(options)
|
10
|
+
@options = options
|
11
|
+
@members = options.links
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](key)
|
15
|
+
found = members.find{|link| link.name == key}
|
16
|
+
return nil unless found
|
17
|
+
|
18
|
+
return with_decorator(found)
|
19
|
+
end
|
20
|
+
|
21
|
+
def each(&block)
|
22
|
+
return enum_for(:each) unless block_given?
|
23
|
+
|
24
|
+
members.each{ |member|
|
25
|
+
yield with_decorator(member)
|
26
|
+
}
|
27
|
+
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
attr_reader :options
|
33
|
+
|
34
|
+
def with_decorator(link)
|
35
|
+
Link.new(link)
|
36
|
+
end
|
37
|
+
|
38
|
+
#memoization maybe ?
|
39
|
+
class Link
|
40
|
+
def initialize(link)
|
41
|
+
@link = link
|
42
|
+
end
|
43
|
+
|
44
|
+
def name
|
45
|
+
link.name
|
46
|
+
end
|
47
|
+
|
48
|
+
def value
|
49
|
+
link.respond_to?(:call) ? link.value.call : link.value
|
50
|
+
end
|
51
|
+
|
52
|
+
def options
|
53
|
+
link.options
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
attr_reader :link
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require "simple_ams"
|
2
|
+
|
3
|
+
#TODO: Add memoization for the relations object (iteration + access)
|
4
|
+
module SimpleAMS
|
5
|
+
class Document::Relations
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
def initialize(options)
|
9
|
+
@options = options
|
10
|
+
@relations = options.relations
|
11
|
+
@serializer = options.serializer
|
12
|
+
@resource = options.resource
|
13
|
+
end
|
14
|
+
|
15
|
+
def [](key)
|
16
|
+
found = relations.find{|relation| relation.name == key}
|
17
|
+
return nil unless found
|
18
|
+
|
19
|
+
return relation_for(found)
|
20
|
+
end
|
21
|
+
|
22
|
+
def each(&block)
|
23
|
+
return enum_for(:each) unless block_given?
|
24
|
+
|
25
|
+
relations.each{ |relation|
|
26
|
+
yield relation_for(relation)
|
27
|
+
}
|
28
|
+
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
def empty?
|
33
|
+
count == 0
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
attr_reader :options, :relations, :serializer, :resource
|
38
|
+
|
39
|
+
def relation_for(relation)
|
40
|
+
renderer_klass_for(relation).new(
|
41
|
+
SimpleAMS::Options.new(
|
42
|
+
relation_value_for(relation.name), relation_options_for(relation)
|
43
|
+
)
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
#TODO: rename that to relation and existing relation to relationship
|
48
|
+
def relation_value_for(name)
|
49
|
+
if serializer.respond_to?(name)
|
50
|
+
serializer.send(name)
|
51
|
+
else
|
52
|
+
resource.send(name)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
#4 options are merged:
|
57
|
+
# *user injected when instantiating the SimpleAMS class
|
58
|
+
# *relation options injected from parent serializer
|
59
|
+
# *serializer class options
|
60
|
+
def relation_options_for(relation)
|
61
|
+
_relation_options = {
|
62
|
+
injected_options: (relation.options || {}).merge(
|
63
|
+
options.relation_options_for(
|
64
|
+
relation.name
|
65
|
+
).merge(
|
66
|
+
expose: options.expose
|
67
|
+
)
|
68
|
+
).merge(
|
69
|
+
_internal: {
|
70
|
+
module: serializer.class.to_s.rpartition('::').first
|
71
|
+
}
|
72
|
+
)
|
73
|
+
}
|
74
|
+
#TODO: deep merge, can we automate this somehow ?
|
75
|
+
_relation_options[:injected_options][:collection] = (_relation_options[:collection] || {}).merge(
|
76
|
+
name: relation.name
|
77
|
+
)
|
78
|
+
|
79
|
+
return _relation_options
|
80
|
+
end
|
81
|
+
|
82
|
+
def renderer_klass_for(relation)
|
83
|
+
renderer = SimpleAMS::Document
|
84
|
+
collection_renderer = renderer::Folder
|
85
|
+
|
86
|
+
relation.collection? ? collection_renderer : renderer
|
87
|
+
end
|
88
|
+
|
89
|
+
=begin TODO: Add that as public method, should help performance in edge cases
|
90
|
+
def relationship_info_for(name)
|
91
|
+
relations.find{|i| i.name == name}
|
92
|
+
end
|
93
|
+
=end
|
94
|
+
end
|
95
|
+
end
|