NoMethodError: undefined method `read_attribute_for_serialization' for #<Record::ActiveRecord_Relation: 没有方法错误:未定义方法`read_attribute_for_serialization'用于#<Record::ActiveRecord_Relation:

32

I'm getting the error:

<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

将错误所在的类指向。对我来说没有用。我还查看了gem文档。我找到了一个使用serializer的示例:很明显不需要任何其他代码。

我正在使用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中可以看到它。

更新

我添加了@JMazzy建议的代码。现在我收到以下错误:

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

2
请记住,在生产环境中不要留下Record.where('artist_id = ' + params[:artist_id])这样的代码,因为它可能会导致 SQL 注入攻击。请改用Record.where(artist_id: params[:artist_id])或者Record.where('artist_id = ?', params[:artist_id])来替代。 - Leonel Galán
6个回答

52
我遇到了同样的错误,并发现在控制器中将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


6
将“serializer”更改为“each_serializer”对我有效。谢谢! - FutoRicky
3
文档链接已失效,这里提供一个新的链接:https://github.com/ggordon/active_model_serializers/blob/master/README.md#2-for-an-array-resource - Pascal

32

您需要在您的模型中添加include ActiveModel::Serialization。 扩展序列化在ActiveModel中不是默认包含的。 请参见GitHub上此答案


当你说“对我的模型”,你指的是哪里?我在record.rb文件中添加了一行代码,然后出现了不同的错误。更多信息请参见原始问题。 - curt
我有一个简单的类(不是ActiveRecord类),添加include ActiveModel::Serialization解决了错误!谢谢! - ZedTuX

13
<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


1

添加serializable_hash并直接初始化构造函数,即

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

...解决了我的问题。


1
我通过将自定义序列化器更改为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

如果我移除问题字段,列表中的下一个字段就会成为问题。这对我来说不再是一个问题,因为我可以始终将自定义序列化器限制为单个元素。

0

在视图模板中尝试序列化记录数组时,我遇到了这个错误。

我有:

InviteSerializer.new(@invites) }                   # throws errror

我需要:

@invites.map { |i| InviteSerializer.new(i) }       # works!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接