Closed jpaas closed 8 years ago
Looking at the code, I can't even see how this would work for ActionController. The SerializableResource filters the adapter options, so that they must be one of [:include, :fields, :adapter, :meta, :meta_key, :links]
. Which means there's no way the adapter options could contain a :context entry.
@jpaas good bug report. https://github.com/rails-api/active_model_serializers/blob/da7e6dc795ac4f6eb0af63c19c46638b13d0d04e/test/action_controller/json_api/pagination_test.rb should cover that it works
I agree that we are sometime too eager to add foreign objects to the app. It should really be encapsulated. context should maybe be called 'request_context' and has two methods we use: original_url
and query_parameters
I was using a fork of grape-active_model_serializers https://github.com/Thanx/grape-active_model_serializers.git, but once I started using the jsonapi adapter, I built my own very simple grape json formatter:
module API
module AmsFormatter
class << self
def call(resource, env)
serializer_options = {}
serializer_options.merge!(env['ams_serializer_options']) if env['ams_serializer_options']
# For some reason serializable_hash doesn't include meta in the response, so I have to use as_json
ActiveModel::SerializableResource.new(resource, serializer_options).as_json.to_json
end
end
end
end
I also had to create this little grape helper to pass my serializer options to the formatter via the env:
def render(resources, ams_serializer_options = {})
env['ams_serializer_options'] = ams_serializer_options
resources
end
So now I can implement a grape endpoint like this and put metadata into the jsonapi response:
formatter :json, API::AmsFormatter
get ':id' do
render(Resource.find(params[:id]), meta: { foo: 'bar' })
end
Oh and BTW, my workaround for this problem at the moment was to subclass the JsonApi adapter to simply skip links for now...
module API
class AmsJsonapiAdapter < ActiveModel::Serializer::Adapter::JsonApi
def links_for(serializer, options)
{}
end
end
end
@jpaas would you want to submit the formatter here as a PR?
Also, you should be able to just to_json
not as_json.to_json
Ah yes @bf4 to_json alone works. I thought I tried that at one point but had trouble. I can submit as a PR. Where would you like it in the namespace?
I'm thinking Grape::ActiveModelSerializers
in lib/grape/active_model_serializers
or something like that and maybe in lib grape-active_model_serializers.rb
that requires active_model_serializers
and grape/active_model_serializers
. Just try something that makes sense to you
I just spent like 6 hours figuring this out. I'm using the same set of tools as @jpaas and I can get the links to work if I pass in the (bastardized) context where I would least expect it :interrobang:
So I changed the code at https://github.com/rails-api/active_model_serializers/issues/1268#issuecomment-148153186 to:
# 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
RequestContext = Struct.new(:original_url, :query_parameters)
class << self
def call(resource, env) serializer_options = {}
serializer_options.merge!(env[:active_model_serializer_options]) if env[:active_model_serializer_options]
serializer_options[:context] = RequestContext.new(env['REQUEST_URI'],
env['rack.request.query_hash'])
ActiveModel::SerializableResource.new(resource, serializer_options).to_json(serializer_options)
end
end
end
end
end
Without passing my little context hack into to_json
, they don't make their way into PaginationLinks
's context
constructor parameter. Interestingly, when I pass them to as_json
instead, I get Ruby out! :open_mouth:
I am also getting the same issue. On executing ActiveModel::SerializableResource.new(@admins, adapter: :json_api).to_json
Although, ActiveModel::SerializableResource.new(@admins, adapter: :json_api)
gives the following response:
#<ActiveModel::SerializableResource:0x000000054789e8 @resource=#<ActiveRecord::Relation [#<Admin id: 36, email: "aubrey_schmitt@feeneykoch.io", encrypted_password: "$2a$10$u1E0eoEymfPs.rmUu9KZce9dXWQ/cIE5PCjKJbJFPmf...", remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, failed_attempts: 0, locked_at: nil, created_at: "2016-03-28 05:15:17", updated_at: "2016-03-28 05:15:17">, #<Admin id: 20, email: "alysa_johnston@thompson.io", encrypted_password: "$2a$10$e5J4nS2wlUtVyoP95qVWvux36bihsE2Pk8.Rn/n8.3f...", remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, failed_attempts: 0, locked_at: nil, created_at: "2016-03-28 05:15:16", updated_at: "2016-03-28 05:15:16">, #<Admin id: 22, email: "kristofer.langosh@kunzeluettgen.com", encrypted_password: "$2a$10$Fi0FaprD1t4MH1uK29IiVuM6M5ZBlb7CIJteIpdHyYF...", remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, failed_attempts: 0, locked_at: nil, created_at: "2016-03-28 05:15:16", updated_at: "2016-03-28 05:15:16">, #<Admin id: 37, email: "beryl_keler@wiza.biz", encrypted_password: "$2a$10$2MGzfCyarGQJcmp1RV2BBeU0xNKqalkyukwszutS5/t...", remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, failed_attempts: 0, locked_at: nil, created_at: "2016-03-28 05:15:17", updated_at: "2016-03-28 05:15:17">, #<Admin id: 5, email: "wilhelmine_buckridge@crona.io", encrypted_password: "$2a$10$d5dXU.HH3SQjPPNEijzoau7di9dwwVk4TsgnCV9Xxga...", remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, failed_attempts: 0, locked_at: nil, created_at: "2016-03-28 05:15:15", updated_at: "2016-03-28 05:15:15">, #<Admin id: 14, email: "edward_wisoky@corkery.net", encrypted_password: "$2a$10$sM9p3J6g04TnfMl/nTtezuXdwW3uHoebIhvuW1t1ptI...", remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, failed_attempts: 0, locked_at: nil, created_at: "2016-03-28 05:15:15", updated_at: "2016-03-28 05:15:15">, #<Admin id: 27, email: "leonor@jerde.biz", encrypted_password: "$2a$10$ztJkxiM88UnROguht0mEUea/GVRK0KPO856vQimaIV3...", remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, failed_attempts: 0, locked_at: nil, created_at: "2016-03-28 05:15:16", updated_at: "2016-03-28 05:15:16">, #<Admin id: 2, email: "carley@wyman.net", encrypted_password: "$2a$10$CcYUeV5yayJYaJ0cfcKGVOo7FtxxHpuCFUw.GRcAxAO...", remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, failed_attempts: 0, locked_at: nil, created_at: "2016-03-28 05:15:14", updated_at: "2016-03-28 05:15:14">, #<Admin id: 10, email: "ervin.gleichner@cremin.org", encrypted_password: "$2a$10$8zSpB.qRVkCJSJRPP.630uOGyMOFQRHGKpB6h58COsx...", remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, failed_attempts: 0, locked_at: nil, created_at: "2016-03-28 05:15:15", updated_at: "2016-03-28 05:15:15">, #<Admin id: 15, email: "lonzo.dickens@johnscole.name", encrypted_password: "$2a$10$BfFV7CZmofSJC8ObT8f9OuE.ntSXNvtstd3MUuEolyu...", remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, failed_attempts: 0, locked_at: nil, created_at: "2016-03-28 05:15:15", updated_at: "2016-03-28 05:15:15">]>, @adapter_opts={:adapter=>:json_api}, @serializer_opts={}>
I've used @hut8's approach, but changed it for rails 4.1 and active_model_serializers version 0.10.rc3, to solve my problem. My problem was that I wanted to render a view using the html
format and serialize a bunch of paginated objects using the json_api
to initialize a client-side JS framework. Without the serialization context, I get undefined method 'query_parameters' for nil:NilClass
Since I'm not doing this within the context of a render
, but rather a helper method, and I'd rather stay away from rendering inside a variable (since that seems like a hack which does more than I want), this is what I ended up doing
def serialized_objects(objects)
@serialized_objects =
ActiveModel::SerializableResource.new(objects, {}).as_json(serialization_context_options)
end
def serialization_context_options
{
serialization_context: Struct.new(:request_url, :query_parameters).new(
request.path,
env['rack.request.query_hash']
)
}
end
Is Grape support complete? I've followed this thread and updated to the latest 0.10.0
release and getting the following error after following the Grape Support documentation
"status":500
"title":"Internal Server Error"
"detail":"key not found: :serialization_context"
"meta":{"error_class":"KeyError"
"backtrace":
"~/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/active_model_serializers-0.10.0/lib/active_model_serializers/adapter/json_api/pagination_links.rb:12:in `fetch'"
"~/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/active_model_serializers-0.10.0/lib/active_model_serializers/adapter/json_api/pagination_links.rb:12:in `initialize'"
"~/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/active_model_serializers-0.10.0/lib/active_model_serializers/adapter/json_api.rb:506:in `new'"
"~/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/active_model_serializers-0.10.0/lib/active_model_serializers/adapter/json_api.rb:506:in `pagination_links_for'"
"~/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/active_model_serializers-0.10.0/lib/active_model_serializers/adapter/json_api.rb:131:in `success_document'"
"~/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/active_model_serializers-0.10.0/lib/active_model_serializers/adapter/json_api.rb:48:in `serializable_hash'"
"~/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/active_model_serializers-0.10.0/lib/active_model_serializers/adapter/base.rb:29:in `as_json'"
"~/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/active_model_serializers-0.10.0/lib/active_model_serializers/serializable_resource.rb:8:in `to_json'"
"~/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/active_model_serializers-0.10.0/lib/active_model_serializers/serializable_resource.rb:8:in `to_json'"
"~/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/active_model_serializers-0.10.0/lib/active_model_serializers/logging.rb:6
That's a bug. Please open a new issue
B mobile phone
On May 29, 2016, at 9:36 AM, Onome notifications@github.com wrote:
Is Grape support complete? I've followed this thread and updated to the latest 0.10.0 release and getting the following error after following the Grape Support documentation
"status":500 "title":"Internal Server Error" "detail":"key not found: :serialization_context" "meta":{"error_class":"KeyError" "backtrace": "~/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/active_model_serializers-0.10.0/lib/active_model_serializers/adapter/json_api/pagination_links.rb:12:in
fetch'" "~/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/active_model_serializers-0.10.0/lib/active_model_serializers/adapter/json_api/pagination_links.rb:12:in
initialize'" "~/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/active_model_serializers-0.10.0/lib/active_model_serializers/adapter/json_api.rb:506:innew'" "~/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/active_model_serializers-0.10.0/lib/active_model_serializers/adapter/json_api.rb:506:in
pagination_links_for'" "~/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/active_model_serializers-0.10.0/lib/active_model_serializers/adapter/json_api.rb:131:insuccess_document'" "~/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/active_model_serializers-0.10.0/lib/active_model_serializers/adapter/json_api.rb:48:in
serializable_hash'" "~/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/active_model_serializers-0.10.0/lib/active_model_serializers/adapter/base.rb:29:inas_json'" "~/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/active_model_serializers-0.10.0/lib/active_model_serializers/serializable_resource.rb:8:in
to_json'" "~/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/active_model_serializers-0.10.0/lib/active_model_serializers/serializable_resource.rb:8:in `to_json'" "~/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/active_model_serializers-0.10.0/lib/active_model_serializers/logging.rb:6 — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.
I'm trying to use Grape+Kaminari+AMS 1.0 (head) and I get a stack trace like so...
It seems to assume that the context has been set as an ActionDispatch::Request. I would try setting it, but I can't figure out how to get it in Grape.