【问题标题】:<NoMethodError: undefined method `read_attribute_for_serialization' for #<Record::ActiveRecord_Relation:<NoMethodError: #<Record::ActiveRecord_Relation: 的未定义方法“read_attribute_for_serialization”:
【发布时间】:2016-07-21 17:06:41
【问题描述】:

我收到了错误:

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

错误在 sn-p 的第三行。

  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 文档。我找到了一个使用序列化器的例子:。很明显,还需要任何其他代码。

我正在使用 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>

【问题讨论】:

  • 请记住不要将Record.where('artist_id = ' + params[:artist_id]) 留在生产环境中,因为它可能会打开您的应用程序以进行 SQL 注入。改用:Record.where(artist_id: params[:artist_id])Record.where('artist_id = ?', params[:artist_id])

标签: ruby-on-rails active-model-serializers


【解决方案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 - 可以删除包含行

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

来自 active_model_serializers documentation

更新链接。谢谢洛瑞德

【讨论】:

【解决方案2】:

您需要将include ActiveModel::Serialization 添加到您的模型中。 ActiveModel 中默认不包含扩展序列化。见this answer on GitHub

【讨论】:

  • 你对我的模特说什么是什么意思?我在record.rb中添加了一行。然后我得到了一个不同的错误。有关更多信息,请参阅原始问题
  • 我有一个简单的类(不是 ActiveRecord 类)并添加 include ActiveModel::Serialization 解决了错误!谢谢!
【解决方案3】:
<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

如果对象(上面的 sn-p 中的product)是nil,那么由于调用了nil.read_attribute_for_serialization,您可能会看到上面报告的NoMethodError

【讨论】:

    【解决方案4】:

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

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

    【讨论】:

      【解决方案5】:

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

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

      ...帮我解决了。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-06-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-24
        • 2015-05-19
        • 1970-01-01
        相关资源
        最近更新 更多