Merge branch 'master' of github.com:jrhe/grape-active_model_serializers

* 'master' of github.com:jrhe/grape-active_model_serializers:
  fix: when resource is empty, keep json resource root
  support active model serializer 0.9.x
  [Issue #13] Add render syntactic sugar
This commit is contained in:
Jonathan Richard Henry Evans (JRHE) 2014-07-23 13:28:47 +01:00
commit b23128934c
7 changed files with 202 additions and 7 deletions

View file

@ -99,6 +99,16 @@ namespace 'foo', :serializer => :bar do
end
```
### Custom metadata along with the resources
```ruby
# Control any additional metadata using meta and meta_key
get "/homes"
collection = Home.all
render collection, { meta: { page: 5, current_page: 3 }, meta_key: :pagination_info }
end
```
### current_user
One of the nice features of ActiveModel::Serializers is that it

View file

@ -17,7 +17,7 @@ Gem::Specification.new do |gem|
gem.licenses = ['MIT']
gem.add_dependency "grape", "~> 0.3"
gem.add_dependency "active_model_serializers", ">= 0.8.1"
gem.add_dependency "active_model_serializers", ">= 0.9.0.alpha1"
gem.add_development_dependency "rspec"
gem.add_development_dependency "rack-test"

View file

@ -27,9 +27,26 @@ module Grape
end
end
def default_serializer_options; end
def url_options; end
end
def render(resources, meta={})
set_meta_and_meta_key(meta)
resources
end
def default_serializer_options; end
def url_options; end
private
def set_meta_and_meta_key(meta)
if meta.has_key?(:meta)
Formatter::ActiveModelSerializers.meta = meta[:meta]
if meta.has_key?(:meta_key)
Formatter::ActiveModelSerializers.meta_key = meta[:meta_key]
end
end
end
end
Endpoint.send(:include, EndpointExtension)
end

View file

@ -16,11 +16,43 @@ module Grape
endpoint = env['api.endpoint']
options = build_options_from_endpoint(endpoint)
if resource.respond_to?(:to_ary) && !resource.empty?
if serializer = options.fetch(:serializer, ActiveModel::Serializer.serializer_for(resource))
options[:scope] = serialization_scope unless options.has_key?(:scope)
# ensure we have an root to fallback on
endpoint.controller_name = default_root(endpoint)
options[:resource_name] = default_root(endpoint) if resource.respond_to?(:to_ary)
serializer.new(resource, options.merge(other_options))
end
::ActiveModel::Serializer.build_json(endpoint, resource, options)
end
def other_options
options = {}
if @meta_content_items
if @meta_key
key_option = @meta_key[:meta_key]
@meta_key.delete(:meta_key)
options[:meta_key] = key_option if key_option
end
meta_option = @meta_content_items[:meta]
@meta_content_items.delete(:meta)
options[key_option || :meta] = meta_option if meta_option
end
options
end
def meta
@meta_content_items || {}
end
def meta=(meta_content)
@meta_content_items = { meta: meta_content } if meta_content
end
def meta_key
@meta_key || {}
end
def meta_key=(key)
@meta_key = { meta_key: key } if key
end
def build_options_from_endpoint(endpoint)
@ -38,6 +70,10 @@ module Grape
endpoint.options[:path][0].to_s.split('/')[-1]
end
end
def serialization_scope
:current_user
end
end
end
end

View file

@ -0,0 +1,65 @@
require 'spec_helper'
require 'support/models/user'
require 'support/serializers/user_serializer'
require 'grape-active_model_serializers'
require 'securerandom'
describe '#render' do
let(:app) { Class.new(Grape::API) }
before do
app.format :json
app.formatter :json, Grape::Formatter::ActiveModelSerializers
end
def get_resource_with(meta)
url = "/#{SecureRandom.hex}"
app.get(url) do
render User.new(first_name: 'Jeff'), meta
end
get url
JSON.parse last_response.body
end
context 'with meta key' do
it 'includes meta key and content' do
result = get_resource_with({ meta: { total: 2 }})
expect(result).to have_key('meta')
expect(result.fetch('meta')).to eq({ 'total' => 2 })
end
end
context 'with a custom meta_key' do
it 'includes the custom meta key name' do
result = get_resource_with({ meta: { total: 2 }, meta_key: :custom_key_name })
expect(result).to have_key('custom_key_name')
expect(result.fetch('custom_key_name')).to eq({ 'total' => 2 })
end
it 'ignores a lonely meta_key' do
result = get_resource_with({ meta_key: :custom_key_name })
expect(result).not_to have_key('meta')
expect(result).not_to have_key('custom_key_name')
end
end
context 'junk keys' do
it 'ignores junk keys' do
result = get_resource_with({ junk_key: { total: 2 } })
expect(result).not_to have_key('junk_key')
end
it 'ignores empty meta_key' do
result = get_resource_with({ meta: { total: 2 }, meta_key: nil })
expect(result).to have_key('meta')
end
it 'ignores empty meta' do
result = get_resource_with({ meta: nil })
expect(result).not_to have_key('meta')
end
end
end

View file

@ -0,0 +1,39 @@
require 'spec_helper'
describe 'Grape::EndpointExtension' do
subject { Grape::Endpoint.new(nil, {path: '/', method: 'foo'}) }
let(:serializer) { Grape::Formatter::ActiveModelSerializers }
let(:user) do
Object.new do
def name
'sven'
end
end
end
let(:users) { [user, user] }
describe "#render" do
it { should respond_to(:render) }
let (:meta_content) { { total: 2 } }
let (:meta_full) { { meta: meta_content } }
context 'supplying meta' do
it 'passes through the Resource and uses given meta settings' do
expect(serializer).to receive(:meta=).with(meta_content)
expect(subject.render(users, meta_full)).to eq(users)
end
end
context 'supplying meta and key' do
let (:meta_key) { { meta_key: :custom_key_name } }
it 'passes through the Resource and uses given meta settings' do
expect(serializer).to receive(:meta=).with(meta_content)
expect(serializer).to receive(:meta_key=).with(meta_key[:meta_key])
expect(subject.render(users, meta_full.merge(meta_key))).to eq(users)
end
end
end
end

View file

@ -2,5 +2,33 @@ require 'spec_helper'
require 'grape-active_model_serializers/formatter'
describe Grape::Formatter::ActiveModelSerializers do
subject { Grape::Formatter::ActiveModelSerializers }
it { should respond_to(:meta) }
it { should respond_to(:meta=) }
it { should respond_to(:meta_key) }
it { should respond_to(:meta_key=) }
context '#meta' do
it 'will silently accept falsy input but return empty Hash' do
subject.meta = nil
expect(subject.meta).to eq({})
end
it 'will wrap valid input in the meta: {} wrapper' do
subject.meta = { total: 2 }
expect(subject.meta).to eq({ meta: { total: 2 } })
end
end
context '#meta_key' do
it 'will silently accept falsy input but return empty Hash' do
subject.meta_key = nil
expect(subject.meta_key).to eq({})
end
it 'will wrap valid input in the meta_key: {} wrapper' do
subject.meta_key = :custom_key_name
expect(subject.meta_key).to eq({ meta_key: :custom_key_name })
end
end
end