Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
9 changes: 6 additions & 3 deletions lib/jsonapi/resource_common.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1199,13 +1199,16 @@ def define_relationship_methods(relationship_name, relationship_klass, options)

def define_foreign_key_setter(relationship)
if relationship.polymorphic?
define_on_resource "format_model_polymorphic_type" do |resource_object_type|
Comment thread
bf4 marked this conversation as resolved.
Outdated
resource_object_type&.to_s&.classify
end
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.public_send("#{relationship.foreign_key}=", v[:id])
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.

I removed the instantiation of the method object here in favor of public send since we couldn't think of a reason the method object would be preferable

_model.public_send("#{relationship.polymorphic_type}=", format_model_polymorphic_type(v[:type]))
end
else
define_on_resource "#{relationship.foreign_key}=" do |value|
_model.method("#{relationship.foreign_key}=").call(value)
_model.public_send("#{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