Skip to content

Commit 2111cee

Browse files
committed
Dynamic attribute filtering on serializers
Add a method named include_attribute that by default returns all fields. Actual serialiser implementations can override this method to dynamically filter the list of attributes to be serialized.
1 parent 1f08865 commit 2111cee

File tree

4 files changed

+47
-1
lines changed

4 files changed

+47
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ Features:
1717
- [#1158](https://github.com/rails-api/active_model_serializers/pull/1158) Add support for wildcards in `include` option (@beauby)
1818
- [#1127](https://github.com/rails-api/active_model_serializers/pull/1127) Add support for nested
1919
associations for JSON and Attributes adapters via the `include` option (@NullVoxPopuli, @beauby).
20+
- [#1141](https://github.com/rails-api/active_model_serializers/pull/1141) Add support for
21+
dynamically including or excluding attributes in serializers (@lautis).
2022

2123
Fixes:
2224

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,26 @@ class PostSerializer < ActiveModel::Serializer
188188
end
189189
```
190190

191+
### Conditionally including or excluding attributes
192+
193+
You can also dynamically include or exclude serialized attributes by defining a
194+
method named include_attributes. This is typically used to customize the output
195+
based on `current_user`. For example:
196+
197+
```ruby
198+
class PostSerializer < ActiveModel::Serializer
199+
attributes :id, :body, :author
200+
201+
def include_attributes(included)
202+
if current_user.admin?
203+
included
204+
else
205+
included - [:author]
206+
end
207+
end
208+
end
209+
```
210+
191211
### Built in Adapters
192212

193213
#### Attributes

lib/active_model/serializer.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@ def json_key
143143
root || object.class.model_name.to_s.underscore
144144
end
145145

146+
def include_attributes(included)
147+
included
148+
end
149+
146150
def attributes(options = {})
147151
attributes =
148152
if options[:fields]
@@ -151,7 +155,7 @@ def attributes(options = {})
151155
self.class._attributes.dup
152156
end
153157

154-
attributes.each_with_object({}) do |name, hash|
158+
include_attributes(attributes).each_with_object({}) do |name, hash|
155159
unless self.class._fragmented
156160
hash[name] = send(name)
157161
else

test/serializers/attributes_test.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,31 @@ def test_attributes_definition
1818
@profile_serializer.class._attributes)
1919
end
2020

21+
def test_attributes
22+
assert_equal({ name: 'Name 1', description: 'Description 1' },
23+
@profile_serializer.attributes)
24+
end
25+
2126
def test_attributes_with_fields_option
2227
assert_equal({ name: 'Name 1' },
2328
@profile_serializer.attributes(fields: [:name]))
2429
end
2530

31+
def test_attributes_with_fields_method
32+
@profile_serializer.define_singleton_method(:include_attributes) do |included|
33+
included - [:name]
34+
end
35+
assert_equal({ description: 'Description 1' },
36+
@profile_serializer.attributes)
37+
end
38+
39+
def test_attributes_with_fields_option_and_method
40+
@profile_serializer.define_singleton_method(:include_attributes) do |included|
41+
included - [:name]
42+
end
43+
assert_equal({}, @profile_serializer.attributes(fields: [:name]))
44+
end
45+
2646
def test_attributes_inheritance_definition
2747
assert_equal([:id, :body], @serializer_klass._attributes)
2848
end

0 commit comments

Comments
 (0)