web-dev-qa-db-ja.com

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":"[email protected]","access_locked?":false}}}' //returned by the first debug


---
- '{"object":{"id":36,"email":"[email protected]","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":"[email protected]","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":"[email protected]","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":"[email protected]","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":"[email protected]","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":"[email protected]","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":"[email protected]","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":"[email protected]","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":"[email protected]","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":"[email protected]","created_at":"2016-03-28T05:15:15.916Z","updated_at":"2016-03-28T05:15:15.916Z"},"instance_options":{},"root":null,"scope":null}'
_

最初のデバッグでは1つのオブジェクトのみをシリアル化していますが、2番目のデバッグではオブジェクトの配列に対してシリアル化を試みています。最初のデバッグは、オブジェクトのシリアライズバージョン(json_api形式)を正しく返しますが、2番目のデバッグはそうではありません。 ArraySerializerも試してみましたが、成功しませんでした:ActiveModel::Serializer::ArraySerializer.new(@admins, each_serializer: AdminSerializer).as_json目的のシリアル化を実現するにはどうすればよいですか。さらに、達成された場合、他の簡単なバージョンを使用できますか?このデバッグ文は冗長すぎるためです。

ここで言及されているすべてのソリューションを試しました- ActiveModel :: SerializerクラスをActiveRecord :: Relation配列でどのように初期化しますか?

私が解決しようとしている基本的な問題は、Adminコントローラーのindexメソッドで、AdminオブジェクトがPOROとしてindex.htmlファイルに渡されることです。しかし、私はこのオブジェクトのシリアル化されたjsonバージョンを必要とするので、それをpropとして自分のreactコンポーネントに渡すことができます

indexメソッドは、発火時に適切なjsonをレンダリングしています http://dashboard.localhost.com:3000/admins.jsonenter image description here

インデックスメソッドの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
_
14
vipin8169

デフォルトのシリアライザとは異なる属性が必要なため、シリアライザを指定する必要があるコントローラがあります。

コントローラ内:

  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を指定しないと、SerializableResourceUserSerializerを使用することに注意してください。

#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)
33
NullVoxPopuli

ガイドに従ってください: コントローラのレンダリング前にシリアル化

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":{}}
2
abookyun

いくつかの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
0
ZZ4