Skip to content

Commit 4c98648

Browse files
committed
Works around primary key being cast due to pluck bug
1 parent d185ebb commit 4c98648

4 files changed

Lines changed: 199 additions & 8 deletions

File tree

lib/jsonapi/active_relation_resource_finder.rb

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,19 +64,19 @@ def find_fragments(filters, options = {})
6464
records = find_records(filters, options)
6565

6666
table_name = _model_class.table_name
67-
pluck_fields = [concat_table_field(table_name, _primary_key)]
67+
pluck_fields = ["#{concat_table_field(table_name, _primary_key)} AS #{table_name}_#{_primary_key}"]
6868

6969
cache_field = attribute_to_model_field(:_cache_field) if options[:cache]
7070
if cache_field
71-
pluck_fields << concat_table_field(table_name, cache_field[:name])
71+
pluck_fields << "#{concat_table_field(table_name, cache_field[:name])} AS #{table_name}_#{cache_field[:name]}"
7272
end
7373

7474
model_fields = {}
7575
attributes = options[:attributes]
7676
attributes.try(:each) do |attribute|
7777
model_field = attribute_to_model_field(attribute)
7878
model_fields[attribute] = model_field
79-
pluck_fields << concat_table_field(table_name, model_field[:name])
79+
pluck_fields << "#{concat_table_field(table_name, model_field[:name])} AS #{table_name}_#{model_field[:name]}"
8080
end
8181

8282
fragments = {}
@@ -203,21 +203,21 @@ def find_related_monomorphic_fragments(source_rids, relationship, options = {})
203203
records = related_klass.apply_filters(records, filters, filter_options)
204204

205205
pluck_fields = [
206-
primary_key_field,
207-
concat_table_field(table_alias, related_klass._primary_key)
206+
"#{primary_key_field} AS #{_table_name}_#{_primary_key}",
207+
"#{concat_table_field(table_alias, related_klass._primary_key)} AS #{table_alias}_#{related_klass._primary_key}"
208208
]
209209

210210
cache_field = related_klass.attribute_to_model_field(:_cache_field) if options[:cache]
211211
if cache_field
212-
pluck_fields << concat_table_field(table_alias, cache_field[:name])
212+
pluck_fields << "#{concat_table_field(table_alias, cache_field[:name])} AS #{table_alias}_#{cache_field[:name]}"
213213
end
214214

215215
model_fields = {}
216216
attributes = options[:attributes]
217217
attributes.try(:each) do |attribute|
218218
model_field = related_klass.attribute_to_model_field(attribute)
219219
model_fields[attribute] = model_field
220-
pluck_fields << concat_table_field(table_alias, model_field[:name])
220+
pluck_fields << "#{concat_table_field(table_alias, model_field[:name])} AS #{table_alias}_#{model_field[:name]}"
221221
end
222222

223223
rows = records.pluck(*pluck_fields)
@@ -263,7 +263,11 @@ def find_related_polymorphic_fragments(source_rids, relationship, options = {})
263263
related_key = concat_table_field(_table_name, relationship.foreign_key)
264264
related_type = concat_table_field(_table_name, relationship.polymorphic_type)
265265

266-
pluck_fields = [primary_key, related_key, related_type]
266+
pluck_fields = [
267+
"#{primary_key} AS #{_table_name}_#{_primary_key}",
268+
"#{related_key} AS #{_table_name}_#{relationship.foreign_key}",
269+
"#{related_type} AS #{_table_name}_#{relationship.polymorphic_type}"
270+
]
267271

268272
relations = relationship.polymorphic_relations
269273

test/fixtures/active_record.rb

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,31 @@
88

99
### DATABASE
1010
ActiveRecord::Schema.define do
11+
create_table :sessions, id: false, force: true do |t|
12+
t.string :id, :limit => 36, :primary_key => true, null: false
13+
t.string :survey_id, :limit => 36, null: false
14+
15+
t.timestamps
16+
end
17+
18+
create_table :responses, force: true do |t|
19+
#t.string :id, :limit => 36, :primary_key => true, null: false
20+
21+
t.string :session_id, limit: 36, null: false
22+
23+
t.string :type
24+
t.string :question_id, limit: 36
25+
26+
t.timestamps
27+
end
28+
29+
create_table :response_texts, force: true do |t|
30+
t.text :text
31+
t.integer :response_id
32+
33+
t.timestamps
34+
end
35+
1136
create_table :people, force: true do |t|
1237
t.string :name
1338
t.string :email
@@ -359,6 +384,42 @@
359384
end
360385

361386
### MODELS
387+
class Session < ActiveRecord::Base
388+
has_many :responses
389+
end
390+
391+
class Response < ActiveRecord::Base
392+
belongs_to :session
393+
has_one :paragraph, :class_name => "ResponseText::Paragraph"
394+
395+
def response_type
396+
case self.type
397+
when "Response::SingleTextbox"
398+
"single_textbox"
399+
else
400+
"question"
401+
end
402+
end
403+
def response_type=type
404+
self.type = case type
405+
when "single_textbox"
406+
"Response::SingleTextbox"
407+
else
408+
"Response"
409+
end
410+
end
411+
end
412+
413+
class Response::SingleTextbox < Response
414+
has_one :paragraph, :class_name => "ResponseText::Paragraph", :foreign_key => :response_id
415+
end
416+
417+
class ResponseText < ActiveRecord::Base
418+
end
419+
420+
class ResponseText::Paragraph < ResponseText
421+
end
422+
362423
class Person < ActiveRecord::Base
363424
has_many :posts, foreign_key: 'author_id'
364425
has_many :comments, foreign_key: 'author_id'
@@ -735,6 +796,19 @@ class Robot < ActiveRecord::Base
735796
end
736797

737798
### CONTROLLERS
799+
class SessionsController < ActionController::Base
800+
include JSONAPI::ActsAsResourceController
801+
before_action :create_responses_relationships, :only => [:create,:update]
802+
803+
private
804+
def create_responses_relationships
805+
if !params[:data][:relationships].nil? && !params[:data][:relationships][:responses].nil?
806+
responses_params = params[:data][:relationships].delete(:responses)
807+
params[:data][:attributes][:responses] = responses_params
808+
end
809+
end
810+
end
811+
738812
class AuthorsController < JSONAPI::ResourceControllerMetal
739813
end
740814

@@ -1038,6 +1112,57 @@ class BaseResource < JSONAPI::Resource
10381112
abstract
10391113
end
10401114

1115+
class SessionResource < JSONAPI::Resource
1116+
key_type :uuid
1117+
1118+
attributes :survey_id, :responses
1119+
1120+
has_many :responses
1121+
1122+
def responses=params
1123+
params[:data].each { |datum|
1124+
response = @model.responses.build(datum[:attributes].permit(:response_type, :question_id))
1125+
1126+
(datum[:relationships] || {}).each_pair { |k,v|
1127+
case k
1128+
when "paragraph"
1129+
response.paragraph = ResponseText::Paragraph.create(v[:data][:attributes].permit(:text))
1130+
end
1131+
}
1132+
}
1133+
end
1134+
def responses
1135+
end
1136+
1137+
def self.creatable_fields(context)
1138+
super + [
1139+
:id,
1140+
]
1141+
end
1142+
1143+
def fetchable_fields
1144+
super - [:responses]
1145+
end
1146+
end
1147+
1148+
class ResponseResource < JSONAPI::Resource
1149+
model_hint model: Response::SingleTextbox, resource: :response
1150+
1151+
has_one :session
1152+
1153+
attributes :question_id, :response_type
1154+
1155+
has_one :paragraph
1156+
end
1157+
1158+
class ParagraphResource < JSONAPI::Resource
1159+
model_name 'ResponseText::Paragraph'
1160+
1161+
attributes :text
1162+
1163+
has_one :response
1164+
end
1165+
10411166
class PersonResource < BaseResource
10421167
attributes :name, :email
10431168
attribute :date_joined, format: :date_with_timezone

test/integration/requests/request_test.rb

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,67 @@ def test_large_get
2020
assert_cacheable_jsonapi_get '/api/v2/books?include=book_comments,book_comments.author'
2121
end
2222

23+
def test_post_sessions
24+
session_id = SecureRandom.uuid
25+
26+
post '/sessions', params: {
27+
data: {
28+
id: session_id,
29+
type: "sessions",
30+
attributes: {
31+
"survey_id": SecureRandom.uuid,
32+
},
33+
relationships: {
34+
responses: {
35+
data: [
36+
{
37+
"type": "responses",
38+
"attributes": {
39+
"response_type": "single_textbox",
40+
"question_id": SecureRandom.uuid,
41+
},
42+
"relationships": {
43+
"paragraph": {
44+
"data": {
45+
"type": "responses",
46+
"response_type": "paragraph",
47+
"attributes": {
48+
"text": "This is my single textbox response"
49+
}
50+
}
51+
}
52+
}
53+
},
54+
],
55+
},
56+
},
57+
}
58+
}.to_json,
59+
headers: {
60+
'CONTENT_TYPE' => JSONAPI::MEDIA_TYPE,
61+
'Accept' => JSONAPI::MEDIA_TYPE
62+
}
63+
assert_jsonapi_response 201
64+
json_body = JSON.parse(response.body)
65+
session_id = json_body["data"]["id"]
66+
67+
# Get what we just created
68+
get "/sessions/#{session_id}?include=responses"
69+
assert_jsonapi_response 200
70+
json_body = JSON.parse(response.body)
71+
72+
assert(json_body.is_a?(Object));
73+
assert(json_body["included"].is_a?(Array));
74+
assert_equal("single_textbox", json_body["included"][0]["attributes"]["response_type"]["single_textbox"]);
75+
76+
get "/sessions/#{session_id}?include=responses,responses.paragraph"
77+
assert_jsonapi_response 200
78+
json_body = JSON.parse(response.body)
79+
80+
assert_equal("single_textbox", json_body["included"][0]["attributes"]["response_type"]["single_textbox"]);
81+
assert_equal("paragraphs", json_body["included"][1]["type"]);
82+
end
83+
2384
def test_get_inflected_resource
2485
assert_cacheable_jsonapi_get '/api/v8/numeros_telefone'
2586
end

test/test_helper.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ class CatResource < JSONAPI::Resource
240240

241241
JSONAPI.configuration.route_format = :underscored_route
242242
TestApp.routes.draw do
243+
jsonapi_resources :sessions
243244
jsonapi_resources :people
244245
jsonapi_resources :special_people
245246
jsonapi_resources :comments

0 commit comments

Comments
 (0)