aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel/lib/active_model/serializer.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activemodel/lib/active_model/serializer.rb')
-rw-r--r--activemodel/lib/active_model/serializer.rb60
1 files changed, 33 insertions, 27 deletions
diff --git a/activemodel/lib/active_model/serializer.rb b/activemodel/lib/active_model/serializer.rb
index 7a55921e85..5b603bdbd7 100644
--- a/activemodel/lib/active_model/serializer.rb
+++ b/activemodel/lib/active_model/serializer.rb
@@ -8,6 +8,9 @@ module ActiveModel
def initialize(serializable, options = nil)
@serializable = serializable
@options = options ? options.dup : {}
+
+ @options[:only] = Array.wrap(@options[:only]).map { |n| n.to_s }
+ @options[:except] = Array.wrap(@options[:except]).map { |n| n.to_s }
end
def serialize
@@ -18,37 +21,40 @@ module ActiveModel
serialize(&block)
end
- protected
- def serializable_attribute_names
- attribute_names = @serializable.attributes.keys
-
- if options[:only]
- only = Array.wrap(options[:only]).map { |n| n.to_s }
- attribute_names &= only
- elsif options[:except]
- except = Array.wrap(options[:except]).map { |n| n.to_s }
- attribute_names -= except
- end
-
- attribute_names
+ # To replicate the behavior in ActiveRecord#attributes,
+ # <tt>:except</tt> takes precedence over <tt>:only</tt>. If <tt>:only</tt> is not set
+ # for a N level model but is set for the N+1 level models,
+ # then because <tt>:except</tt> is set to a default value, the second
+ # level model can have both <tt>:except</tt> and <tt>:only</tt> set. So if
+ # <tt>:only</tt> is set, always delete <tt>:except</tt>.
+ def serializable_attribute_names
+ attribute_names = @serializable.attributes.keys.sort
+
+ if options[:only].any?
+ attribute_names &= options[:only]
+ elsif options[:except].any?
+ attribute_names -= options[:except]
end
- def serializable_method_names
- Array.wrap(options[:methods]).inject([]) do |methods, name|
- methods << name if @serializable.respond_to?(name.to_s)
- methods
- end
- end
+ attribute_names
+ end
- def serializable_names
- serializable_attribute_names + serializable_method_names
+ def serializable_method_names
+ Array.wrap(options[:methods]).inject([]) do |methods, name|
+ methods << name if @serializable.respond_to?(name.to_s)
+ methods
end
+ end
- def serializable_hash
- serializable_names.inject({}) { |hash, name|
- hash[name] = @serializable.send(name)
- hash
- }
- end
+ def serializable_names
+ serializable_attribute_names + serializable_method_names
+ end
+
+ def serializable_hash
+ serializable_names.inject({}) { |hash, name|
+ hash[name] = @serializable.send(name)
+ hash
+ }
+ end
end
end