From 3dd6cccb4d8820bb8a675630e2c07b542ac213bd Mon Sep 17 00:00:00 2001 From: Benjamin Fleischer Date: Mon, 6 Nov 2017 22:04:50 -0600 Subject: [PATCH 1/2] Fix 0.10.6 regression; make using belongs_to on self opt-in --- docs/general/configuration_options.md | 16 ++++++++++++++++ lib/active_model/serializer.rb | 1 + .../adapter/json_api/relationship.rb | 3 ++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/general/configuration_options.md b/docs/general/configuration_options.md index 83f8890d..a07d71ee 100644 --- a/docs/general/configuration_options.md +++ b/docs/general/configuration_options.md @@ -57,6 +57,7 @@ still prefer the render option `:key_transform` over this setting. application, setting `config.key_transform` to `:unaltered` will provide a performance boost.* ##### default_includes + What relationships to serialize by default. Default: `'*'`, which includes one level of related objects. See [includes](adapters.md#included) for more info. @@ -162,6 +163,21 @@ Default: `{}`. *Used when `jsonapi_include_toplevel_object` is `true`* +##### jsonapi_use_foreign_key_on_belongs_to_relationship + +When true, the relationship will determine its resource object identifier +without calling the association or its serializer. This can be useful when calling +the association object is triggering unnecessary queries. + +For example, if a `comment` belongs to a `post`, and the comment +uses the foreign key `post_id`, we can determine the resource object +identifier `id` as `comment.post_id` and the `type` from the association options. +Or quite simply, it behaves as `belongs_to :post, type: :posts, foreign_key: :post_id`. + +Note: This option has *no effect* on polymorphic associations as we cannot reliably +determine the associated object's type without instantiating it. + +Default: `false`. ## Hooks diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index 35ba60c7..b5b95736 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -142,6 +142,7 @@ module ActiveModel # Make JSON API top-level jsonapi member opt-in # ref: http://jsonapi.org/format/#document-top-level config.jsonapi_include_toplevel_object = false + config.jsonapi_use_foreign_key_on_belongs_to_relationship = false config.include_data_default = true # For configuring how serializers are found. diff --git a/lib/active_model_serializers/adapter/json_api/relationship.rb b/lib/active_model_serializers/adapter/json_api/relationship.rb index e2957958..80e1714e 100644 --- a/lib/active_model_serializers/adapter/json_api/relationship.rb +++ b/lib/active_model_serializers/adapter/json_api/relationship.rb @@ -94,7 +94,8 @@ module ActiveModelSerializers end def belongs_to_id_on_self?(association) - association.belongs_to? && + parent_serializer.config.jsonapi_use_foreign_key_on_belongs_to_relationship && + association.belongs_to? && parent_serializer.object.respond_to?(association.reflection.foreign_key) end end From b41451c9bf14dd2a24a3fe03362f0ac89bf887d1 Mon Sep 17 00:00:00 2001 From: Benjamin Fleischer Date: Mon, 6 Nov 2017 22:10:00 -0600 Subject: [PATCH 2/2] Make tests pass --- test/serializers/associations_test.rb | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/test/serializers/associations_test.rb b/test/serializers/associations_test.rb index 5d195cbc..46a2959d 100644 --- a/test/serializers/associations_test.rb +++ b/test/serializers/associations_test.rb @@ -159,7 +159,14 @@ module ActiveModel end end - actual = serializable(post, adapter: :json_api, serializer: BelongsToBlogModelSerializer).as_json + actual = + begin + original_option = BelongsToBlogModelSerializer.config.jsonapi_use_foreign_key_on_belongs_to_relationship + BelongsToBlogModelSerializer.config.jsonapi_use_foreign_key_on_belongs_to_relationship = true + serializable(post, adapter: :json_api, serializer: BelongsToBlogModelSerializer).as_json + ensure + BelongsToBlogModelSerializer.config.jsonapi_use_foreign_key_on_belongs_to_relationship = original_option + end expected = { data: { id: '1', type: 'posts', relationships: { blog: { data: { id: '5', type: 'blogs' } } } } } assert_equal expected, actual @@ -189,7 +196,14 @@ module ActiveModel } post = BelongsToExternalBlogModel.new(attributes) - actual = serializable(post, adapter: :json_api, serializer: BelongsToExternalBlogModelSerializer).as_json + actual = + begin + original_option = BelongsToExternalBlogModelSerializer.config.jsonapi_use_foreign_key_on_belongs_to_relationship + BelongsToExternalBlogModelSerializer.config.jsonapi_use_foreign_key_on_belongs_to_relationship = true + serializable(post, adapter: :json_api, serializer: BelongsToExternalBlogModelSerializer).as_json + ensure + BelongsToExternalBlogModelSerializer.config.jsonapi_use_foreign_key_on_belongs_to_relationship = original_option + end expected = { data: { id: '1', type: 'posts', relationships: { :'external-blog' => { data: { id: '6', type: 'external-blogs' } } } } } assert_equal expected, actual