web-dev-qa-db-ja.com

<NoMethodError:#<Record :: ActiveRecord_Relationの未定義メソッド `read_attribute_for_serialization '

エラーが発生しています:

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

エラーはスニペットの3行目にあります。

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

これは、コントローラーRecordsContrllerの代替シリアライザーです。もう1つ、「RecordsSerializer」は正常に動作します。

このエラーを検索すると、いくつかの解決策が見つかりました。コードを追加する場所が不明な人もいました。別の提案を追加:

alias :read_attribute_for_serialization :send

エラーが発生したクラスに。私にはうまくいきませんでした。また、gemのドキュメントにも目を通しました。シリアライザーの使用例を見つけました。他のコードが必要であることは明らかでした。

私はRuby 2.3.0およびRails 5.0.0。

コントローラ

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

モデル

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

レコードのスキーマ

  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

主キーidがスキーマに表示されないことに気付きました。テーブル構造を表示すると、Sequel Proに表示されます。

更新

@JMazzyによって提案されたコードを追加しました。私は今エラーを受け取ります:

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

同じエラーが発生し、serializer:からeach_serializer:コントローラーで問題を解決しました。

コントローラー

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-インクルード行を削除できます

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

Active_model_serializersから ドキュメント

リンクを更新しました。おかげでLowryder

42
Kem

モデルにinclude ActiveModel::Serializationを追加する必要があります。 ActiveModelにはデフォルトで拡張シリアル化は含まれていません。 GitHubのこの回答 を参照してください。

17
JMazzy
<NoMethodError: undefined method `read_attribute_for_serialization'

このエラーは、シリアル化されるオブジェクトがnilの場合に発生する可能性があります。 nilであるかどうかを確認するために、シリアル化するオブジェクトのデバッグを印刷することを検討してください。

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

オブジェクト(上記のスニペットのproduct)がnilである場合、nil.read_attribute_for_serializationが呼び出されているため、上記のNoMethodErrorが表示される場合があります。

5
Eliot Sykes

カスタムシリアライザーをRecordDetailSerializerに変更し、コントローラーのshowメソッドから呼び出して、当面の問題を修正しました。インクルードを削除したとき、@ JMazzyはまだ機能することを示唆しました。まだ厄介なものがあります。インデックスメソッドでカスタムメソッドを使用する場合:

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

上記の質問の下部に表示されている欠落しているIDでエラーが発生します。ただし、showメソッドで使用する場合:

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

問題のフィールドを削除すると、リストの次のフィールドが問題になります。カスタムシリアライザーを常に個別の要素に制限できるため、これはもはや問題ではありません。

1
curt