From d7de53ce30aeb9a6600614e6eabff10d8b60031c Mon Sep 17 00:00:00 2001 From: Benjamin Fleischer Date: Wed, 16 Dec 2015 00:03:55 -0600 Subject: [PATCH] Consider evaluating association in serializer context For discussion: Consider evaluating association in serializer context That way, associations are really just anything that can be conditionally included. They no longer have to actually be methods on the object or serializer. e.g. ```diff has_many :comments do - last(1) + Comment.active.for_serialization(object).last(1) end ``` --- CHANGELOG.md | 17 ++++++++++++++++- lib/active_model/serializer/reflection.rb | 8 ++++---- test/fixtures/poro.rb | 2 ++ test/serializers/associations_test.rb | 2 +- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5dd7a819c..da1b57b97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,22 @@ Breaking changes: Features: -- [#1336](https://github.com/rails-api/active_model_serializers/pull/1336) Added support for Grape >= 0.13, < 1.0 +- [#1378](https://github.com/rails-api/active_model_serializers/pull/1378) Change association blocks + to be evaluated in *serializer* scope, rather than *association* scope. (@bf4) + * Syntax changes from e.g. + `has_many :titles do customers.pluck(:title) end` (in #1356) to + `has_many :titles do object.customers.pluck(:title) end` +- [#1356](https://github.com/rails-api/active_model_serializers/pull/1356) Add inline syntax for + attributes and associations (@bf4 @beauby @noahsilas) + * Allows defining attributes so that they don't conflict with existing methods. e.g. `attribute + :title do 'Mr. Topum Hat' end` + * Allows defining associations so that they don't conflict with existing methods. e.g. `has_many + :titles do customers.pluck(:title) end` + * Allows dynamic associations, as compared to compare to using + [`virtual_value`](https://github.com/rails-api/active_model_serializers/pull/1356#discussion_r47146466). + e.g. `has_many :reviews, virtual_value: [{ id: 1 }, { id: 2 }]` + * Removes dynamically defined methods on the serializer +- [#1336](https://github.com/rails-api/active_model_serializers/pull/1336) Added support for Grape >= 0.13, < 1.0 (@johnhamelink) - [#1291](https://github.com/rails-api/active_model_serializers/pull/1291) Add logging (@maurogeorge) - [#1225](https://github.com/rails-api/active_model_serializers/pull/1225) Better serializer lookup, use nested serializer when it exists (@beauby) - [#1172](https://github.com/rails-api/active_model_serializers/pull/1172) Better serializer registration, get more than just the first module (@bf4) diff --git a/lib/active_model/serializer/reflection.rb b/lib/active_model/serializer/reflection.rb index d5f4da906..19eb78b80 100644 --- a/lib/active_model/serializer/reflection.rb +++ b/lib/active_model/serializer/reflection.rb @@ -8,14 +8,14 @@ class Serializer # has_one :author, serializer: AuthorSerializer # has_many :comments # has_many :comments, key: :last_comments do - # last(1) + # object.comments.last(1) # end # end # - # Notice that the association block is evaluated in the context of the association. + # Notice that the association block is evaluated in the context of the serializer. # Specifically, the association 'comments' is evaluated two different ways: # 1) as 'comments' and named 'comments'. - # 2) as 'comments.last(1)' and named 'last_comments'. + # 2) as 'object.comments.last(1)' and named 'last_comments'. # # PostSerializer._reflections #=> # # [ @@ -29,7 +29,7 @@ class Serializer # @api private def value(instance) if block - instance.read_attribute_for_serialization(name).instance_eval(&block) + instance.instance_eval(&block) else instance.read_attribute_for_serialization(name) end diff --git a/test/fixtures/poro.rb b/test/fixtures/poro.rb index 5a6e3681e..092b7e82c 100644 --- a/test/fixtures/poro.rb +++ b/test/fixtures/poro.rb @@ -33,6 +33,7 @@ class Profile < Model class ProfileSerializer < ActiveModel::Serializer attributes :name, :description + # TODO: is this used anywhere? def arguments_passed_in? instance_options[:my_options] == :accessible end @@ -75,6 +76,7 @@ def blog Blog.new(id: 999, name: 'Custom blog') end + # TODO: is this used anywhere? def custom_options instance_options end diff --git a/test/serializers/associations_test.rb b/test/serializers/associations_test.rb index c0d83a888..25b5b62f8 100644 --- a/test/serializers/associations_test.rb +++ b/test/serializers/associations_test.rb @@ -129,7 +129,7 @@ def test_associations_custom_keys class InlineAssociationTestPostSerializer < ActiveModel::Serializer has_many :comments has_many :comments, key: :last_comments do - last(1) + object.comments.last(1) end end