From cb588fd822f3946e415cbf3de12223ac5bff04a2 Mon Sep 17 00:00:00 2001 From: Lucas Date: Sat, 15 Jul 2017 07:30:37 +0200 Subject: [PATCH 1/2] Add hook for default jsonapi object. --- lib/jsonapi/rails/action_controller.rb | 4 ++ lib/jsonapi/rails/railtie.rb | 4 +- lib/jsonapi/rails/renderer.rb | 5 +- spec/action_controller_spec.rb | 71 ++++++++++++++++++-------- 4 files changed, 58 insertions(+), 26 deletions(-) diff --git a/lib/jsonapi/rails/action_controller.rb b/lib/jsonapi/rails/action_controller.rb index 377cf6f..585996c 100644 --- a/lib/jsonapi/rails/action_controller.rb +++ b/lib/jsonapi/rails/action_controller.rb @@ -42,6 +42,10 @@ def deserializable_resource(key, options = {}, &block) end end + def jsonapi_object + nil + end + def jsonapi_expose { url_helpers: ::Rails.application.routes.url_helpers diff --git a/lib/jsonapi/rails/railtie.rb b/lib/jsonapi/rails/railtie.rb index 5d3530c..0c68556 100644 --- a/lib/jsonapi/rails/railtie.rb +++ b/lib/jsonapi/rails/railtie.rb @@ -30,11 +30,13 @@ class Railtie < ::Rails::Railtie ::ActionController::Renderers.add(:jsonapi) do |resources, options| self.content_type ||= Mime[:jsonapi] + options = options.dup # Renderer proc is evaluated in the controller context. if (pagination_links = jsonapi_pagination(resources)) (options[:links] ||= {}).merge!(pagination_links) end - options[:expose] = jsonapi_expose.merge!(options[:expose] || {}) + options[:expose] = jsonapi_expose.merge!(options[:expose] || {}) + options[:jsonapi] = options[:jsonapi_object] || jsonapi_object RENDERERS[:jsonapi].render(resources, options).to_json end diff --git a/lib/jsonapi/rails/renderer.rb b/lib/jsonapi/rails/renderer.rb index e5b11ef..40dc54c 100644 --- a/lib/jsonapi/rails/renderer.rb +++ b/lib/jsonapi/rails/renderer.rb @@ -10,10 +10,7 @@ def initialize(renderer = JSONAPI::Serializable::SuccessRenderer.new) end def render(resources, options) - opts = options.dup - opts[:jsonapi] = opts.delete(:jsonapi_object) - - @renderer.render(resources, opts) + @renderer.render(resources, options) end end diff --git a/spec/action_controller_spec.rb b/spec/action_controller_spec.rb index 54e7a5b..6e1f7bb 100644 --- a/spec/action_controller_spec.rb +++ b/spec/action_controller_spec.rb @@ -95,35 +95,64 @@ def create end end - describe '#render jsonapi:' do - controller do - def index - serializer = Class.new(JSONAPI::Serializable::Resource) do - type :users - attribute :name + describe '#render' do + context 'when calling render jsonapi: user' do + controller do + def index + serializer = Class.new(JSONAPI::Serializable::Resource) do + type :users + attribute :name + end + user = OpenStruct.new(id: 1, name: 'Lucas') + + render jsonapi: user, class: serializer end - user = OpenStruct.new(id: 1, name: 'Lucas') + end + + subject { JSON.parse(response.body) } + let(:serialized_user) do + { + 'data' => { + 'id' => '1', + 'type' => 'users', + 'attributes' => { 'name' => 'Lucas' } + } + } + end + + it 'renders a JSON API success document' do + get :index - render jsonapi: user, class: serializer + expect(response.content_type).to eq('application/vnd.api+json') + is_expected.to eq(serialized_user) end end - subject { JSON.parse(response.body) } - let(:serialized_user) do - { - 'data' => { - 'id' => '1', - 'type' => 'users', - 'attributes' => { 'name' => 'Lucas' } + context 'when specifying a default jsonapi object' do + controller do + def index + render jsonapi: nil + end + + def jsonapi_object + { version: '1.0' } + end + end + + subject { JSON.parse(response.body) } + let(:document) do + { + 'data' => nil, + 'jsonapi' => { 'version' => '1.0' } } - } - end + end - it 'renders a JSON API document' do - get :index + it 'renders a JSON API success document' do + get :index - expect(response.content_type).to eq('application/vnd.api+json') - is_expected.to eq(serialized_user) + expect(response.content_type).to eq('application/vnd.api+json') + is_expected.to eq(document) + end end end end From f8f84899feec16b07b00591ad4bfee82f767eed2 Mon Sep 17 00:00:00 2001 From: Lucas Date: Tue, 25 Jul 2017 10:02:58 +0200 Subject: [PATCH 2/2] Refactor renderers. --- lib/jsonapi/rails/railtie.rb | 23 +++++------------------ lib/jsonapi/rails/renderer.rb | 16 ++++++++++++++-- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/lib/jsonapi/rails/railtie.rb b/lib/jsonapi/rails/railtie.rb index 0c68556..e4bd93c 100644 --- a/lib/jsonapi/rails/railtie.rb +++ b/lib/jsonapi/rails/railtie.rb @@ -27,26 +27,13 @@ class Railtie < ::Rails::Railtie ::ActionDispatch::ParamsParser::DEFAULT_PARSERS[Mime[:jsonapi]] = PARSER end - ::ActionController::Renderers.add(:jsonapi) do |resources, options| - self.content_type ||= Mime[:jsonapi] + RENDERERS.each do |name, renderer| + ::ActionController::Renderers.add(name) do |resources, options| + # Renderer proc is evaluated in the controller context. + self.content_type ||= Mime[:jsonapi] - options = options.dup - # Renderer proc is evaluated in the controller context. - if (pagination_links = jsonapi_pagination(resources)) - (options[:links] ||= {}).merge!(pagination_links) + renderer.render(resources, options, self).to_json end - options[:expose] = jsonapi_expose.merge!(options[:expose] || {}) - options[:jsonapi] = options[:jsonapi_object] || jsonapi_object - - RENDERERS[:jsonapi].render(resources, options).to_json - end - - ::ActionController::Renderers.add(:jsonapi_error) do |errors, options| - # Renderer proc is evaluated in the controller context. - options = options.merge(_jsonapi_pointers: jsonapi_pointers) - self.content_type ||= Mime[:jsonapi] - - RENDERERS[:jsonapi_error].render(errors, options).to_json end end end diff --git a/lib/jsonapi/rails/renderer.rb b/lib/jsonapi/rails/renderer.rb index 40dc54c..c0583b5 100644 --- a/lib/jsonapi/rails/renderer.rb +++ b/lib/jsonapi/rails/renderer.rb @@ -9,7 +9,17 @@ def initialize(renderer = JSONAPI::Serializable::SuccessRenderer.new) freeze end - def render(resources, options) + def render(resources, options, controller) + options = options.dup + + if (pagination_links = controller.jsonapi_pagination(resources)) + (options[:links] ||= {}).merge!(pagination_links) + end + options[:expose] = + controller.jsonapi_expose.merge!(options[:expose] || {}) + options[:jsonapi] = + options[:jsonapi_object] || controller.jsonapi_object + @renderer.render(resources, options) end end @@ -21,8 +31,10 @@ def initialize(renderer = JSONAPI::Serializable::ErrorsRenderer.new) freeze end - def render(errors, options) + def render(errors, options, controller) + options = options.merge(_jsonapi_pointers: controller.jsonapi_pointers) # TODO(beauby): SerializableError inference on AR validation errors. + @renderer.render(errors, options) end end