Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass adapter options through calls to render. #63

Merged
merged 2 commits into from
Sep 9, 2016
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
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

### 1.5.1 (Next)

* [#65](https://github.com/ruby-grape/grape-active_model_serializers/pull/65): Added Danger, PR linter - [@dblock](https://github.com/dblock).
* Your contribution here.
* [#65](https://github.com/ruby-grape/grape-active_model_serializers/pull/65): Added Danger, PR linter - [@dblock](https://github.com/dblock).
* [#63](https://github.com/ruby-grape/grape-active_model_serializers/pull/63): Pass adapter options through render - [@drn](https://github.com/drn).

### 1.5.0 (August 24, 2016)

Expand Down
34 changes: 32 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,10 @@ Or as follows.

ActiveModelSerializer will fetch automatically the right serializer to render.

### Manually specifying serializer options
### Manually specifying serializer / adapter options

```ruby
# Serializer options can be specified on routes or namespaces.
# Serializer and adapter options can be specified on routes or namespaces.
namespace 'foo', serializer: BarSerializer do
get "/" do
# will use "bar" serializer
Expand All @@ -171,6 +171,36 @@ namespace 'foo', serializer: BarSerializer do
end
```

```ruby
# Serializer and adapter options can also be specified in the body of the route
resource :users do
get '/:id' do
if conditional
# uses UserSerializer and configured default adapter automatically
current_user
else
# uses specified serializer and adapter
render current_user, serializer: ErrorSerializer, adapter: :attributes
end
end
end
```

```ruby
# Adhoc serializer options can be specified in the body of the route
resource :users do
get '/:id' do
render current_user, extra: { adhoc_name_option: 'value' }
end
end

class UserSerializer
def name
instance_options[:adhoc_name_option] # accessible in instance_options
end
end
```

### Custom Metadata

```ruby
Expand Down
11 changes: 9 additions & 2 deletions lib/grape-active_model_serializers/endpoint_extension.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,15 @@ def serialization_scope
end
end

def render(resources, meta = {})
env['ams_meta'] = meta
def render(resources, extra_options = {})
options = extra_options.symbolize_keys
env['ams_meta'] = options.slice(
:meta, :meta_key
)
env['ams_adapter'] = options.slice(
:adapter, :serializer, :each_serializer
)
env['ams_extra'] = options[:extra]
resources
end

Expand Down
18 changes: 15 additions & 3 deletions lib/grape-active_model_serializers/options_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ def options
options[:scope] = endpoint unless options.key?(:scope)
options.merge!(default_root_options) unless options.key?(:root)
options.merge!(meta_options)
options.merge!(adapter_options)
options.merge!(extra_options)
options
)
end
Expand Down Expand Up @@ -56,13 +58,23 @@ def innermost_scope

def meta_options
options = {}
ams_meta = env['ams_meta'] || {}
meta = ams_meta[:meta]
meta_key = ams_meta[:meta_key]
meta_options = env['ams_meta'] || {}
meta = meta_options[:meta]
meta_key = meta_options[:meta_key]
options[:meta] = meta if meta
options[:meta_key] = meta_key if meta && meta_key
options
end

def adapter_options
env['ams_adapter'] || {}
end

def extra_options
options = env['ams_extra'] || {}
return options if options.is_a?(Hash)
raise 'Extra options must be a hash'
end
end
end
end
129 changes: 129 additions & 0 deletions spec/grape/active_model_serializers/options_builder_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
require 'spec_helper'

describe Grape::ActiveModelSerializers::OptionsBuilder do
let(:resolver) { described_class.new(resource, env) }
let(:resource) { User.new }
let(:env) { { 'api.endpoint' => UsersApi.endpoints.first } }

context '#options' do
let(:options) { resolver.options }

context 'meta options' do
let(:env) { super().merge('ams_meta' => meta_options) }
let(:meta_options) {
{
meta: meta,
meta_key: meta_key
}
}
let(:meta) { { sample: 'metadata' } }
let(:meta_key) { 'specified_key' }

context 'meta option set' do
context 'meta_key set' do
it 'includes meta' do
expect(options[:meta]).to eq(meta)
end

it 'includes meta_key' do
expect(options[:meta_key]).to eq(meta_key)
end
end

context 'meta_key unset' do
let(:meta_key) { nil }

it 'includes meta' do
expect(options[:meta]).to eq(meta)
end

it 'does not include meta_key' do
expect(options.keys).not_to include(:meta_key)
end
end
end

context 'meta option unset' do
let(:meta) { nil }

context 'meta_key set' do
it 'does not include meta' do
expect(options.keys).not_to include(:meta)
end

it 'does not include meta_key' do
expect(options.keys).not_to include(:meta_key)
end
end

context 'meta_key unset' do
let(:meta_key) { nil }

it 'does not include meta' do
expect(options.keys).not_to include(:meta)
end

it 'does not include meta_key' do
expect(options.keys).not_to include(:meta_key)
end
end
end
end

context 'adapter options' do
let(:env) { super().merge('ams_adapter' => adapter_options) }
let(:adapter_options) { {} }

context 'adapter' do
let(:adapter_options) { { adapter: adapter } }
let(:adapter) { :attributes }

it 'includes adapter as top-level option' do
expect(options[:adapter]).to eq(adapter)
end
end

context 'serializer' do
let(:adapter_options) { { serializer: serializer } }
let(:serializer) { V2::UserSerializer }

it 'includes serializer as top-level option' do
expect(options[:serializer]).to eq(serializer)
end
end

context 'each_serializer' do
let(:adapter_options) { { each_serializer: each_serializer } }
let(:each_serializer) { V2::UserSerializer }

it 'includes each_serializer as top-level option' do
expect(options[:each_serializer]).to eq(each_serializer)
end
end
end

context 'extra options' do
let(:env) { super().merge('ams_extra' => extra_options) }

context 'hash' do
let(:extra_options) { { extra: 'info' } }

it 'includes extra options in top-level options' do
expect(options.keys).to include(:extra)
end
end

context 'not a hash' do
let(:extra_options) { 'extra' }

it 'raises an exception' do
expect {
options
}.to raise_exception(
'Extra options must be a hash'
)
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
require 'pry'
require 'spec_helper'

# asserts serializer resolution order:
Expand Down