diff --git a/lib/jsonapi/active_relation/join_manager.rb b/lib/jsonapi/active_relation/join_manager.rb index 3d1ec34b5..ffa1cf0f1 100644 --- a/lib/jsonapi/active_relation/join_manager.rb +++ b/lib/jsonapi/active_relation/join_manager.rb @@ -147,9 +147,15 @@ def perform_joins(records, options) related_resource_klass = join_details[:related_resource_klass] join_type = relationship_details[:join_type] + join_options = { + relationship: relationship, + relationship_details: relationship_details, + related_resource_klass: related_resource_klass, + } + if relationship == :root unless source_relationship - add_join_details('', {alias: resource_klass._table_name, join_type: :root}) + add_join_details('', {alias: resource_klass._table_name, join_type: :root, join_options: join_options}) end next end @@ -163,7 +169,7 @@ def perform_joins(records, options) options: options) } - details = {alias: self.class.alias_from_arel_node(join_node), join_type: join_type} + details = {alias: self.class.alias_from_arel_node(join_node), join_type: join_type, join_options: join_options} if relationship == source_relationship if relationship.polymorphic? && relationship.belongs_to? diff --git a/lib/jsonapi/active_relation_resource.rb b/lib/jsonapi/active_relation_resource.rb index ed3b89d20..c2056776c 100644 --- a/lib/jsonapi/active_relation_resource.rb +++ b/lib/jsonapi/active_relation_resource.rb @@ -324,6 +324,11 @@ def apply_join(records:, relationship:, resource_type:, join_type:, options:) records = records.joins_left(relation_name) end end + + if relationship.use_related_resource_records_for_joins + records = records.merge(self.records(options)) + end + records end diff --git a/lib/jsonapi/configuration.rb b/lib/jsonapi/configuration.rb index f7e899cfa..834ca1b1c 100644 --- a/lib/jsonapi/configuration.rb +++ b/lib/jsonapi/configuration.rb @@ -39,7 +39,8 @@ class Configuration :default_resource_cache_field, :resource_cache_digest_function, :resource_cache_usage_report_function, - :default_exclude_links + :default_exclude_links, + :use_related_resource_records_for_joins def initialize #:underscored_key, :camelized_key, :dasherized_key, or custom @@ -158,6 +159,11 @@ def initialize # and relationships. Accepts either `:default`, `:none`, or array containing the # specific default links to exclude, which may be `:self` and `:related`. self.default_exclude_links = :none + + # Use a related resource's `records` when performing joins. This setting allows included resources to account for + # permission scopes. It can be overridden explicitly per relationship. Furthermore, specifying a `relation_name` + # on a relationship will cause this setting to be ignored. + self.use_related_resource_records_for_joins = true end def cache_formatters=(bool) @@ -299,6 +305,8 @@ def allow_include=(allow_include) attr_writer :resource_cache_usage_report_function attr_writer :default_exclude_links + + attr_writer :use_related_resource_records_for_joins end class << self diff --git a/lib/jsonapi/relationship.rb b/lib/jsonapi/relationship.rb index a185587c9..5261b6049 100644 --- a/lib/jsonapi/relationship.rb +++ b/lib/jsonapi/relationship.rb @@ -3,7 +3,7 @@ class Relationship attr_reader :acts_as_set, :foreign_key, :options, :name, :class_name, :polymorphic, :always_include_optional_linkage_data, :parent_resource, :eager_load_on_include, :custom_methods, - :inverse_relationship, :allow_include + :inverse_relationship, :allow_include, :use_related_resource_records_for_joins attr_writer :allow_include @@ -23,6 +23,15 @@ def initialize(name, options = {}) @polymorphic_types ||= options[:polymorphic_relations] end + use_related_resource_records_for_joins_default = if options[:relation_name] + false + else + JSONAPI.configuration.use_related_resource_records_for_joins + end + + @use_related_resource_records_for_joins = options.fetch(:use_related_resource_records_for_joins, + use_related_resource_records_for_joins_default) == true + @always_include_optional_linkage_data = options.fetch(:always_include_optional_linkage_data, false) == true @eager_load_on_include = options.fetch(:eager_load_on_include, false) == true @allow_include = options[:allow_include] diff --git a/test/fixtures/active_record.rb b/test/fixtures/active_record.rb index c1f3cc674..6170eca81 100644 --- a/test/fixtures/active_record.rb +++ b/test/fixtures/active_record.rb @@ -1413,7 +1413,7 @@ class PostResource < JSONAPI::Resource has_one :author, class_name: 'Person' has_one :section - has_many :tags, acts_as_set: true, inverse_relationship: :posts, eager_load_on_include: false + has_many :tags, acts_as_set: true, inverse_relationship: :posts has_many :comments, acts_as_set: false, inverse_relationship: :post # Not needed - just for testing @@ -1932,16 +1932,7 @@ class AuthorResource < JSONAPI::Resource model_name 'Person' attributes :name - has_many :books, inverse_relationship: :authors, relation_name: -> (options) { - book_admin = options[:context][:book_admin] || options[:context][:current_user].try(:book_admin) - - if book_admin - :books - else - :not_banned_books - end - } - + has_many :books has_many :book_comments end @@ -1981,6 +1972,9 @@ class BookResource < JSONAPI::Resource } filter :banned, apply: :apply_filter_banned + filter :title, apply: ->(records, value, options) { + records.where('books.title LIKE ?', "#{value[0]}%") + } class << self def books @@ -1992,10 +1986,9 @@ def not_banned_books end def records(options = {}) - context = options[:context] - current_user = context ? context[:current_user] : nil + current_user = options.dig(:context, :current_user) - records = _model_class.all + records = super # Hide the banned books from people who are not book admins unless current_user && current_user.book_admin records = records.where(not_banned_books) @@ -2004,8 +1997,7 @@ def records(options = {}) end def apply_filter_banned(records, value, options) - context = options[:context] - current_user = context ? context[:current_user] : nil + current_user = options.dig(:context, :current_user) # Only book admins might filter for banned books if current_user && current_user.book_admin @@ -2045,7 +2037,7 @@ def approved_comments(approved = true) end def records(options = {}) - current_user = options[:context][:current_user] + current_user = options.dig(:context, :current_user) _model_class.for_user(current_user) end end @@ -2100,7 +2092,7 @@ class PostResource < JSONAPI::Resource has_one :author, class_name: 'Person', exclude_links: [:self, "related"] has_one :section, exclude_links: [:self, :related] - has_many :tags, acts_as_set: true, inverse_relationship: :posts, eager_load_on_include: false, exclude_links: :default + has_many :tags, acts_as_set: true, inverse_relationship: :posts, exclude_links: :default has_many :comments, acts_as_set: false, inverse_relationship: :post, exclude_links: ["self", :related] end diff --git a/test/integration/book_authorization_test.rb b/test/integration/book_authorization_test.rb new file mode 100644 index 000000000..6327f2ba3 --- /dev/null +++ b/test/integration/book_authorization_test.rb @@ -0,0 +1,38 @@ +require File.expand_path('../../test_helper', __FILE__) + +class BookAuthorizationTest < ActionDispatch::IntegrationTest + def setup + DatabaseCleaner.start + JSONAPI.configuration.json_key_format = :underscored_key + JSONAPI.configuration.route_format = :underscored_route + Api::V2::BookResource.paginator :offset + end + + def test_restricted_records_primary + Api::V2::BookResource.paginator :none + + # Not a book admin + $test_user = Person.find(1001) + assert_cacheable_jsonapi_get '/api/v2/books?filter[title]=Book%206' + assert_equal 12, json_response['data'].size + + # book_admin + $test_user = Person.find(1005) + assert_cacheable_jsonapi_get '/api/v2/books?filter[title]=Book%206' + assert_equal 111, json_response['data'].size + end + + def test_restricted_records_related + Api::V2::BookResource.paginator :none + + # Not a book admin + $test_user = Person.find(1001) + assert_cacheable_jsonapi_get '/api/v2/authors/1002/books' + assert_equal 1, json_response['data'].size + + # book_admin + $test_user = Person.find(1005) + assert_cacheable_jsonapi_get '/api/v2/authors/1002/books' + assert_equal 2, json_response['data'].size + end +end diff --git a/test/unit/active_relation_resource_finder/join_manager_test.rb b/test/unit/active_relation_resource_finder/join_manager_test.rb index 840c90ee2..2b38d0642 100644 --- a/test/unit/active_relation_resource_finder/join_manager_test.rb +++ b/test/unit/active_relation_resource_finder/join_manager_test.rb @@ -23,7 +23,7 @@ def test_no_added_joins records = join_manager.join(records, {}) assert_equal 'SELECT "posts".* FROM "posts"', records.to_sql - assert_hash_equals({alias: 'posts', join_type: :root}, join_manager.source_join_details) + assert_hash_equals({alias: 'posts', join_type: :root}, join_manager.source_join_details.except!(:join_options)) end def test_add_single_join @@ -32,8 +32,22 @@ def test_add_single_join records = PostResource.records({}) records = join_manager.join(records, {}) assert_equal 'SELECT "posts".* FROM "posts" LEFT OUTER JOIN "posts_tags" ON "posts_tags"."post_id" = "posts"."id" LEFT OUTER JOIN "tags" ON "tags"."id" = "posts_tags"."tag_id"', records.to_sql - assert_hash_equals({alias: 'posts', join_type: :root}, join_manager.source_join_details) - assert_hash_equals({alias: 'tags', join_type: :left}, join_manager.join_details_by_relationship(PostResource._relationship(:tags))) + assert_hash_equals({alias: 'posts', join_type: :root}, join_manager.source_join_details.except!(:join_options)) + assert_hash_equals({alias: 'tags', join_type: :left}, join_manager.join_details_by_relationship(PostResource._relationship(:tags)).except!(:join_options)) + end + + def test_joins_have_join_options + filters = {'tags' => ['1']} + join_manager = JSONAPI::ActiveRelation::JoinManager.new(resource_klass: PostResource, filters: filters) + records = PostResource.records({}) + records = join_manager.join(records, {}) + assert_equal 'SELECT "posts".* FROM "posts" LEFT OUTER JOIN "posts_tags" ON "posts_tags"."post_id" = "posts"."id" LEFT OUTER JOIN "tags" ON "tags"."id" = "posts_tags"."tag_id"', records.to_sql + + source_join_options = join_manager.source_join_details[:join_options] + assert_array_equals [:relationship, :relationship_details, :related_resource_klass], source_join_options.keys + + relationship_join_options = join_manager.join_details_by_relationship(PostResource._relationship(:tags))[:join_options] + assert_array_equals [:relationship, :relationship_details, :related_resource_klass], relationship_join_options.keys end def test_add_single_sort_join @@ -43,8 +57,8 @@ def test_add_single_sort_join records = join_manager.join(records, {}) assert_equal 'SELECT "posts".* FROM "posts" LEFT OUTER JOIN "posts_tags" ON "posts_tags"."post_id" = "posts"."id" LEFT OUTER JOIN "tags" ON "tags"."id" = "posts_tags"."tag_id"', records.to_sql - assert_hash_equals({alias: 'posts', join_type: :root}, join_manager.source_join_details) - assert_hash_equals({alias: 'tags', join_type: :left}, join_manager.join_details_by_relationship(PostResource._relationship(:tags))) + assert_hash_equals({alias: 'posts', join_type: :root}, join_manager.source_join_details.except!(:join_options)) + assert_hash_equals({alias: 'tags', join_type: :left}, join_manager.join_details_by_relationship(PostResource._relationship(:tags)).except!(:join_options)) end def test_add_single_sort_and_filter_join @@ -54,8 +68,8 @@ def test_add_single_sort_and_filter_join records = PostResource.records({}) records = join_manager.join(records, {}) assert_equal 'SELECT "posts".* FROM "posts" LEFT OUTER JOIN "posts_tags" ON "posts_tags"."post_id" = "posts"."id" LEFT OUTER JOIN "tags" ON "tags"."id" = "posts_tags"."tag_id"', records.to_sql - assert_hash_equals({alias: 'posts', join_type: :root}, join_manager.source_join_details) - assert_hash_equals({alias: 'tags', join_type: :left}, join_manager.join_details_by_relationship(PostResource._relationship(:tags))) + assert_hash_equals({alias: 'posts', join_type: :root}, join_manager.source_join_details.except!(:join_options)) + assert_hash_equals({alias: 'tags', join_type: :left}, join_manager.join_details_by_relationship(PostResource._relationship(:tags)).except!(:join_options)) end def test_add_sibling_joins @@ -69,9 +83,9 @@ def test_add_sibling_joins records = join_manager.join(records, {}) assert_equal 'SELECT "posts".* FROM "posts" LEFT OUTER JOIN "posts_tags" ON "posts_tags"."post_id" = "posts"."id" LEFT OUTER JOIN "tags" ON "tags"."id" = "posts_tags"."tag_id" LEFT OUTER JOIN "people" ON "people"."id" = "posts"."author_id"', records.to_sql - assert_hash_equals({alias: 'posts', join_type: :root}, join_manager.source_join_details) - assert_hash_equals({alias: 'tags', join_type: :left}, join_manager.join_details_by_relationship(PostResource._relationship(:tags))) - assert_hash_equals({alias: 'people', join_type: :left}, join_manager.join_details_by_relationship(PostResource._relationship(:author))) + assert_hash_equals({alias: 'posts', join_type: :root}, join_manager.source_join_details.except!(:join_options)) + assert_hash_equals({alias: 'tags', join_type: :left}, join_manager.join_details_by_relationship(PostResource._relationship(:tags)).except!(:join_options)) + assert_hash_equals({alias: 'people', join_type: :left}, join_manager.join_details_by_relationship(PostResource._relationship(:author)).except!(:join_options)) end @@ -82,7 +96,7 @@ def test_add_joins_source_relationship records = join_manager.join(records, {}) assert_equal 'SELECT "posts".* FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id"', records.to_sql - assert_hash_equals({alias: 'comments', join_type: :inner}, join_manager.source_join_details) + assert_hash_equals({alias: 'comments', join_type: :inner}, join_manager.source_join_details.except!(:join_options)) end @@ -96,7 +110,7 @@ def test_add_joins_source_relationship_with_custom_apply assert_equal sql, records.to_sql - assert_hash_equals({alias: 'comments', join_type: :inner}, join_manager.source_join_details) + assert_hash_equals({alias: 'comments', join_type: :inner}, join_manager.source_join_details.except!(:join_options)) end def test_add_nested_scoped_joins @@ -110,11 +124,11 @@ def test_add_nested_scoped_joins records = Api::V10::PostResource.records({}) records = join_manager.join(records, {}) - assert_hash_equals({alias: 'posts', join_type: :root}, join_manager.source_join_details) - assert_hash_equals({alias: 'comments', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::PostResource._relationship(:comments))) - assert_hash_equals({alias: 'authors_comments', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::CommentResource._relationship(:author))) - assert_hash_equals({alias: 'tags', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::CommentResource._relationship(:tags))) - assert_hash_equals({alias: 'people', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::PostResource._relationship(:author))) + assert_hash_equals({alias: 'posts', join_type: :root}, join_manager.source_join_details.except!(:join_options)) + assert_hash_equals({alias: 'comments', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::PostResource._relationship(:comments)).except!(:join_options)) + assert_hash_equals({alias: 'authors_comments', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::CommentResource._relationship(:author)).except!(:join_options)) + assert_hash_equals({alias: 'tags', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::CommentResource._relationship(:tags)).except!(:join_options)) + assert_hash_equals({alias: 'people', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::PostResource._relationship(:author)).except!(:join_options)) # Now test with different order for the filters filters = { @@ -127,11 +141,11 @@ def test_add_nested_scoped_joins records = Api::V10::PostResource.records({}) records = join_manager.join(records, {}) - assert_hash_equals({alias: 'posts', join_type: :root}, join_manager.source_join_details) - assert_hash_equals({alias: 'comments', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::PostResource._relationship(:comments))) - assert_hash_equals({alias: 'authors_comments', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::CommentResource._relationship(:author))) - assert_hash_equals({alias: 'tags', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::CommentResource._relationship(:tags))) - assert_hash_equals({alias: 'people', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::PostResource._relationship(:author))) + assert_hash_equals({alias: 'posts', join_type: :root}, join_manager.source_join_details.except!(:join_options)) + assert_hash_equals({alias: 'comments', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::PostResource._relationship(:comments)).except!(:join_options)) + assert_hash_equals({alias: 'authors_comments', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::CommentResource._relationship(:author)).except!(:join_options)) + assert_hash_equals({alias: 'tags', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::CommentResource._relationship(:tags)).except!(:join_options)) + assert_hash_equals({alias: 'people', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::PostResource._relationship(:author)).except!(:join_options)) end def test_add_nested_joins_with_fields @@ -145,11 +159,11 @@ def test_add_nested_joins_with_fields records = Api::V10::PostResource.records({}) records = join_manager.join(records, {}) - assert_hash_equals({alias: 'posts', join_type: :root}, join_manager.source_join_details) - assert_hash_equals({alias: 'comments', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::PostResource._relationship(:comments))) - assert_hash_equals({alias: 'authors_comments', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::CommentResource._relationship(:author))) - assert_hash_equals({alias: 'tags', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::CommentResource._relationship(:tags))) - assert_hash_equals({alias: 'people', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::PostResource._relationship(:author))) + assert_hash_equals({alias: 'posts', join_type: :root}, join_manager.source_join_details.except!(:join_options)) + assert_hash_equals({alias: 'comments', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::PostResource._relationship(:comments)).except!(:join_options)) + assert_hash_equals({alias: 'authors_comments', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::CommentResource._relationship(:author)).except!(:join_options)) + assert_hash_equals({alias: 'tags', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::CommentResource._relationship(:tags)).except!(:join_options)) + assert_hash_equals({alias: 'people', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::PostResource._relationship(:author)).except!(:join_options)) end def test_add_joins_with_sub_relationship @@ -160,10 +174,10 @@ def test_add_joins_with_sub_relationship records = Api::V10::PostResource.records({}) records = join_manager.join(records, {}) - assert_hash_equals({alias: 'comments', join_type: :inner}, join_manager.source_join_details) - assert_hash_equals({alias: 'comments', join_type: :inner}, join_manager.join_details_by_relationship(Api::V10::PostResource._relationship(:comments))) - assert_hash_equals({alias: 'tags', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::CommentResource._relationship(:tags))) - assert_hash_equals({alias: 'comments_people', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::PersonResource._relationship(:comments))) + assert_hash_equals({alias: 'comments', join_type: :inner}, join_manager.source_join_details.except!(:join_options)) + assert_hash_equals({alias: 'comments', join_type: :inner}, join_manager.join_details_by_relationship(Api::V10::PostResource._relationship(:comments)).except!(:join_options)) + assert_hash_equals({alias: 'tags', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::CommentResource._relationship(:tags)).except!(:join_options)) + assert_hash_equals({alias: 'comments_people', join_type: :left}, join_manager.join_details_by_relationship(Api::V10::PersonResource._relationship(:comments)).except!(:join_options)) end def test_add_joins_with_sub_relationship_and_filters @@ -181,11 +195,11 @@ def test_add_joins_with_sub_relationship_and_filters records = PostResource.records({}) records = join_manager.join(records, {}) - assert_hash_equals({alias: 'comments', join_type: :inner}, join_manager.source_join_details) - assert_hash_equals({alias: 'comments', join_type: :inner}, join_manager.join_details_by_relationship(PostResource._relationship(:comments))) - assert_hash_equals({alias: 'people', join_type: :left}, join_manager.join_details_by_relationship(CommentResource._relationship(:author))) - assert_hash_equals({alias: 'tags', join_type: :left}, join_manager.join_details_by_relationship(CommentResource._relationship(:tags))) - assert_hash_equals({alias: 'comments_people', join_type: :left}, join_manager.join_details_by_relationship(PersonResource._relationship(:comments))) + assert_hash_equals({alias: 'comments', join_type: :inner}, join_manager.source_join_details.except!(:join_options)) + assert_hash_equals({alias: 'comments', join_type: :inner}, join_manager.join_details_by_relationship(PostResource._relationship(:comments)).except!(:join_options)) + assert_hash_equals({alias: 'people', join_type: :left}, join_manager.join_details_by_relationship(CommentResource._relationship(:author)).except!(:join_options)) + assert_hash_equals({alias: 'tags', join_type: :left}, join_manager.join_details_by_relationship(CommentResource._relationship(:tags)).except!(:join_options)) + assert_hash_equals({alias: 'comments_people', join_type: :left}, join_manager.join_details_by_relationship(PersonResource._relationship(:comments)).except!(:join_options)) end def test_polymorphic_join_belongs_to_just_source @@ -196,10 +210,10 @@ def test_polymorphic_join_belongs_to_just_source records = join_manager.join(records, {}) # assert_equal 'SELECT "pictures".* FROM "pictures" LEFT OUTER JOIN "products" ON "products"."id" = "pictures"."imageable_id" AND "pictures"."imageable_type" = \'Product\' LEFT OUTER JOIN "documents" ON "documents"."id" = "pictures"."imageable_id" AND "pictures"."imageable_type" = \'Document\'', records.to_sql - assert_hash_equals({alias: 'products', join_type: :left}, join_manager.source_join_details('products')) - assert_hash_equals({alias: 'documents', join_type: :left}, join_manager.source_join_details('documents')) - assert_hash_equals({alias: 'products', join_type: :left}, join_manager.join_details_by_polymorphic_relationship(PictureResource._relationship(:imageable), 'products')) - assert_hash_equals({alias: 'documents', join_type: :left}, join_manager.join_details_by_polymorphic_relationship(PictureResource._relationship(:imageable), 'documents')) + assert_hash_equals({alias: 'products', join_type: :left}, join_manager.source_join_details('products').except!(:join_options)) + assert_hash_equals({alias: 'documents', join_type: :left}, join_manager.source_join_details('documents').except!(:join_options)) + assert_hash_equals({alias: 'products', join_type: :left}, join_manager.join_details_by_polymorphic_relationship(PictureResource._relationship(:imageable), 'products').except!(:join_options)) + assert_hash_equals({alias: 'documents', join_type: :left}, join_manager.join_details_by_polymorphic_relationship(PictureResource._relationship(:imageable), 'documents').except!(:join_options)) end def test_polymorphic_join_belongs_to_filter @@ -210,9 +224,9 @@ def test_polymorphic_join_belongs_to_filter records = join_manager.join(records, {}) # assert_equal 'SELECT "pictures".* FROM "pictures" LEFT OUTER JOIN "products" ON "products"."id" = "pictures"."imageable_id" AND "pictures"."imageable_type" = \'Product\' LEFT OUTER JOIN "documents" ON "documents"."id" = "pictures"."imageable_id" AND "pictures"."imageable_type" = \'Document\'', records.to_sql - assert_hash_equals({alias: 'pictures', join_type: :root}, join_manager.source_join_details) - assert_hash_equals({alias: 'products', join_type: :left}, join_manager.join_details_by_polymorphic_relationship(PictureResource._relationship(:imageable), 'products')) - assert_hash_equals({alias: 'documents', join_type: :left}, join_manager.join_details_by_polymorphic_relationship(PictureResource._relationship(:imageable), 'documents')) + assert_hash_equals({alias: 'pictures', join_type: :root}, join_manager.source_join_details.except!(:join_options)) + assert_hash_equals({alias: 'products', join_type: :left}, join_manager.join_details_by_polymorphic_relationship(PictureResource._relationship(:imageable), 'products').except!(:join_options)) + assert_hash_equals({alias: 'documents', join_type: :left}, join_manager.join_details_by_polymorphic_relationship(PictureResource._relationship(:imageable), 'documents').except!(:join_options)) end def test_polymorphic_join_belongs_to_filter_on_resource @@ -228,9 +242,9 @@ def test_polymorphic_join_belongs_to_filter_on_resource records = PictureResource.records({}) records = join_manager.join(records, {}) - assert_hash_equals({alias: 'pictures', join_type: :root}, join_manager.source_join_details) - assert_hash_equals({alias: 'products', join_type: :left}, join_manager.join_details_by_polymorphic_relationship(PictureResource._relationship(:imageable), 'products')) - assert_hash_equals({alias: 'documents', join_type: :left}, join_manager.join_details_by_polymorphic_relationship(PictureResource._relationship(:imageable), 'documents')) - assert_hash_equals({alias: 'file_properties', join_type: :left}, join_manager.join_details_by_relationship(PictureResource._relationship(:file_properties))) + assert_hash_equals({alias: 'pictures', join_type: :root}, join_manager.source_join_details.except!(:join_options)) + assert_hash_equals({alias: 'products', join_type: :left}, join_manager.join_details_by_polymorphic_relationship(PictureResource._relationship(:imageable), 'products').except!(:join_options)) + assert_hash_equals({alias: 'documents', join_type: :left}, join_manager.join_details_by_polymorphic_relationship(PictureResource._relationship(:imageable), 'documents').except!(:join_options)) + assert_hash_equals({alias: 'file_properties', join_type: :left}, join_manager.join_details_by_relationship(PictureResource._relationship(:file_properties)).except!(:join_options)) end end diff --git a/test/unit/resource/relationship_test.rb b/test/unit/resource/relationship_test.rb index a98d26601..e030ff309 100644 --- a/test/unit/resource/relationship_test.rb +++ b/test/unit/resource/relationship_test.rb @@ -18,6 +18,41 @@ def self.is_admin(context) end end +class TestRelationshipOptionsPostsResource < JSONAPI::Resource + model_name 'Post' + has_one :author, allow_include: :is_admin, use_related_resource_records_for_joins: false +end + +class RelationshipTest < ActiveSupport::TestCase + def test_use_related_resource_records_for_joins_enabled_by_default + assert JSONAPI.configuration.use_related_resource_records_for_joins == true + relationship = JSONAPI::Relationship::ToOne.new(:author) + assert relationship.use_related_resource_records_for_joins + end + + def test_use_related_resource_records_for_joins_can_be_disabled_globally + original_config = JSONAPI.configuration.dup + + JSONAPI.configuration.use_related_resource_records_for_joins = false + relationship = JSONAPI::Relationship::ToOne.new(:author) + assert relationship.use_related_resource_records_for_joins == false + ensure + JSONAPI.configuration = original_config + end + + def test_use_related_resource_records_for_joins_is_disabled_by_deafult_with_relation_name + relationship = JSONAPI::Relationship::ToOne.new(:author, + relation_name: "foo" ) + refute relationship.use_related_resource_records_for_joins + end + + def test_use_related_resource_records_for_joins_can_be_disabled + relationship = JSONAPI::Relationship::ToOne.new(:author, + use_related_resource_records_for_joins: false ) + refute relationship.use_related_resource_records_for_joins + end +end + class HasOneRelationshipTest < ActiveSupport::TestCase def test_polymorphic_type