使用 active_model_serializers 序列化模型数组
Serialize an array of models using active_model_serializers
我正在尝试使用 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}) %>
以上调试产生以下响应:
--- '{"data":{"id":"1","type":"admins","attributes":{"email":"tech@bluesapling.com","access_locked?":false}}}' //returned by the first debug
---
- '{"object":{"id":36,"email":"aubrey_schmitt@feeneykoch.io","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":"alysa_johnston@thompson.io","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":"kristofer.langosh@kunzeluettgen.com","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":"beryl_keler@wiza.biz","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":"wilhelmine_buckridge@crona.io","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":"edward_wisoky@corkery.net","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":"leonor@jerde.biz","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":"carley@wyman.net","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":"ervin.gleichner@cremin.org","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":"lonzo.dickens@johnscole.name","created_at":"2016-03-28T05:15:15.916Z","updated_at":"2016-03-28T05:15:15.916Z"},"instance_options":{},"root":null,"scope":null}'
在第一个调试中,我只序列化了一个对象,而在第二个调试中,我试图对一组对象进行序列化。
第一个调试正确返回对象的序列化版本(json_api 格式),而第二个调试不是。
也尝试了 ArraySerializer,但没有成功:ActiveModel::Serializer::ArraySerializer.new(@admins, each_serializer: AdminSerializer).as_json
我如何实现所需的序列化。此外,如果实现了,我可以使用其他一些简化版本吗?由于此调试语句过于冗长。
尝试了这里提到的所有解决方案 - How do you initialize an ActiveModel::Serializer class with an ActiveRecord::Relation array?
我试图解决的基本问题是,在 Admin 控制器的索引方法中,Admin 对象作为 PORO 传递给 index.html 文件。但是我想要这个对象的序列化 json 版本,这样我就可以将它作为 prop
传递给我的 React 组件
index 方法在触发时正确呈现 json http://dashboard.localhost.com:3000/admins.json
索引方法更新#1
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
遵循指南:Serializing before controller render
你可以使用 ActiveModel::SerializableResource.new(@admins, adapter: :json_api).to_json
在index.html.erb
<%= debug (ActiveModel::SerializableResource.new(@posts, adapter: :json_api).to_json) %>
下面是输出(使用帖子)
'{"data":[{"id":"1","type":"posts","attributes":{"title":"first post","body":null}},{"id":"2","type":"posts","attributes":{"title":"second post","body":null}}],"links":{}}
我有一个控制器,我需要在其中指定序列化程序,因为需要与默认序列化程序不同的属性。
在控制器中:
def index
search = User.ransack(search_params)
render json: search.result, each_serializer: MembershipRenewalSerializer::MemberSerializer
end
那么,为了让事情正常进行,如果您指定 each_serializer
选项会怎样?
编辑:
外部控制器:
ActiveModel::SerializableResource.new(
User.first(2),
each_serializer: MembershipRenewalSerializer::MemberSerializer
).to_json
请注意,如果不指定 each_serializer
,SerializableResource
将使用 UserSerializer
。
编辑#2,
@admins 数据似乎发生了一些奇怪的事情。
尝试转换为数组:
ActiveModel::SerializableResource.new(@admins.to_a).to_json
编辑 #3
要对数组进行分页,请尝试以下操作:
@search = Admin.search(params[:q])
@results = @search.result(:distinct => true).to_a
@admins = Kaminari.paginate_array(@results).page(params[:page]).per(10)
我对某些 API 辅助方法产生了担忧,您可以在其中检查其集合传递是否找到合适的序列化程序并将其传递给集合序列化程序。
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
应该把它变成字符串并使用 json.stringify 把它变成字符串,让你的生活更轻松
我正在尝试使用 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}) %>
以上调试产生以下响应:
--- '{"data":{"id":"1","type":"admins","attributes":{"email":"tech@bluesapling.com","access_locked?":false}}}' //returned by the first debug
---
- '{"object":{"id":36,"email":"aubrey_schmitt@feeneykoch.io","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":"alysa_johnston@thompson.io","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":"kristofer.langosh@kunzeluettgen.com","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":"beryl_keler@wiza.biz","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":"wilhelmine_buckridge@crona.io","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":"edward_wisoky@corkery.net","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":"leonor@jerde.biz","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":"carley@wyman.net","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":"ervin.gleichner@cremin.org","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":"lonzo.dickens@johnscole.name","created_at":"2016-03-28T05:15:15.916Z","updated_at":"2016-03-28T05:15:15.916Z"},"instance_options":{},"root":null,"scope":null}'
在第一个调试中,我只序列化了一个对象,而在第二个调试中,我试图对一组对象进行序列化。
第一个调试正确返回对象的序列化版本(json_api 格式),而第二个调试不是。
也尝试了 ArraySerializer,但没有成功:ActiveModel::Serializer::ArraySerializer.new(@admins, each_serializer: AdminSerializer).as_json
我如何实现所需的序列化。此外,如果实现了,我可以使用其他一些简化版本吗?由于此调试语句过于冗长。
尝试了这里提到的所有解决方案 - How do you initialize an ActiveModel::Serializer class with an ActiveRecord::Relation array?
我试图解决的基本问题是,在 Admin 控制器的索引方法中,Admin 对象作为 PORO 传递给 index.html 文件。但是我想要这个对象的序列化 json 版本,这样我就可以将它作为 prop
传递给我的 React 组件index 方法在触发时正确呈现 json http://dashboard.localhost.com:3000/admins.json
索引方法更新#1
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
遵循指南:Serializing before controller render
你可以使用 ActiveModel::SerializableResource.new(@admins, adapter: :json_api).to_json
在index.html.erb
<%= debug (ActiveModel::SerializableResource.new(@posts, adapter: :json_api).to_json) %>
下面是输出(使用帖子)
'{"data":[{"id":"1","type":"posts","attributes":{"title":"first post","body":null}},{"id":"2","type":"posts","attributes":{"title":"second post","body":null}}],"links":{}}
我有一个控制器,我需要在其中指定序列化程序,因为需要与默认序列化程序不同的属性。
在控制器中:
def index
search = User.ransack(search_params)
render json: search.result, each_serializer: MembershipRenewalSerializer::MemberSerializer
end
那么,为了让事情正常进行,如果您指定 each_serializer
选项会怎样?
编辑:
外部控制器:
ActiveModel::SerializableResource.new(
User.first(2),
each_serializer: MembershipRenewalSerializer::MemberSerializer
).to_json
请注意,如果不指定 each_serializer
,SerializableResource
将使用 UserSerializer
。
编辑#2,
@admins 数据似乎发生了一些奇怪的事情。
尝试转换为数组:
ActiveModel::SerializableResource.new(@admins.to_a).to_json
编辑 #3
要对数组进行分页,请尝试以下操作:
@search = Admin.search(params[:q])
@results = @search.result(:distinct => true).to_a
@admins = Kaminari.paginate_array(@results).page(params[:page]).per(10)
我对某些 API 辅助方法产生了担忧,您可以在其中检查其集合传递是否找到合适的序列化程序并将其传递给集合序列化程序。
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
应该把它变成字符串并使用 json.stringify 把它变成字符串,让你的生活更轻松