web-dev-qa-db-fra.com

Sérialiser un tableau de modèles à l'aide de active_model_serializers

J'essaie d'envoyer la version sérialisée d'un modèle à une vue en tant que paramètre, en utilisant la gemme 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}) %>

Les débogages ci-dessus donnent la réponse ci-dessous:

--- '{"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}'

Dans le premier débogage, je sérialise un seul objet, tandis que dans le second j'essaie de le faire pour un tableau d'objets. Le premier débogage renvoie correctement la version sérialisée de l'objet (au format json_api) alors que le deuxième débogage ne l'est pas. J'ai également essayé ArraySerializer, sans succès: ActiveModel::Serializer::ArraySerializer.new(@admins, each_serializer: AdminSerializer).as_json comment puis-je obtenir la sérialisation souhaitée. De plus, s'il est atteint, puis-je utiliser une autre version simplifiée de celui-ci? Comme cette déclaration de débogage est beaucoup trop verbeuse.

J'ai essayé toutes les solutions mentionnées ici - Comment initialiser une classe ActiveModel :: Serializer avec un tableau ActiveRecord :: Relation?

Le problème de base que j'essaie de résoudre est, dans la méthode d'indexation du contrôleur Admin, l'objet Admin est passé en tant que PORO au fichier index.html. Mais je veux la version json sérialisée de cet objet afin que je puisse la passer à mes composants Reaper en tant qu'accessoire

la méthode d'index rend le json correct lors du tir http://dashboard.localhost.com:3000/admins.jsonenter image description here

MISE À JOUR # 1 pour la méthode d'index

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

J'ai un contrôleur dans lequel je dois spécifier le sérialiseur, car je souhaite avoir des attributs différents du sérialiseur par défaut.

Dans le contrôleur:

  def index
    search = User.ransack(search_params)
    render json: search.result, each_serializer: MembershipRenewalSerializer::MemberSerializer
  end

Donc, juste pour que les choses fonctionnent, que se passe-t-il si vous spécifiez le each_serializer option?

Modifications:

Contrôleur extérieur:

ActiveModel::SerializableResource.new(
  User.first(2), 
  each_serializer: MembershipRenewalSerializer::MemberSerializer
).to_json

Notez que sans spécifier each_serializer, SerializableResource utiliserait le UserSerializer.

Modifier # 2,

Il semble qu'il se passe quelque chose de bizarre avec les données @admins.

Essayez de convertir en tableau:

ActiveModel::SerializableResource.new(@admins.to_a).to_json 

Éditer # 3

Pour paginer votre tableau, essayez ce qui suit:

@search = Admin.search(params[:q])
@results = @search.result(:distinct => true).to_a
@admins = Kaminari.paginate_array(@results).page(params[:page]).per(10)
33
NullVoxPopuli

Suivez le guide: Sérialisation avant le rendu du contrôleur

Vous pouvez utiliser ActiveModel::SerializableResource.new(@admins, adapter: :json_api).to_json

dans index.html.erb

<%= debug (ActiveModel::SerializableResource.new(@posts, adapter: :json_api).to_json) %>

ci-dessous est la sortie (en utilisant les messages)

'{"data":[{"id":"1","type":"posts","attributes":{"title":"first post","body":null}},{"id":"2","type":"posts","attributes":{"title":"second post","body":null}}],"links":{}}
2
abookyun

Je crée un problème avec certaines méthodes d'assistance API et là, vous pouvez vérifier si c'est une passe de collection trouver le sérialiseur approprié et le passer au sérialiseur de collection.

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