Skip to content

Commit 0768d04

Browse files
author
Артём Большаков
committed
Move all associations related code to Associations module
1 parent eddf4e7 commit 0768d04

File tree

2 files changed

+123
-101
lines changed

2 files changed

+123
-101
lines changed

lib/active_model/serializer.rb

Lines changed: 2 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,13 @@ class Serializer
77
autoload :Configuration
88
autoload :ArraySerializer
99
autoload :Adapter
10-
autoload :Association
11-
autoload :Reflection
12-
autoload :SingularReflection
13-
autoload :CollectionReflection
14-
autoload :BelongsToReflection
15-
autoload :HasOneReflection
16-
autoload :HasManyReflection
17-
10+
autoload :Associations
1811
include Configuration
12+
include Associations
1913

2014
class << self
2115
attr_accessor :_attributes
2216
attr_accessor :_attributes_keys
23-
attr_accessor :_reflections
2417
attr_accessor :_urls
2518
attr_accessor :_cache
2619
attr_accessor :_fragmented
@@ -74,57 +67,6 @@ def self.cache(options = {})
7467
@_cache_options = (options.empty?) ? nil : options
7568
end
7669

77-
# Defines an association in the object should be rendered.
78-
#
79-
# The serializer object should implement the association name
80-
# as a method which should return an array when invoked. If a method
81-
# with the association name does not exist, the association name is
82-
# dispatched to the serialized object.
83-
def self.has_many(*attrs)
84-
associate attrs do |name, options|
85-
HasManyReflection.new(name, options)
86-
end
87-
end
88-
89-
# Defines an association in the object that should be rendered.
90-
#
91-
# The serializer object should implement the association name
92-
# as a method which should return an object when invoked. If a method
93-
# with the association name does not exist, the association name is
94-
# dispatched to the serialized object.
95-
def self.belongs_to(*attrs)
96-
associate attrs do |name, options|
97-
BelongsToReflection.new(name, options)
98-
end
99-
end
100-
101-
# Defines an association in the object should be rendered.
102-
#
103-
# The serializer object should implement the association name
104-
# as a method which should return an object when invoked. If a method
105-
# with the association name does not exist, the association name is
106-
# dispatched to the serialized object.
107-
def self.has_one(*attrs)
108-
associate attrs do |name, options|
109-
HasOneReflection.new(name, options)
110-
end
111-
end
112-
113-
def self.associate(attrs, &block) #:nodoc:
114-
options = attrs.extract_options!
115-
self._reflections = _reflections.dup
116-
117-
attrs.each do |name|
118-
unless method_defined?(name)
119-
define_method name do
120-
object.send name
121-
end
122-
end
123-
124-
self._reflections << block.call(name, options)
125-
end
126-
end
127-
12870
def self.url(attr)
12971
@_urls.push attr
13072
end
@@ -211,51 +153,10 @@ def attributes(options = {})
211153
end
212154
end
213155

214-
215-
def associations
216-
return unless object
217-
218-
Enumerator.new do |y|
219-
self.class._reflections.dup.each do |reflection|
220-
name = reflection.name
221-
association_value = send(name)
222-
reflection_options = reflection.options.dup
223-
serializer_class = ActiveModel::Serializer.serializer_for(association_value, reflection_options)
224-
225-
if serializer_class
226-
begin
227-
serializer = serializer_class.new(
228-
association_value,
229-
serializer_options(reflection_options)
230-
)
231-
rescue ActiveModel::Serializer::ArraySerializer::NoSerializerError
232-
virtual_value = association_value
233-
virtual_value = virtual_value.as_json if virtual_value.respond_to?(:as_json)
234-
reflection_options[:virtual_value] = virtual_value
235-
end
236-
elsif !association_value.nil? && !association_value.instance_of?(Object)
237-
reflection_options[:virtual_value] = association_value
238-
end
239-
240-
y.yield Association.new(name, serializer, reflection_options)
241-
end
242-
end
243-
end
244-
245156
def self.serializers_cache
246157
@serializers_cache ||= ThreadSafe::Cache.new
247158
end
248159

249-
private
250-
251-
def serializer_options(reflection_options)
252-
serializer = reflection_options.fetch(:serializer, nil)
253-
254-
serializer_options = options.except(:serializer)
255-
serializer_options[:serializer] = serializer if serializer
256-
serializer_options
257-
end
258-
259160
attr_reader :options
260161

261162
def self.get_serializer_for(klass)
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
module ActiveModel
2+
class Serializer
3+
module Associations
4+
extend ActiveSupport::Concern
5+
6+
included do |base|
7+
class << base
8+
attr_accessor :_reflections
9+
end
10+
11+
autoload :Association
12+
autoload :Reflection
13+
autoload :SingularReflection
14+
autoload :CollectionReflection
15+
autoload :BelongsToReflection
16+
autoload :HasOneReflection
17+
autoload :HasManyReflection
18+
end
19+
20+
module ClassMethods
21+
def self.inherited(base)
22+
base._reflections = self._reflections.try(:dup) || []
23+
super
24+
end
25+
26+
# Defines an association in the object should be rendered.
27+
#
28+
# The serializer object should implement the association name
29+
# as a method which should return an array when invoked. If a method
30+
# with the association name does not exist, the association name is
31+
# dispatched to the serialized object.
32+
def has_many(*attrs)
33+
associate attrs do |name, options|
34+
HasManyReflection.new(name, options)
35+
end
36+
end
37+
38+
# Defines an association in the object that should be rendered.
39+
#
40+
# The serializer object should implement the association name
41+
# as a method which should return an object when invoked. If a method
42+
# with the association name does not exist, the association name is
43+
# dispatched to the serialized object.
44+
def belongs_to(*attrs)
45+
associate attrs do |name, options|
46+
BelongsToReflection.new(name, options)
47+
end
48+
end
49+
50+
# Defines an association in the object should be rendered.
51+
#
52+
# The serializer object should implement the association name
53+
# as a method which should return an object when invoked. If a method
54+
# with the association name does not exist, the association name is
55+
# dispatched to the serialized object.
56+
def has_one(*attrs)
57+
associate attrs do |name, options|
58+
HasOneReflection.new(name, options)
59+
end
60+
end
61+
62+
private
63+
64+
def associate(attrs, &block) #:nodoc:
65+
options = attrs.extract_options!
66+
self._reflections = _reflections.dup
67+
68+
attrs.each do |name|
69+
unless method_defined?(name)
70+
define_method name do
71+
object.send name
72+
end
73+
end
74+
75+
self._reflections << block.call(name, options)
76+
end
77+
end
78+
end
79+
80+
def associations
81+
return unless object
82+
83+
Enumerator.new do |y|
84+
self.class._reflections.dup.each do |reflection|
85+
name = reflection.name
86+
association_value = send(name)
87+
reflection_options = reflection.options.dup
88+
serializer_class = ActiveModel::Serializer.serializer_for(association_value, reflection_options)
89+
90+
if serializer_class
91+
begin
92+
serializer = serializer_class.new(
93+
association_value,
94+
serializer_options(reflection_options)
95+
)
96+
rescue ActiveModel::Serializer::ArraySerializer::NoSerializerError
97+
virtual_value = association_value
98+
virtual_value = virtual_value.as_json if virtual_value.respond_to?(:as_json)
99+
reflection_options[:virtual_value] = virtual_value
100+
end
101+
elsif !association_value.nil? && !association_value.instance_of?(Object)
102+
reflection_options[:virtual_value] = association_value
103+
end
104+
105+
y.yield Association.new(name, serializer, reflection_options)
106+
end
107+
end
108+
end
109+
110+
private
111+
112+
def serializer_options(reflection_options)
113+
serializer = reflection_options.fetch(:serializer, nil)
114+
115+
serializer_options = options.except(:serializer)
116+
serializer_options[:serializer] = serializer if serializer
117+
serializer_options
118+
end
119+
end
120+
end
121+
end

0 commit comments

Comments
 (0)