Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: format model polymorphic type from resource object type #1435

Merged
merged 8 commits into from
Jan 22, 2024
2 changes: 1 addition & 1 deletion lib/jsonapi/acts_as_resource_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ def base_url
end

def resource_klass_name
@resource_klass_name ||= "#{self.class.name.underscore.sub(/_controller$/, '').singularize}_resource".camelize
@resource_klass_name ||= "#{self.class.name.underscore.sub(/_controller$/, '').classify}Resource"
end

def verify_content_type_header
Expand Down
2 changes: 1 addition & 1 deletion lib/jsonapi/link_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def build_engine

begin
unless scopes.empty?
"#{ scopes.first.to_s.camelize }::Engine".safe_constantize
"#{ scopes.first.to_s.classify }::Engine".safe_constantize
end

# :nocov:
Expand Down
4 changes: 2 additions & 2 deletions lib/jsonapi/relationship.rb
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ class ToOne < Relationship

def initialize(name, options = {})
super
@class_name = options.fetch(:class_name, name.to_s.camelize)
@class_name = options.fetch(:class_name, name.to_s.classify)
@foreign_key ||= "#{name}_id".to_sym
@foreign_key_on = options.fetch(:foreign_key_on, :self)
# if parent_resource
Expand Down Expand Up @@ -231,7 +231,7 @@ class ToMany < Relationship

def initialize(name, options = {})
super
@class_name = options.fetch(:class_name, name.to_s.camelize.singularize)
@class_name = options.fetch(:class_name, name.to_s.classify)
@foreign_key ||= "#{name.to_s.singularize}_ids".to_sym
@reflect = options.fetch(:reflect, true) == true
# if parent_resource
Expand Down
12 changes: 8 additions & 4 deletions lib/jsonapi/resource_common.rb
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,7 @@ def resource_klass_for_model(model)
end

def _resource_name_from_type(type)
"#{type.to_s.underscore.singularize}_resource".camelize
"#{type.to_s.classify}Resource"
end

def resource_type_for(model)
Expand All @@ -578,6 +578,10 @@ def resource_type_for(model)
end
end

def polymorphic_type_for(model_name)
model_name&.to_s&.classify
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

💯

end

attr_accessor :_attributes,
:_relationships,
:_type,
Expand Down Expand Up @@ -1200,12 +1204,12 @@ 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.public_send("#{relationship.foreign_key}=", v[:id])
Copy link
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}=", self.class.polymorphic_type_for(v[:type]))
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

🔨 the fix

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
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