Skip to content

Commit 64fa010

Browse files
committed
Add test for Issue JSONAPI-Resources#1473: Polymorphic has_many relationships
Issue JSONAPI-Resources#1473 reported problems with polymorphic has_many relationships in v0-11-dev branch. This test verifies that the current master branch handles these relationships correctly. Test scenario: - Article has_many :article_comments, as: :commentable - ArticleComment belongs_to :commentable, polymorphic: true - ArticleResource has_many :article_comments, foreign_key_on: :related The test confirms that including polymorphic has_many relationships works without attempting invalid inverse joins. Note: This issue appears to be specific to v0-11-dev branch and does not affect the current master branch. Related: https://github.com/cerebris/jsonapi-resources/issues/1473
1 parent e057af8 commit 64fa010

4 files changed

Lines changed: 189 additions & 0 deletions

File tree

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
require File.expand_path('../../test_helper', __FILE__)
2+
3+
# Test for Issue #1473: Inverse polymorphic relationship error
4+
# https://github.com/cerebris/jsonapi-resources/issues/1473
5+
6+
class ArticlesControllerTest < ActionController::TestCase
7+
def setup
8+
DatabaseCleaner.start
9+
JSONAPI.configuration.json_key_format = :underscored_key
10+
@article = Article.create!(title: 'Test Article')
11+
@comment1 = ArticleComment.create!(
12+
content: 'First comment',
13+
commentable: @article
14+
)
15+
@comment2 = ArticleComment.create!(
16+
content: 'Second comment',
17+
commentable: @article
18+
)
19+
end
20+
21+
def teardown
22+
DatabaseCleaner.clean
23+
end
24+
25+
# Test that including polymorphic has_many relationships works
26+
# Issue #1473 reported that this would fail with:
27+
# "Can't join 'ArticleComment' to association named 'article'"
28+
def test_index_with_polymorphic_has_many_include
29+
get :index, params: { include: 'article_comments' }
30+
assert_response :success
31+
assert_equal 1, json_response['data'].size
32+
assert json_response['included'], "Should have included resources"
33+
assert_equal 2, json_response['included'].size, "Should include 2 comments"
34+
end
35+
36+
def test_show_with_polymorphic_has_many_include
37+
get :show, params: { id: @article.id, include: 'article_comments' }
38+
assert_response :success
39+
assert_equal @article.id.to_s, json_response['data']['id']
40+
assert json_response['included'], "Should have included resources"
41+
assert_equal 2, json_response['included'].size, "Should include 2 comments"
42+
end
43+
end

test/fixtures/active_record.rb

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,18 @@
429429
t.integer :version
430430
t.timestamps null: false
431431
end
432+
433+
# Tables for testing Issue #1473: Polymorphic has_many with foreign_key_on: :related
434+
create_table :articles, force: true do |t|
435+
t.string :title
436+
t.timestamps null: false
437+
end
438+
439+
create_table :article_comments, force: true do |t|
440+
t.text :content
441+
t.references :commentable, polymorphic: true, index: true
442+
t.timestamps null: false
443+
end
432444
end
433445

434446
### MODELS
@@ -868,6 +880,15 @@ class ListItem < ActiveRecord::Base
868880
belongs_to :list, inverse_of: :items
869881
end
870882

883+
# Models for testing Issue #1473: Polymorphic has_many with foreign_key_on: :related
884+
class Article < ActiveRecord::Base
885+
has_many :article_comments, as: :commentable
886+
end
887+
888+
class ArticleComment < ActiveRecord::Base
889+
belongs_to :commentable, polymorphic: true
890+
end
891+
871892
### CONTROLLERS
872893
class SessionsController < ActionController::Base
873894
include JSONAPI::ActsAsResourceController
@@ -1230,6 +1251,13 @@ class IndicatorsController < JSONAPI::ResourceController
12301251
class RobotsController < JSONAPI::ResourceController
12311252
end
12321253

1254+
# Controllers for testing Issue #1473
1255+
class ArticlesController < JSONAPI::ResourceController
1256+
end
1257+
1258+
class ArticleCommentsController < JSONAPI::ResourceController
1259+
end
1260+
12331261
### RESOURCES
12341262
class BaseResource < JSONAPI::Resource
12351263
abstract
@@ -2691,6 +2719,17 @@ class RobotResource < ::JSONAPI::Resource
26912719
end
26922720
end
26932721

2722+
# Resources for testing Issue #1473: Polymorphic has_many with foreign_key_on: :related
2723+
class ArticleResource < JSONAPI::Resource
2724+
attribute :title
2725+
has_many :article_comments, foreign_key_on: :related
2726+
end
2727+
2728+
class ArticleCommentResource < JSONAPI::Resource
2729+
attribute :content
2730+
has_one :commentable, polymorphic: true
2731+
end
2732+
26942733
### PORO Data - don't do this in a production app
26952734
$breed_data = BreedData.new
26962735
$breed_data.add(Breed.new(0, 'persian'))

test/test_helper.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,10 @@ class CatResource < JSONAPI::Resource
340340
jsonapi_resources :employees
341341
jsonapi_resources :robots
342342

343+
# Routes for testing Issue #1473
344+
jsonapi_resources :articles
345+
jsonapi_resources :article_comments
346+
343347
jsonapi_resources :lists
344348
jsonapi_resources :list_items
345349

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
require File.expand_path('../../../test_helper', __FILE__)
2+
3+
# Test for Issue #1473: Inverse polymorphic relationship error
4+
# https://github.com/cerebris/jsonapi-resources/issues/1473
5+
#
6+
# This test reproduces the scenario where:
7+
# - Article has_many :article_comments, as: :commentable
8+
# - ArticleComment belongs_to :commentable, polymorphic: true
9+
# - ArticleResource has_many :article_comments, foreign_key_on: :related
10+
# - Requesting articles?include=article_comments should work without
11+
# attempting to use inverse joins like ArticleComment.joins(:article)
12+
13+
class PolymorphicHasManyTest < ActiveSupport::TestCase
14+
def setup
15+
DatabaseCleaner.start
16+
# Create test data
17+
@article = Article.create!(title: 'Test Article')
18+
@comment1 = ArticleComment.create!(
19+
content: 'First comment',
20+
commentable: @article
21+
)
22+
@comment2 = ArticleComment.create!(
23+
content: 'Second comment',
24+
commentable: @article
25+
)
26+
end
27+
28+
def teardown
29+
DatabaseCleaner.clean
30+
end
31+
32+
def test_polymorphic_has_many_find_fragments_with_include
33+
# This test verifies that we can include polymorphic has_many relationships
34+
# with foreign_key_on: :related without attempting invalid inverse joins
35+
36+
resource_klass = ArticleResource
37+
context = {}
38+
39+
# Create include directives for article_comments
40+
include_directives = JSONAPI::IncludeDirective.new(
41+
resource_klass,
42+
['article_comments'],
43+
allow_remote_includes: false
44+
)
45+
46+
# Find fragments should not raise an error about missing inverse relationship
47+
assert_nothing_raised do
48+
fragments = resource_klass.find_fragments(
49+
{},
50+
{
51+
context: context,
52+
include_directives: include_directives
53+
}
54+
)
55+
56+
assert fragments.any?, "Should find article fragments"
57+
end
58+
end
59+
60+
def test_polymorphic_has_many_resource_set_populate
61+
# Test that populating a resource set with polymorphic includes works correctly
62+
63+
resource_klass = ArticleResource
64+
context = {}
65+
66+
# Find the article fragments
67+
fragments = resource_klass.find_fragments({}, { context: context })
68+
assert fragments.any?, "Should find article fragments"
69+
70+
# Create include directives
71+
include_directives = JSONAPI::IncludeDirective.new(
72+
resource_klass,
73+
['article_comments'],
74+
allow_remote_includes: false
75+
)
76+
77+
# Create and populate resource set
78+
resource_set = JSONAPI::ResourceSet.new(resource_klass)
79+
fragments.each do |fragment|
80+
resource_set.add_resource_fragment(fragment, include_directives)
81+
end
82+
83+
# This should not raise "Can't join 'ArticleComment' to association named 'article'"
84+
assert_nothing_raised do
85+
resource_set.populate!(context)
86+
end
87+
88+
# Verify that the article_comments are included
89+
primary_resources = resource_set.resource_set_by_resource_klass_and_id
90+
assert primary_resources[resource_klass].any?, "Should have article resources"
91+
end
92+
93+
def test_polymorphic_has_many_records_includes_work
94+
# Test that the underlying ActiveRecord includes work correctly
95+
96+
# This should use Article.includes(:article_comments), not ArticleComment.joins(:article)
97+
assert_nothing_raised do
98+
articles = Article.includes(:article_comments).to_a
99+
assert_equal 1, articles.size
100+
assert_equal 2, articles.first.article_comments.size
101+
end
102+
end
103+
end

0 commit comments

Comments
 (0)