-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Grape formatter feature requested in #1258 - Rebased and Repushed (#1273) #1336
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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. |
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 |
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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. naive question. Does grape require the formatter to return a JSON string? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Grape can handle Hashes, Strings, Arrays, and Enumerables - I will add an update to return the serializable hash There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. really should be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Apparently I was wrong about this - if I use |
||
end | ||
end | ||
end | ||
end |
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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
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' | ||
|
||
post = ARModels::Post.new(title: 'Dummy Title', body: 'Lorem Ipsum') | ||
serializable_resource = serializable(post) | ||
|
||
assert last_response.ok? | ||
assert_equal serializable_resource.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 }) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd just like to note that the other two tests here have an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point - I've moved towards using |
||
|
||
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 = { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. serializable? or I can merge it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How could I create an array to pass into the serializer? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you modified the routing as + def setup
+ @post = ARModels::Post.create(title: 'Dummy Title', body: 'Lorem Ipsum')
+ ARModels::Post.create(title: 'post 2', body: 'body 2')
+ @posts = ARModels::Post.all
+ end
# ..
resources :grape do
get '/render' do
- post = ARModels::Post.new(title: 'Dummy Title', body: 'Lorem Ipsum')
+ render @post
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
+ render @post, meta: { page: 1, total_pages: 2 }, adapter: :json_api
end
get '/render_array_with_json_api' do
- render ARModels::Post.all, adapter: :json_api
+ render @posts, adapter: :json_api
end
end Then your tests become testing serializable_resource = serializable(@post)
serializable_resource = serializable(@post, serializer: ARModels::PostSerializer, adapter: :json_api, meta: { page: 1, total_pages: 2 })
serializable_resource = serializable(@posts, adapter: :json_api) or There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thoughts There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry I never got back to you on this - work got in the way 😄 I tried to implement what you said, but unfortunately it doesn't work due to the fact that |
||
'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 last_response.ok? | ||
assert_equal expected.to_json, last_response.body | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
awesome! Thanks for editing this and the other doc files!