I am trying to send the serialized version of a model to a view as a param, using the gem active_model_serializers
#app/serializers/admin_serializer.rb
class AdminSerializer < ActiveModel::Serializer attributes :id, :email, :access_locked?
end
#app/controllers/dashboard/admins_controller.rb def index @search = Admin.search(params[:q]) @admins = @search.result(:distinct => true).page(params[:page]).per(10) @page_entries_info = view_context.page_entries_info @admins # render json: @admins respond_to do |format| format.html format.js format.json {render json: @admins} end end
#app/views/dashboard/admins/index.html.erb <%= debug (ActiveModel::Serializer::Adapter.adapter_class(:json_api).new(ActiveModel::Serializer.serializer_for(@admins.first).new(@admins.first),{}).to_json) %> <%= debug (@admins.all.map{|admin| AdminSerializer.new(admin).to_json}) %>Above debugs are yielding the below response:
--- '{"data":{"id":"1","type":"admins","attributes":{"email":"","access_locked?":false}}}' //returned by the first debug
---
- '{"object":{"id":36,"email":"","created_at":"2016-03-28T05:15:17.546Z","updated_at":"2016-03-28T05:15:17.546Z"},"instance_options":{},"root":null,"scope":null}'
- '{"object":{"id":20,"email":"","created_at":"2016-03-28T05:15:16.304Z","updated_at":"2016-03-28T05:15:16.304Z"},"instance_options":{},"root":null,"scope":null}'
- '{"object":{"id":22,"email":"","created_at":"2016-03-28T05:15:16.459Z","updated_at":"2016-03-28T05:15:16.459Z"},"instance_options":{},"root":null,"scope":null}'
- '{"object":{"id":37,"email":"","created_at":"2016-03-28T05:15:17.624Z","updated_at":"2016-03-28T05:15:17.624Z"},"instance_options":{},"root":null,"scope":null}'
- '{"object":{"id":5,"email":"","created_at":"2016-03-28T05:15:15.139Z","updated_at":"2016-03-28T05:15:15.139Z"},"instance_options":{},"root":null,"scope":null}'
- '{"object":{"id":14,"email":"","created_at":"2016-03-28T05:15:15.838Z","updated_at":"2016-03-28T05:15:15.838Z"},"instance_options":{},"root":null,"scope":null}'
- '{"object":{"id":27,"email":"","created_at":"2016-03-28T05:15:16.848Z","updated_at":"2016-03-28T05:15:16.848Z"},"instance_options":{},"root":null,"scope":null}'
- '{"object":{"id":2,"email":"","created_at":"2016-03-28T05:15:14.873Z","updated_at":"2016-03-28T05:15:14.873Z"},"instance_options":{},"root":null,"scope":null}'
- '{"object":{"id":10,"email":"","created_at":"2016-03-28T05:15:15.527Z","updated_at":"2016-03-28T05:15:15.527Z"},"instance_options":{},"root":null,"scope":null}'
- '{"object":{"id":15,"email":"","created_at":"2016-03-28T05:15:15.916Z","updated_at":"2016-03-28T05:15:15.916Z"},"instance_options":{},"root":null,"scope":null}'In the first debug I am serializing only one object, while in the second one I am trying to do it for an array of objects.
The first debug is correctly returning the serialized version of the object(in json_api format) while second debug is not.
Tried ArraySerializer as well, with no success: ActiveModel::Serializer::ArraySerializer.new(@admins, each_serializer: AdminSerializer).as_jsonhow do I achieve the desired serialization. Moreover, if achieved, can I used some other simplified version of this? As this debug statement is way too verbose.
Tried all the solutions mentioned here - How do you initialize an ActiveModel::Serializer class with an ActiveRecord::Relation array?
The basic problem which I am trying to solve is, in the index method of the Admin controller, the Admin object is passed as a PORO to the index.html file. But I want the serialized json version of this object so that I can pass it to my react components as a prop
index method is rendering proper json on firing
UPDATE#1 for the index method
def index @search = Admin.search(params[:q]) @admins_array = @search.result(:distinct => true).to_a if params[:page] @admins = @search.result(:distinct => true).page(params[:page][:number]).per(10) @admins_json_array = Kaminari.paginate_array(@admins_array).page(params[:page][:number]).per(10) else @admins = @search.result(:distinct => true).page(1).per(10) @admins_json_array = Kaminari.paginate_array(@admins_array).page(1).per(10) end @admins_json = ActiveModel::SerializableResource.new(@admins_json_array.to_a) ... ... ...
end 3 4 Answers
I have a controller that I need to specify the serializer in, due to wanting different attributes from the default serializer.
In Controller:
def index search = User.ransack(search_params) render json: search.result, each_serializer: MembershipRenewalSerializer::MemberSerializer endSo, just to get things working, what happens if you specify the each_serializer option?
Edits:
Outside Controller:
ActiveModel::SerializableResource.new( User.first(2), each_serializer: MembershipRenewalSerializer::MemberSerializer
).to_jsonNote, that without specifying each_serializer, SerializableResource would use the UserSerializer.
Edit #2,
It looks like there is something weird happening with the @admins data.
Try converting to an array:
ActiveModel::SerializableResource.new(@admins.to_a).to_json Edit #3
To paginate your array, try the following:
@search = Admin.search(params[:q])
@results = @search.result(:distinct => true).to_a
@admins = Kaminari.paginate_array(@results).page(params[:page]).per(10) 20 Follow the guide: Serializing before controller render
You could use ActiveModel::SerializableResource.new(@admins, adapter: :json_api).to_json
in index.html.erb
<%= debug (ActiveModel::SerializableResource.new(@posts, adapter: :json_api).to_json) %>below is the output(using posts)
'{"data":[{"id":"1","type":"posts","attributes":{"title":"first post","body":null}},{"id":"2","type":"posts","attributes":{"title":"second post","body":null}}],"links":{}} 7 I create a concern with some API helper methods and there you can check if its a collection pass find the appropiate serializer and pass it to the collection serializer.
def api_response(data) render json: wrap_answer(data)
end
def wrap_answer(data) if data.respond_to?(:each) ActiveModel::Serializer::CollectionSerializer.new(data, each_serializer: ActiveModel::Serializer.serializer_for(data.first)) else data end
end should have made that into string and use json.stringify to make that as a string and make your life easy
1