首页 > 解决方案 > ruby on rail - 模型中的 attr_accessor 问题

问题描述

我是一名新手 Rails 程序员,在获取数据时遇到问题。我的用户模型

class User < ActiveRecord::Base 
attr_accessor :name

我的用户控制器

@users = User.all

我的观点 users/index.html.erb

 <% @users.each do |user| %>
<%= user.name %> //error: undefined method `name`

但是如果我在用户模型中删除 attr_accessor :name,我的应用程序就会运行。请告诉我有什么问题

我的rails版本是5。

标签: ruby-on-rails

解决方案


attr_accessor 是一个类级别的方法。您正在尝试在实例级别上使用它。

试试cattr_accessor吧。尽管您不需要attr_accessororcattr_accessor来访问ActiveRecord::Base模式中定义的模型的属性。

====> 编辑 <==== 下面的更正答案

无视上面的建议。这不准确。我留下它以供参考。您收到undefined method: name错误的原因是因为您attr_accessor在已经通过ActiveRecord::Base.

设置模型数据库列attr_accessor的属性ActiveRecord::Base会导致某种冲突。当您删除该attr_accessor方法并添加应该与其完全等效的内容时...

def name
  name
end

然后尝试调用你的调用的无限递归循环,因为.name我们上面定义的 getter 方法正在调用自身,而不是访问实际上从数据库中提取数据的 ActiveRecord getter 方法。

我猜想某种方式的 active_record 模型类只会给你一个undefined method错误,而不是进行以错误结尾的递归调用stack level too deep

但是,由于您没有收到stack too deep错误,我的下一个猜测是attr_accessor您定义的覆盖动态创建的ActiveRecord::Basegetter,而 rails 仍在尝试访问覆盖的方法(不再存在)。可能导致undefined method 'name'错误。

但...

当您以这种方式添加自己的 getter 方法时......然后它就可以工作......

def name
  super
end

这是因为super您的类只是继承其动态定义的ActiveRecord::Basegetter 方法的行为。您可以通过添加来测试它...

def name
  super
  'Foo'
end

当你打电话时,@model.name你会看到它Foo被退回。从方法中删除“Foo”,返回的是super对动态创建的ActiveRecord::Basegetter 方法的调用。

我愿意对此答案进行编辑和输入。这是我在控制台中进行测试并阅读后得出的合乎逻辑的结论。

何时使用attr_accessor

另外,要进一步回答您有关何时使用的问题attr_accessor...

当您想要创建和存储与业务逻辑以及模型相关的信息并且仅在请求/实例生命周期期间持续时,您将使用它。

例如原始密码(尽管我对任何操纵原始密码的人感到畏缩)

或类似...

@stock.current_price

where@stock是一个ActiveRecord::Base对象,但是.current_price在实例化@stock对象时从 API 计算或检索,因为从数据库中持久化和检索不断变化的值(例如任何给定时间点的股票价格)是没有意义的。


推荐阅读