web-dev-qa-db-fra.com

<NoMethodError: méthode non définie `read_attribute_for_serialization 'pour # <Record :: ActiveRecord_Relation:

Je reçois l'erreur:

<NoMethodError: undefined method `read_attribute_for_serialization' for #<Record::ActiveRecord_Relation:0x007faa7cfe3318>>

L'erreur se trouve sur la troisième ligne de l'extrait.

  def artist
    @records = Record.where('artist_id = ' + params[:artist_id])
    render :json => @records, serializer: RecordSummarySerializer
  end

Il s'agit d'un sérialiseur alternatif pour le contrôleur RecordsContrller. L'autre, 'RecordsSerializer, fonctionne très bien.

Une recherche sur cette erreur a permis de dégager quelques solutions. Certains ne savaient pas exactement où ajouter du code. Un autre a suggéré d'ajouter:

alias :read_attribute_for_serialization :send

à la classe où l'erreur se produit. Ça n'a pas marché pour moi. J'ai également regardé la documentation de la gemme. J'ai trouvé un exemple d'utilisation du sérialiseur :. Il était clair que tout autre code était nécessaire.

J'utilise Ruby 2.3.0 et Rails 5.0.0.

Manette

class RecordsController < ApplicationController
...
  def index
    @records = Record.order('title')
    render :json => @records
  end

  def artist
    @records = Record.where('artist_id = ' + params[:artist_id])
    render :json => @records, serializer: RecordSummarySerializer
  end
...
end

Modèle

class Record < ActiveRecord::Base
  belongs_to :artist
  belongs_to :label
  belongs_to :style
  has_many :tracks
  has_many :credits

  validates :title, presence: true
  validates :catalog, presence: true
end

record_summary_serializer.rb

include ActiveModel::Serialization
class RecordSummarySerializer < ActiveModel::Serializer
  attributes :id, :artist_id, :label_id, :style_id, :title, :catalog,
             :recording_date, :penguin, :category
end

record_serializer.rb

class RecordSerializer < ActiveModel::Serializer
  attributes :id, :artist_id, :label_id, :style_id, :title, :catalog,     :alternate_catalog,
         :recording_date, :notes, :penguin, :category
  has_one :artist
  has_many :tracks
end

Schéma des enregistrements

  create_table "records", unsigned: true, force: :cascade, options:   "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
    t.string   "title",             limit: 50
    t.string   "catalog",           limit: 20,                          null: false
    t.string   "alternate_catalog", limit: 20
    t.integer  "artist_id",                                                          unsigned: true
    t.integer  "label_id",                                                null: false, unsigned: true
    t.integer  "style_id",                                                           unsigned: true
    t.datetime "recording_date"
    t.text     "notes",             limit: 4294967295
    t.string   "penguin",           limit: 50
    t.string   "category",          limit: 50,         default: "jazz"
    t.index ["artist_id"], name: "RecordHasOneArtist", using: :btree
    t.index ["label_id"], name: "RecordHasOneLabel", using: :btree
    t.index ["style_id"], name: "RecordHasOneStyle", using: :btree
  end

Je viens de remarquer que la clé primaire, id, n'apparaît pas dans le schéma. Je le vois dans Sequel Pro lorsque je regarde la structure de la table.

Mise à jour

J'ai ajouté le code suggéré par @JMazzy. Je reçois maintenant l'erreur:

<NoMethodError: undefined method `id' for #<Record::ActiveRecord_Relation:0x007faa8005a9d8>\nDid you mean?  ids>
24
curt

J'ai eu la même erreur et j'ai trouvé la modification serializer: à each_serializer: dans le contrôleur a résolu le problème.

Contrôleur

class RecordsController < ApplicationController
...
  def artist
    @records = Record.where('artist_id = ' + params[:artist_id])
    render :json => @records, each_serializer: RecordSummarySerializer
  end
...
end

record_summary_serializer.rb - peut supprimer la ligne d'inclusion

class RecordSummarySerializer < ActiveModel::Serializer
  attributes :id, :artist_id, :label_id, :style_id, :title, :catalog,
             :recording_date, :penguin, :category
end

De active_model_serializers documentation .

Lien mis à jour. merci Lowryder

42
Kem

Vous devez ajouter include ActiveModel::Serialization à votre modèle. La sérialisation étendue n'est pas incluse par défaut dans ActiveModel. Voir cette réponse sur GitHub .

17
JMazzy
<NoMethodError: undefined method `read_attribute_for_serialization'

Cette erreur peut se produire lorsque l'objet sérialisé est nil. Envisagez d'imprimer le débogage de l'objet que vous sérialisez pour vérifier s'il s'agit de nil:

def show
  product = Product.find_by(id: params[:id])
  p "Is product nil? #{product.nil?}"
  render json: product
end

Si l'objet (product dans l'extrait ci-dessus) est nil, vous pouvez voir le NoMethodError signalé ci-dessus en raison de nil.read_attribute_for_serialization être appelé.

5
Eliot Sykes

J'ai résolu mon problème immédiat en changeant le sérialiseur personnalisé en RecordDetailSerializer et en l'appelant à partir de ma méthode show dans le contrôleur. Lorsque j'ai supprimé l'inclusion @JMazzy a suggéré que cela fonctionnait toujours. Il y a encore quelque chose de foutu. Si j'utilise la méthode personnalisée dans la méthode d'index:

def index
  @records = Record.order('title')
  render :json => @records, serializer: RecordDetailSerializer
end

J'obtiens l'erreur sur l'ID manquant indiqué au bas de ma question ci-dessus. Cependant, lorsque je l'utilise dans ma méthode d'exposition:

def show
  @record = Record.find(params[:id])
  render :json => @record, serializer: RecordDetailSerializer
end

Si je supprime le champ de problème, le champ suivant de la liste devient le problème. Ce n'est plus un problème pour moi car je peux toujours limiter les sérialiseurs personnalisés à un élément individuel.

1
curt