Skip to content

Commit f76ea3d

Browse files
authored
Merge pull request #2089 from bf4/improve_reflection_interface
Improve reflection internal interface
2 parents f5ad632 + f327b6b commit f76ea3d

File tree

2 files changed

+80
-26
lines changed

2 files changed

+80
-26
lines changed

lib/active_model/serializer.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,13 +117,13 @@ def self.serialization_adapter_instance
117117
config.serializer_lookup_enabled = true
118118

119119
# @deprecated Use {#config.collection_serializer=} instead of this. Is
120-
# compatibilty layer for ArraySerializer.
120+
# compatibility layer for ArraySerializer.
121121
def config.array_serializer=(collection_serializer)
122122
self.collection_serializer = collection_serializer
123123
end
124124

125125
# @deprecated Use {#config.collection_serializer} instead of this. Is
126-
# compatibilty layer for ArraySerializer.
126+
# compatibility layer for ArraySerializer.
127127
def config.array_serializer
128128
collection_serializer
129129
end

lib/active_model/serializer/reflection.rb

Lines changed: 78 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,19 @@ class Serializer
1414
# end
1515
# has_many :secret_meta_data, if: :is_admin?
1616
#
17+
# has_one :blog do |serializer|
18+
# meta count: object.roles.count
19+
# serializer.cached_blog
20+
# end
21+
#
22+
# private
23+
#
24+
# def cached_blog
25+
# cache_store.fetch("cached_blog:#{object.updated_at}") do
26+
# Blog.find(object.blog_id)
27+
# end
28+
# end
29+
#
1730
# def is_admin?
1831
# current_user.admin?
1932
# end
@@ -32,43 +45,82 @@ class Serializer
3245
# # ]
3346
#
3447
# So you can inspect reflections in your Adapters.
35-
#
3648
class Reflection < Field
3749
def initialize(*)
3850
super
39-
@_links = {}
40-
@_include_data = Serializer.config.include_data_default
41-
@_meta = nil
51+
options[:links] = {}
52+
options[:include_data_setting] = Serializer.config.include_data_default
53+
options[:meta] = nil
4254
end
4355

56+
# @api public
57+
# @example
58+
# has_one :blog do
59+
# include_data false
60+
# link :self, 'a link'
61+
# link :related, 'another link'
62+
# link :self, '//example.com/link_author/relationships/bio'
63+
# id = object.profile.id
64+
# link :related do
65+
# "//example.com/profiles/#{id}" if id != 123
66+
# end
67+
# link :related do
68+
# ids = object.likes.map(&:id).join(',')
69+
# href "//example.com/likes/#{ids}"
70+
# meta ids: ids
71+
# end
72+
# end
4473
def link(name, value = nil, &block)
45-
@_links[name] = block || value
74+
options[:links][name] = block || value
4675
:nil
4776
end
4877

78+
# @api public
79+
# @example
80+
# has_one :blog do
81+
# include_data false
82+
# meta(id: object.blog.id)
83+
# meta liked: object.likes.any?
84+
# link :self do
85+
# href object.blog.id.to_s
86+
# meta(id: object.blog.id)
87+
# end
4988
def meta(value = nil, &block)
50-
@_meta = block || value
89+
options[:meta] = block || value
5190
:nil
5291
end
5392

93+
# @api public
94+
# @example
95+
# has_one :blog do
96+
# include_data false
97+
# link :self, 'a link'
98+
# link :related, 'another link'
99+
# end
100+
#
101+
# has_one :blog do
102+
# include_data false
103+
# link :self, 'a link'
104+
# link :related, 'another link'
105+
# end
106+
#
107+
# belongs_to :reviewer do
108+
# meta name: 'Dan Brown'
109+
# include_data true
110+
# end
111+
#
112+
# has_many :tags, serializer: TagSerializer do
113+
# link :self, '//example.com/link_author/relationships/tags'
114+
# include_data :if_sideloaded
115+
# end
54116
def include_data(value = true)
55-
@_include_data = value
117+
options[:include_data_setting] = value
56118
:nil
57119
end
58120

59121
# @param serializer [ActiveModel::Serializer]
60122
# @yield [ActiveModel::Serializer]
61123
# @return [:nil, associated resource or resource collection]
62-
# @example
63-
# has_one :blog do |serializer|
64-
# serializer.cached_blog
65-
# end
66-
#
67-
# def cached_blog
68-
# cache_store.fetch("cached_blog:#{object.updated_at}") do
69-
# Blog.find(object.blog_id)
70-
# end
71-
# end
72124
def value(serializer, include_slice)
73125
@object = serializer.object
74126
@scope = serializer.scope
@@ -103,7 +155,6 @@ def value(serializer, include_slice)
103155
# comments_reflection.build_association(post_serializer, foo: 'bar')
104156
#
105157
# @api private
106-
#
107158
def build_association(parent_serializer, parent_serializer_options, include_slice = {})
108159
reflection_options = options.dup
109160

@@ -113,8 +164,8 @@ def build_association(parent_serializer, parent_serializer_options, include_slic
113164
association_value = value(parent_serializer, include_slice)
114165
serializer_class = parent_serializer.class.serializer_for(association_value, reflection_options)
115166
reflection_options[:include_data] = include_data?(include_slice)
116-
reflection_options[:links] = @_links
117-
reflection_options[:meta] = @_meta
167+
reflection_options[:links] = options[:links]
168+
reflection_options[:meta] = options[:meta]
118169

119170
if serializer_class
120171
serializer = catch(:no_serializer) do
@@ -138,15 +189,18 @@ def build_association(parent_serializer, parent_serializer_options, include_slic
138189

139190
protected
140191

192+
# used in instance exec
141193
attr_accessor :object, :scope
142194

143195
private
144196

145197
def include_data?(include_slice)
146-
if @_include_data == :if_sideloaded
147-
include_slice.key?(name)
148-
else
149-
@_include_data
198+
include_data_setting = options[:include_data_setting]
199+
case include_data_setting
200+
when :if_sideloaded then include_slice.key?(name)
201+
when true then true
202+
when false then false
203+
else fail ArgumentError, "Unknown include_data_setting '#{include_data_setting.inspect}'"
150204
end
151205
end
152206

0 commit comments

Comments
 (0)