<NoMethodError: undefined метод `read_attribute_for_serialization 'для # <Record:: ActiveRecord_Relation:
Я получаю сообщение об ошибке:
<NoMethodError: undefined method `read_attribute_for_serialization' for #<Record::ActiveRecord_Relation:0x007faa7cfe3318>>
Ошибка в третьей строке фрагмента.
def artist
@records = Record.where('artist_id = ' + params[:artist_id])
render :json => @records, serializer: RecordSummarySerializer
end
Это альтернативный сериализатор для контроллера RecordsContrller. Другой, "RecordsSerializer", отлично работает.
Поиск по этой ошибке вызвал несколько решений. Некоторым было неясно, куда добавить код. Другой предложил добавить:
alias :read_attribute_for_serialization :send
в класс, где происходит ошибка. Это не сработало для меня. Я также просмотрел документацию о драгоценных камнях. Я нашел пример использования сериализатора:. Было ясно, что нужен другой код.
Я использую 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
Model
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, когда просматриваю структуру таблицы.
Update
Я добавил код, предложенный @JMazzy. Теперь я получаю сообщение об ошибке:
<NoMethodError: undefined method `id' for #<Record::ActiveRecord_Relation:0x007faa8005a9d8>\nDid you mean? ids>
Ответы
Ответ 1
У меня была такая же ошибка и я обнаружил, что изменение 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 - можно удалить строку include
class RecordSummarySerializer < ActiveModel::Serializer
attributes :id, :artist_id, :label_id, :style_id, :title, :catalog,
:recording_date, :penguin, :category
end
От active_model_serializers документация.
Обновлена ссылка. спасибо Lowryder
Ответ 2
Вам нужно добавить include ActiveModel::Serialization
к вашей модели. Расширенная сериализация не включена по умолчанию в ActiveModel. См. этот ответ на GitHub.
Ответ 3
Я исправил свою ближайшую проблему, изменив собственный сериализатор на RecordDetailSerializer и вызвав его из моего метода show в контроллере. Когда я удалил include @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
Если я удалю поле проблемы, следующее поле в списке станет проблемой. Это не проблема для меня, поскольку я всегда могу ограничить собственные сериализаторы и отдельные элементы.
Ответ 4
<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
, вы можете увидеть сообщение NoMethodError
, указанное выше, из-за вызова nil.read_attribute_for_serialization
.