diff options
Diffstat (limited to 'activemodel/lib/active_model/serializer.rb')
-rw-r--r-- | activemodel/lib/active_model/serializer.rb | 60 |
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 |