Skip to content

Commit

Permalink
Grape formatter feature requested in #1268
Browse files Browse the repository at this point in the history
 - adds handling for when the returned resource is not serializable via ams
 - fix for when resource is an Array
 - Moves grape include to grape namespace. Changes Enumerable to Array because a plain hash is enumerable.
 - Add integration test
 - Refine scope of Grape version dependency
 - Assert that the response is equal to a manually defined JSON string
 - Add single module to include in Grape projects
 - Create a Serializable Resource to test rails-api from Grape
 - Update docs
 - Fix discrepency between ActiveRecord 4.0 - 4.1 and 4.2
 - Updated Changelog
  • Loading branch information
jpaas authored and johnhamelink committed Nov 26, 2015
1 parent 8aaaa44 commit b1a9161
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Breaking changes:

Features:

- [#1336](https://github.com/rails-api/active_model_serializers/pull/1336) Added support for Grape >= 0.13, < 1.0
- [#1291](https://github.com/rails-api/active_model_serializers/pull/1291) Add logging (@maurogeorge)
- [#1225](https://github.com/rails-api/active_model_serializers/pull/1125) Better serializer lookup, use nested serializer when it exists (@beauby)
- [#1172](https://github.com/rails-api/active_model_serializers/pull/1172) Better serializer registration, get more than just the first module (@bf4)
Expand Down
1 change: 1 addition & 0 deletions active_model_serializers.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,5 @@ Gem::Specification.new do |spec|
spec.add_development_dependency 'bundler', '~> 1.6'
spec.add_development_dependency 'timecop', '~> 0.7'
spec.add_development_dependency 'minitest-reporters'
spec.add_development_dependency 'grape', '~> 0.13'
end
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ This is the documentation of AMS, it's focused on the **0.10.x version.**
- [How to add pagination links](howto/add_pagination_links.md)
- [Using AMS Outside Of Controllers](howto/outside_controller_use.md)
- [How to use JSON API with Ember](howto/ember-and-json-api.md)
- [Grape](howto/grape.md)

## Getting Help

Expand Down
19 changes: 19 additions & 0 deletions docs/howto/grape.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Integration with Grape

[Grape](https://github.com/ruby-grape/grape) is an opinionated micro-framework for creating REST-like APIs in ruby.

ActiveModelSerializers currently supports Grape >= 0.13, < 1.0

To add [Grape](https://github.com/ruby-grape/grape) support, enable the formatter and helper functions by including `Grape::ActiveModelSerializers` in your base endpoint. For example:

```ruby
module Example
class Dummy < Grape::API
require 'grape/active_model_serializers'
include Grape::ActiveModelSerializers
mount Example::V1::Base
end
end
```

Aside from this, [configuration](../general/configuration_options.md) of ActiveModelSerializers is exactly the same.
14 changes: 14 additions & 0 deletions lib/grape/active_model_serializers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# To add grape support, require 'grape/active_model_serializers' in the base of your grape endpoints
# Then add 'include Grape::ActiveModelSerializers' to enable the formatter and helpers
require 'active_model_serializers'
require 'grape/formatters/active_model_serializers'
require 'grape/helpers/active_model_serializers'

module Grape::ActiveModelSerializers
extend ActiveSupport::Concern

included do
formatter :json, Grape::Formatters::ActiveModelSerializers
helpers Grape::Helpers::ActiveModelSerializers
end
end
15 changes: 15 additions & 0 deletions lib/grape/formatters/active_model_serializers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# A grape response formatter that can be used as 'formatter :json, Grape::Formatters::ActiveModelSerializers'
#
# Serializer options can be passed as a hash from your grape endpoint using env[:active_model_serializer_options],
# or better yet user the render helper in Grape::Helpers::ActiveModelSerializers
module Grape
module Formatters
module ActiveModelSerializers
def self.call(resource, env)
serializer_options = {}
serializer_options.merge!(env[:active_model_serializer_options]) if env[:active_model_serializer_options]
ActiveModel::SerializableResource.new(resource, serializer_options).to_json
end
end
end
end
16 changes: 16 additions & 0 deletions lib/grape/helpers/active_model_serializers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Helpers can be included in your grape endpoint as: helpers Grape::Helpers::ActiveModelSerializers
module Grape
module Helpers
module ActiveModelSerializers
# A convenience method for passing ActiveModelSerializers serializer options
#
# Example: To include relationships in the response: render(post, include: ['comments'])
#
# Example: To include pagination meta data: render(posts, meta: { page: posts.page, total_pages: posts.total_pages })
def render(resource, active_model_serializer_options = {})
env[:active_model_serializer_options] = active_model_serializer_options
resource
end
end
end
end
85 changes: 85 additions & 0 deletions test/grape_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
require 'test_helper'
require 'grape'
require 'grape/active_model_serializers'

class ActiveModelSerializers::GrapeTest < Minitest::Test
include Rack::Test::Methods

class GrapeTest < Grape::API
format :json
include Grape::ActiveModelSerializers

resources :grape do
get '/render' do
render ARModels::Post.new(title: 'Dummy Title', body: 'Lorem Ipsum')
end

get '/render_with_json_api' do
post = ARModels::Post.new(title: 'Dummy Title', body: 'Lorem Ipsum')
render(post, meta: { page: 1, total_pages: 2 }, adapter: :json_api)
end

get '/render_array_with_json_api' do
post = ARModels::Post.create(title: 'Dummy Title', body: 'Lorem Ipsum')
post.dup.save
render(ARModels::Post.all, adapter: :json_api)
end
end
end

def app
GrapeTest.new
end

def test_formatter_returns_json
get '/grape/render'
assert last_response.ok?
expected = { id: nil, title: 'Dummy Title', body: 'Lorem Ipsum', comments: [], author: nil }
assert_equal expected.to_json, last_response.body
end

def test_render_helper_passes_through_options_correctly
get '/grape/render_with_json_api'

post = ARModels::Post.new(title: 'Dummy Title', body: 'Lorem Ipsum')
serializable_resource = serializable(post, serializer: ARModels::PostSerializer, adapter: :json_api, meta: { page: 1, total_pages: 2 })

assert last_response.ok?
assert_equal serializable_resource.to_json, last_response.body
end

def test_formatter_handles_arrays
get '/grape/render_array_with_json_api'

expected = {
'data' => [
{
id: '1',
type: 'ar_models_posts',
attributes: {
title: 'Dummy Title',
body: 'Lorem Ipsum'
},
relationships: {
comments: { data: [] },
author: { data: nil }
}
},
{
id: '2',
type: 'ar_models_posts',
attributes: {
title: 'Dummy Title',
body: 'Lorem Ipsum'
},
relationships: {
comments: { data: [] },
author: { data: nil }
}
}
]
}

assert_equal expected.to_json, last_response.body
end
end

0 comments on commit b1a9161

Please sign in to comment.