Skip to content

Commit ce1236c

Browse files
committed
Singularize and capitalize polymorphic types for presence validation
Singularizing polymorphic association types allows you to use plural or singular type values in your requests as allowed by JSON API. Because ActiveRecord calls #constantize on the polymorphic association type when you use the hash to create a new model if you validate the presence of the related model, you must capitalize the type to avoid a NameError.
1 parent 61412d8 commit ce1236c

File tree

7 files changed

+49
-6
lines changed

7 files changed

+49
-6
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ Features:
2424
- [#1340](https://github.com/rails-api/active_model_serializers/pull/1340) Add support for resource-level meta. (@beauby)
2525

2626
Fixes:
27+
- [#1615](https://github.com/rails-api/active_model_serializers/pull/1615) Allow plural polymorphic relationship types when validating presence. (@dpdawson)
28+
- [#1615](https://github.com/rails-api/active_model_serializers/pull/1615) Capitalize polymorphic association types to prevent error when ActiveRecord constantizes them when validating presence. (@dpdawson)
2729
- [#1570](https://github.com/rails-api/active_model_serializers/pull/1570) Fixed pagination issue with last page size. (@bmorrall)
2830
- [#1516](https://github.com/rails-api/active_model_serializers/pull/1516) No longer return a nil href when only
2931
adding meta to a relationship link. (@groyoh)

docs/general/deserialization.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ ActiveModelSerializers::Deserialization
9191
# title: 'Title 1',
9292
# published_at: '2015-12-20',
9393
# author_id: '2',
94-
# author_type: 'user'
94+
# author_type: 'User'
9595
# }
9696
```
9797

lib/active_model_serializers/adapter/json_api/deserialization.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ module Deserialization
6969
# # title: 'Title 1',
7070
# # published_at: '2015-12-20',
7171
# # author_id: '2',
72-
# # author_type: 'people'
72+
# # author_type: 'People'
7373
# # }
7474
#
7575
def parse!(document, options = {})
@@ -188,7 +188,7 @@ def parse_relationship(assoc_name, assoc_data, options)
188188
end
189189

190190
polymorphic = (options[:polymorphic] || []).include?(assoc_name.to_sym)
191-
hash["#{prefix_key}_type".to_sym] = assoc_data['type'] if polymorphic
191+
hash["#{prefix_key}_type".to_sym] = assoc_data['type'].singularize.capitalize if polymorphic
192192

193193
hash
194194
end

test/active_record_test.rb

+33
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,38 @@ class ActiveRecordTest < ActiveSupport::TestCase
55

66
def setup
77
@resource = ARModels::Post.new
8+
@image = Image.create
9+
end
10+
11+
def test_active_model_record_with_validated_polymorphic_relationship_creation
12+
picture = Picture.create!(picture_params)
13+
14+
assert_equal(@image, picture.imageable)
15+
end
16+
17+
private
18+
19+
def picture_params
20+
params = ActionController::Parameters.new({
21+
data: {
22+
attributes: {
23+
title: 'Picture Title'
24+
},
25+
relationships: {
26+
imageable: {
27+
data: {
28+
type: 'images',
29+
id: @image.id
30+
}
31+
},
32+
},
33+
type: 'pictures'
34+
}
35+
})
36+
37+
ActiveModelSerializers::Deserialization.jsonapi_parse!(
38+
params.to_unsafe_h,
39+
polymorphic: [:imageable]
40+
)
841
end
942
end

test/adapter/json_api/parse_test.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ def test_polymorphic
125125
src: 'http://example.com/images/productivity.png',
126126
author_id: nil,
127127
photographer_id: '9',
128-
photographer_type: 'people',
128+
photographer_type: 'Person',
129129
comment_ids: %w(1 2)
130130
}
131131
assert_equal(expected, parsed_hash)

test/fixtures/active_record.rb

+4-2
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@
2525
end
2626
create_table :pictures, force: true do |t|
2727
t.string :title
28-
t.string :imageable_type
29-
t.string :imageable_id
28+
t.references :imageable, polymorphic: true
29+
t.timestamp null: false
30+
end
31+
create_table :images, force: true do |t|
3032
t.timestamp null: false
3133
end
3234
end

test/fixtures/poro.rb

+6
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,12 @@ class Employee < ActiveRecord::Base
7878

7979
class Picture < ActiveRecord::Base
8080
belongs_to :imageable, polymorphic: true
81+
82+
validates :imageable, presence: true
83+
end
84+
85+
class Image < ActiveRecord::Base
86+
has_many :pictures, as: :imageable
8187
end
8288

8389
module Spam; end

0 commit comments

Comments
 (0)