Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
20 changes: 12 additions & 8 deletions lib/jsonapi/active_relation_resource_finder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,19 +64,19 @@ def find_fragments(filters, options = {})
records = find_records(filters, options)

table_name = _model_class.table_name
pluck_fields = [concat_table_field(table_name, _primary_key)]
pluck_fields = ["#{concat_table_field(table_name, _primary_key)} AS #{table_name}_#{_primary_key}"]

cache_field = attribute_to_model_field(:_cache_field) if options[:cache]
if cache_field
pluck_fields << concat_table_field(table_name, cache_field[:name])
pluck_fields << "#{concat_table_field(table_name, cache_field[:name])} AS #{table_name}_#{cache_field[:name]}"
end

model_fields = {}
attributes = options[:attributes]
attributes.try(:each) do |attribute|
model_field = attribute_to_model_field(attribute)
model_fields[attribute] = model_field
pluck_fields << concat_table_field(table_name, model_field[:name])
pluck_fields << "#{concat_table_field(table_name, model_field[:name])} AS #{table_name}_#{model_field[:name]}"
end

fragments = {}
Expand Down Expand Up @@ -203,21 +203,21 @@ def find_related_monomorphic_fragments(source_rids, relationship, options = {})
records = related_klass.apply_filters(records, filters, filter_options)

pluck_fields = [
primary_key_field,
concat_table_field(table_alias, related_klass._primary_key)
"#{primary_key_field} AS #{_table_name}_#{_primary_key}",
"#{concat_table_field(table_alias, related_klass._primary_key)} AS #{table_alias}_#{related_klass._primary_key}"
]

cache_field = related_klass.attribute_to_model_field(:_cache_field) if options[:cache]
if cache_field
pluck_fields << concat_table_field(table_alias, cache_field[:name])
pluck_fields << "#{concat_table_field(table_alias, cache_field[:name])} AS #{table_alias}_#{cache_field[:name]}"
end

model_fields = {}
attributes = options[:attributes]
attributes.try(:each) do |attribute|
model_field = related_klass.attribute_to_model_field(attribute)
model_fields[attribute] = model_field
pluck_fields << concat_table_field(table_alias, model_field[:name])
pluck_fields << "#{concat_table_field(table_alias, model_field[:name])} AS #{table_alias}_#{model_field[:name]}"
end

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

pluck_fields = [primary_key, related_key, related_type]
pluck_fields = [
"#{primary_key} AS #{_table_name}_#{_primary_key}",
"#{related_key} AS #{_table_name}_#{relationship.foreign_key}",
"#{related_type} AS #{_table_name}_#{relationship.polymorphic_type}"
]

relations = relationship.polymorphic_relations

Expand Down
126 changes: 126 additions & 0 deletions test/fixtures/active_record.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,31 @@

### DATABASE
ActiveRecord::Schema.define do
create_table :sessions, id: false, force: true do |t|
t.string :id, :limit => 36, :primary_key => true, null: false
t.string :survey_id, :limit => 36, null: false

t.timestamps
end

create_table :responses, force: true do |t|
#t.string :id, :limit => 36, :primary_key => true, null: false

t.string :session_id, limit: 36, null: false

t.string :type
t.string :question_id, limit: 36

t.timestamps
end

create_table :response_texts, force: true do |t|
t.text :text
t.integer :response_id

t.timestamps
end

create_table :people, force: true do |t|
t.string :name
t.string :email
Expand Down Expand Up @@ -359,6 +384,43 @@
end

### MODELS
class Session < ActiveRecord::Base
self.primary_key = "id"
has_many :responses
end

class Response < ActiveRecord::Base
belongs_to :session
has_one :paragraph, :class_name => "ResponseText::Paragraph"

def response_type
case self.type
when "Response::SingleTextbox"
"single_textbox"
else
"question"
end
end
def response_type=type
self.type = case type
when "single_textbox"
"Response::SingleTextbox"
else
"Response"
end
end
end

class Response::SingleTextbox < Response
has_one :paragraph, :class_name => "ResponseText::Paragraph", :foreign_key => :response_id
end

class ResponseText < ActiveRecord::Base
end

class ResponseText::Paragraph < ResponseText
end

class Person < ActiveRecord::Base
has_many :posts, foreign_key: 'author_id'
has_many :comments, foreign_key: 'author_id'
Expand Down Expand Up @@ -735,6 +797,19 @@ class Robot < ActiveRecord::Base
end

### CONTROLLERS
class SessionsController < ActionController::Base
include JSONAPI::ActsAsResourceController
before_action :create_responses_relationships, :only => [:create,:update]

private
def create_responses_relationships
if !params[:data][:relationships].nil? && !params[:data][:relationships][:responses].nil?
responses_params = params[:data][:relationships].delete(:responses)
params[:data][:attributes][:responses] = responses_params
end
end
end

class AuthorsController < JSONAPI::ResourceControllerMetal
end

Expand Down Expand Up @@ -1038,6 +1113,57 @@ class BaseResource < JSONAPI::Resource
abstract
end

class SessionResource < JSONAPI::Resource
key_type :uuid

attributes :survey_id, :responses

has_many :responses

def responses=params
params[:data].each { |datum|
response = @model.responses.build(((datum[:attributes].respond_to?(:permit))? datum[:attributes].permit(:response_type, :question_id) : datum[:attributes]))

(datum[:relationships] || {}).each_pair { |k,v|
case k
when "paragraph"
response.paragraph = ResponseText::Paragraph.create(((v[:data][:attributes].respond_to?(:permit))? v[:data][:attributes].permit(:text) : v[:data][:attributes]))
end
}
}
end
def responses
end

def self.creatable_fields(context)
super + [
:id,
]
end

def fetchable_fields
super - [:responses]
end
end

class ResponseResource < JSONAPI::Resource
model_hint model: Response::SingleTextbox, resource: :response

has_one :session

attributes :question_id, :response_type

has_one :paragraph
end

class ParagraphResource < JSONAPI::Resource
model_name 'ResponseText::Paragraph'

attributes :text

has_one :response
end

class PersonResource < BaseResource
attributes :name, :email
attribute :date_joined, format: :date_with_timezone
Expand Down
63 changes: 63 additions & 0 deletions test/integration/requests/request_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,69 @@ def test_large_get
assert_cacheable_jsonapi_get '/api/v2/books?include=book_comments,book_comments.author'
end

def test_post_sessions
session_id = SecureRandom.uuid

post '/sessions', params: {
data: {
id: session_id,
type: "sessions",
attributes: {
survey_id: SecureRandom.uuid,
},
relationships: {
responses: {
data: [
{
type: "responses",
attributes: {
response_type: "single_textbox",
question_id: SecureRandom.uuid,
},
relationships: {
paragraph: {
data: {
type: "responses",
response_type: "paragraph",
attributes: {
text: "This is my single textbox response"
}
}
}
}
},
],
},
},
}
}.to_json,
headers: {
'CONTENT_TYPE' => JSONAPI::MEDIA_TYPE,
'Accept' => JSONAPI::MEDIA_TYPE
}
assert_jsonapi_response 201
json_body = JSON.parse(response.body)
session_id = json_body["data"]["id"]

# Get what we just created
get "/sessions/#{session_id}?include=responses"
assert_jsonapi_response 200
json_body = JSON.parse(response.body)

assert(json_body.is_a?(Object));
assert(json_body["included"].is_a?(Array));
assert_equal("single_textbox", json_body["included"][0]["attributes"]["response_type"]["single_textbox"]);

get "/sessions/#{session_id}?include=responses,responses.paragraph"
assert_jsonapi_response 200
json_body = JSON.parse(response.body)

assert_equal("single_textbox", json_body["included"][0]["attributes"]["response_type"]["single_textbox"]);

# Rails 4.2.x branch will not retrieve the responses.paragraph, 5.x branch will - this looks to be a deeper, but unrelated bug
#assert_equal("paragraphs", json_body["included"][1]["type"]);
end

def test_get_inflected_resource
assert_cacheable_jsonapi_get '/api/v8/numeros_telefone'
end
Expand Down
1 change: 1 addition & 0 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ class CatResource < JSONAPI::Resource

JSONAPI.configuration.route_format = :underscored_route
TestApp.routes.draw do
jsonapi_resources :sessions
jsonapi_resources :people
jsonapi_resources :special_people
jsonapi_resources :comments
Expand Down