diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index a21c2884a..c8154bfe6 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -15,6 +15,7 @@ class << self def inherited(base) base._root = _root base._attributes = (_attributes || []).dup + base._hidden_attributes = (_hidden_attributes || []).dup base._associations = (_associations || {}).dup end @@ -60,7 +61,7 @@ def serializer_for(resource) end end - attr_accessor :_root, :_attributes, :_associations + attr_accessor :_root, :_attributes, :_hidden_attributes, :_associations alias root _root= alias root= _root= @@ -86,6 +87,11 @@ def has_many(*attrs) associate(Association::HasMany, *attrs) end + def hidden_attributes(*attrs) + @_hidden_attributes.concat attrs + attributes(*attrs) + end + private def associate(klass, *attrs) @@ -110,6 +116,7 @@ def initialize(object, options={}) @wrap_in_array = options[:_wrap_in_array] @only = Array(options[:only]) if options[:only] @except = Array(options[:except]) if options[:except] + @expose = Array(options[:expose]) if options[:expose] end attr_accessor :object, :scope, :root, :meta_key, :meta @@ -127,6 +134,10 @@ def attributes end end + def hidden_attributes + self.class._hidden_attributes + end + def associations associations = self.class._associations included_associations = filter(associations.keys) @@ -142,6 +153,8 @@ def associations end def filter(keys) + @expose ||= [] + hidden_attributes.each { |item| keys.delete(item) unless @expose.include?(item) } if @only keys & @only elsif @except diff --git a/test/fixtures/poro.rb b/test/fixtures/poro.rb index a43954b53..03d3b39bd 100644 --- a/test/fixtures/poro.rb +++ b/test/fixtures/poro.rb @@ -35,6 +35,9 @@ def comments class Comment < Model end +class Desk < Model +end + ### ## Serializers ### @@ -62,3 +65,8 @@ class PostSerializer < ActiveModel::Serializer class CommentSerializer < ActiveModel::Serializer attributes :content end + +class DeskSerializer < ActiveModel::Serializer + attributes :drawer, :lamp + hidden_attributes :secret_document +end \ No newline at end of file diff --git a/test/unit/active_model/serializer/filter_test.rb b/test/unit/active_model/serializer/filter_test.rb index 73df71319..aa1089222 100644 --- a/test/unit/active_model/serializer/filter_test.rb +++ b/test/unit/active_model/serializer/filter_test.rb @@ -5,6 +5,7 @@ class Serializer class FilterOptionsTest < Minitest::Test def setup @profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }) + @desk = Desk.new({ drawer: 'My drawer', lamp: 'My lamp', secret_document: 'Some secret document' }) end def test_only_option @@ -20,6 +21,20 @@ def test_except_option 'profile' => { name: 'Name 1', description: 'Description 1' } }, @profile_serializer.as_json) end + + def test_not_expose_hidden_attribute + desk_serializer = DeskSerializer.new(@desk) + assert_equal({ + 'desk' => { drawer: 'My drawer', lamp: 'My lamp' } + }, desk_serializer.as_json) + end + + def test_expose_hidden_attribute + desk_serializer = DeskSerializer.new(@desk, expose: :secret_document) + assert_equal({ + 'desk' => { drawer: 'My drawer', lamp: 'My lamp', secret_document: 'Some secret document' } + }, desk_serializer.as_json) + end end class FilterAttributesTest < Minitest::Test