【问题标题】:Serialize an array of models using active_model_serializers使用 active_model_serializers 序列化模型数组
【发布时间】:2016-07-16 15:51:54
【问题描述】:

我正在尝试使用 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 控制器的 index 方法中,Admin 对象作为 PORO 传递给 index.html 文件。但我想要这个对象的序列化 json 版本,以便我可以将它作为道具传递给我的反应组件

index 方法在触发 http://dashboard.localhost.com:3000/admins.json 时呈现正确的 json

UPDATE#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

【问题讨论】:

  • 你有我可以克隆并试用的仓库吗?
  • 不,我不能那样做。特权不够
  • 你能用足够的代码创建一个小的存储库来复制问题吗?

标签: ruby-on-rails json ruby-on-rails-4 active-model-serializers json-api


【解决方案1】:

按照指南: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":{}}

【讨论】:

  • 它没有用。还是没有得到指定格式的数据
  • PS:我在视图文件中这样做。
  • 我忘记了“.to_json”。试试看。
  • 没有 to_json,至少我得到了一些数据。我一追加 to_json => undefined method query_parameters for nil:NilClass github.com/rails-api/active_model_serializers/issues/1268,就会得到以下异常
  • 作为编辑后的答案,我确信它对 @posts 有效,它是 Post 实例的数组。您能否打印您的 @admins 中的内容以进行进一步调试?
【解决方案2】:

由于需要与默认序列化程序不同的属性,我需要在其中指定序列化程序的控制器。

在控制器中:

  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_serializerSerializableResource 将使用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)

【讨论】:

  • index render json 正在按预期工作,并以 json_api 指定的正确格式呈现 json。更新了我的问题,以反映这种状态
  • 这在我的 Rails 控制台中为我工作:ActiveModel::SerializableResource.new(User.first(2)).to_json
  • &lt;%= debug(ActiveModel::SerializableResource.new(@admins.first(2)).to_json) %&gt; 也对我有用.. 但遗憾的是 &lt;%= debug(ActiveModel::SerializableResource.new(@admins).to_json) %&gt; 没有。导致undefined method query_parameters' for nil:NilClass`
  • 可能会更容易,是的。我仍在尝试弄清楚如何在我的机器上自己复制它。
  • ActiveModel::SerializableResource 已被弃用,取而代之的是 ActiveModelSerializers::SerializableResource
【解决方案3】:

我使用一些 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

【讨论】:

    【解决方案4】:

    应该把它变成字符串并使用 json.stringify 把它变成一个字符串,让你的生活更轻松

    【讨论】:

    • 请参阅How to Answer,了解如何发布完整的答案,而不是建议
    猜你喜欢
    • 2017-03-03
    • 2020-04-15
    • 1970-01-01
    • 2017-07-17
    • 2023-04-06
    • 2014-02-11
    • 1970-01-01
    • 1970-01-01
    • 2013-01-26
    相关资源
    最近更新 更多