Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions lib/jsonapi/resource_common.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1200,12 +1200,16 @@ def define_relationship_methods(relationship_name, relationship_klass, options)
def define_foreign_key_setter(relationship)
if relationship.polymorphic?
define_on_resource "#{relationship.foreign_key}=" do |v|
_model.method("#{relationship.foreign_key}=").call(v[:id])
_model.public_send("#{relationship.polymorphic_type}=", v[:type])
_model.assign_attributes(
Comment thread
bf4 marked this conversation as resolved.
Outdated
relationship.foreign_key => v[:id],
relationship.polymorphic_type => v[:type]&.to_s&.classify
Comment thread
bf4 marked this conversation as resolved.
Outdated
)
end
else
define_on_resource "#{relationship.foreign_key}=" do |value|
_model.method("#{relationship.foreign_key}=").call(value)
_model.assign_attributes(
relationship.foreign_key => value
)
end
end
relationship.foreign_key
Expand Down
11 changes: 9 additions & 2 deletions test/fixtures/active_record.rb
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@
t.string :drive_layout
t.string :serial_number
t.integer :person_id
t.references :imageable, polymorphic: true, index: true
t.timestamps null: false
end

Expand Down Expand Up @@ -734,6 +735,9 @@ class Picture < ActiveRecord::Base

class Vehicle < ActiveRecord::Base
belongs_to :person
belongs_to :imageable, polymorphic: true
# belongs_to :document, -> { where( pictures: { imageable_type: 'Document' } ) }, foreign_key: 'imageable_id'
# belongs_to :product, -> { where( pictures: { imageable_type: 'Product' } ) }, foreign_key: 'imageable_id'
end

class Car < Vehicle
Expand All @@ -743,13 +747,13 @@ class Boat < Vehicle
end

class Document < ActiveRecord::Base
has_many :pictures, as: :imageable
has_many :pictures, as: :imageable # polymorphic
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just for greppability

belongs_to :author, class_name: 'Person', foreign_key: 'author_id'
has_one :file_properties, as: :fileable
end

class Product < ActiveRecord::Base
has_many :pictures, as: :imageable
has_many :pictures, as: :imageable # polymorphic
belongs_to :designer, class_name: 'Person', foreign_key: 'designer_id'
has_one :file_properties, as: :fileable
end
Expand Down Expand Up @@ -1336,6 +1340,7 @@ class VehicleResource < JSONAPI::Resource
immutable

has_one :person
has_one :imageable, polymorphic: true
attributes :make, :model, :serial_number
end

Expand Down Expand Up @@ -1915,6 +1920,8 @@ class PreferencesResource < PreferencesResource; end
class SectionResource < SectionResource; end
class TagResource < TagResource; end
class CommentResource < CommentResource; end
class DocumentResource < DocumentResource; end
class ProductResource < ProductResource; end
class VehicleResource < VehicleResource; end
class CarResource < CarResource; end
class BoatResource < BoatResource; end
Expand Down
41 changes: 41 additions & 0 deletions test/integration/requests/request_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,47 @@ def test_post_polymorphic_with_has_many_relationship
assert_equal Car, person.vehicles.fourth.class
end

def test_post_sti_polymorphic_with_has_one_relationship
post '/cars', params:
{
'data' => {
'type' => 'cars',
'attributes' => {
'make' => 'Mazda',
'model' => 'Miata MX5',
'drive_layout' => 'Front Engine RWD',
'serial_number' => '32432adfsfdysua',
},
'relationships' => {
'person' => {
'data' => {
'type' => 'people', 'id' => '1001',
}
},
'imageable' => {
'data' => {
'type' => 'products', 'id' => '1',
}
},
}
}
}.to_json,
headers: {
'CONTENT_TYPE' => JSONAPI::MEDIA_TYPE,
'Accept' => JSONAPI::MEDIA_TYPE
}

assert_jsonapi_response 201

body = JSON.parse(response.body)
car = Vehicle.find(body.dig("data", "id"))

assert_equal "Car", car.type
assert_equal "Mazda", car.make
assert_equal Product, car.imageable.class
assert_equal Person, car.person.class
end

def test_post_polymorphic_invalid_with_wrong_type
post '/people', params:
{
Expand Down