1 require 'active_support/json'
3 module ActiveRecord
#:nodoc:
5 class Serializer
#:nodoc:
8 def initialize(record
, options
= {})
9 @record, @options = record
, options
.dup
12 # To replicate the behavior in ActiveRecord#attributes,
13 # <tt>:except</tt> takes precedence over <tt>:only</tt>. If <tt>:only</tt> is not set
14 # for a N level model but is set for the N+1 level models,
15 # then because <tt>:except</tt> is set to a default value, the second
16 # level model can have both <tt>:except</tt> and <tt>:only</tt> set. So if
17 # <tt>:only</tt> is set, always delete <tt>:except</tt>.
18 def serializable_attribute_names
19 attribute_names
= @record.attribute_names
22 options
.delete(:except)
23 attribute_names
= attribute_names
& Array(options
[:only]).collect
{ |n
| n
.to_s
}
25 options
[:except] = Array(options
[:except]) | Array(@record.class.inheritance_column
)
26 attribute_names
= attribute_names
- options
[:except].collect
{ |n
| n
.to_s
}
32 def serializable_method_names
33 Array(options
[:methods]).inject([]) do |method_attributes
, name
|
34 method_attributes
<< name
if @record.respond_to
?(name
.to_s
)
39 def serializable_names
40 serializable_attribute_names
+ serializable_method_names
43 # Add associations specified via the <tt>:includes</tt> option.
44 # Expects a block that takes as arguments:
45 # +association+ - name of the association
46 # +records+ - the association record(s) to be serialized
47 # +opts+ - options for the association records
48 def add_includes(&block
)
49 if include_associations
= options
.delete(:include)
50 base_only_or_except
= { :except => options
[:except],
51 :only => options
[:only] }
53 include_has_options
= include_associations
.is_a
?(Hash
)
54 associations
= include_has_options
? include_associations
.keys
: Array(include_associations
)
56 for association
in associations
57 records
= case @record.class.reflect_on_association(association
).macro
58 when :has_many, :has_and_belongs_to_many
59 @record.send(association
).to_a
60 when :has_one, :belongs_to
61 @record.send(association
)
65 association_options
= include_has_options
? include_associations
[association
] : base_only_or_except
66 opts
= options
.merge(association_options
)
67 yield(association
, records
, opts
)
71 options
[:include] = include_associations
75 def serializable_record
76 returning(serializable_record
= {}) do
77 serializable_names
.each
{ |name
| serializable_record
[name
] = @record.send(name
) }
78 add_includes
do |association
, records
, opts
|
79 if records
.is_a
?(Enumerable
)
80 serializable_record
[association
] = records
.collect
{ |r
| self.class.new(r
, opts
).serializable_record
}
82 serializable_record
[association
] = self.class.new(records
, opts
).serializable_record
89 # overwrite to implement
99 require 'active_record/serializers/xml_serializer'
100 require 'active_record/serializers/json_serializer'