2010-10-15 86 views
65

我已经使用RESTful技术来生成模型(实际上,我使用的是Devise gem,这对我来说是这样),并且我添加了名为first_name的新字段和姓氏到模型。迁移进展良好。我在模型中添加了attr_accessor:first_name,:last_name,并且预计它会正常工作。但是,当我尝试用Doctor.create({:first_name =>“MyName”})等方式批量分配新实例时,出现错误,说我无法批量分配受保护的属性。“警告:无法批量分配受保护的属性”

我认为使用attr_accessor的重点是解决模型字段的保护问题。你能帮我理解这个信息吗?

编辑:哦,顺便也没有创建记录。我认为他们应该是因为这只是一个警告,但他们不在数据库上。

EDIT2:这里是我的模型

class Doctor < User 
    has_many :patients 
    has_many :prescriptions, :through=> :patients 

    validates_presence_of :invitations, :on => :create, :message => "can't be blank" 

    attr_accessor :invitations 
end 

和模式,不具备FIRST_NAME和姓氏,因为它们在用户表,这是医生的祖先创造。我使用单表继承。

create_table :doctors do |t| 
    t.integer :invitations 

    t.timestamps 
end 

,这是改变用户表

add_column :users, :first_name, :string 
add_column :users, :last_name, :string 
add_column :users, :type, :string 

编辑迁移:这里是种子文件。我不包括truncate_db_table方法,但它的工作原理。

%w{doctors patients}.each do |m| 
    truncate_db_table(m) 
end 

Doctor.create(:invitations=>5, :email=>"[email protected]", :first_name=>"Name", :last_name=>"LastName") 
Patient.create(:doctor_id=>1, :gender=>"male", :date_of_birth=>"1991-02-24") 
+0

我不是很了解Rails 4,但我认为这个问题是Rails 3的问题。 Rails 4中'config/application.rb'中的默认硬编码配置是空白的! – 2014-03-21 02:25:32

+0

http://apidock.com/rails/ActiveRecord/Base/attr_accessible/class – shilovk 2014-08-31 13:21:40

回答

139

请勿混淆attr_accessorattr_accessible。 Accessor内置于Ruby中,并定义了一个getter方法 - model_instance.foo # returns something - 和一个setter方法 - model_instance.foo = 'bar'

可访问性由Rails定义,并使该属性可以进行批量赋值(与attr_protected相反)。

如果first_name是模型数据库表中的字段,那么Rails已经为该属性定义了getter和setter。你只需要添加attr_accessible :first_name即可。

+0

现在,当我收集种子文件时,我在邀请函中收到“未知属性”错误。但我知道我在数据库中有这个字段;它在迁移文件中... – picardo 2010-10-15 17:16:33

+0

它在迁移文件中,但是您是否运行迁移?发布你的种子文件。 – 2010-10-15 17:31:16

+0

你更新了其他的东西吗?尽管这是错误的,但您的模型中仍然有attr_accessor。 – 2010-10-15 18:05:43

1

这里不要使用attr_accessor。 ActiveRecord在模型上自动创建它们。另外,如果引发验证或批量分配错误,ActiveRecord不会创建记录。

编辑:你不需要医生表,你需要一个用户表与类型列来处理导轨Single Table Inheritance。邀请将在用户表上。啊,我看到在你添加的代码示例中你确实输入了用户。摆脱医生桌,将邀请转移给用户,我认为你应该没问题。还要摆脱attr_accessor。不需要。

请记住,rails STI对特定模型的所有类和子类使用相同的表。你所有的医生记录将在用户表中的一排“医生”

编辑:另外,你确定你只是想验证创建邀请的存在,而不是更新?

+0

虽然我不使用它,但Rails告诉我“找不到方法”,因为我正在搜索种子文件。我应该怎么做呢? – picardo 2010-10-15 16:46:34

+0

你可以发布你的模型代码和耙子任务吗?也是创建该模型的迁移。确保这些列是在数据库中创建的。 – 2010-10-15 16:48:39

11

要一起黑客以不安全的方式完全不适合生产模式的应用:

进入/配置/应用。rb向下滚动到您将找到的末端

{config.active_record.whitelist_attributes = true} 

将其设置为false。

编辑/ BTW(4个月的红宝石密集型的工作,包括11一周的讲习班后): DHH认为,为noobies(他的话),“启动并运行”比“​​非常安全”更重要。

被建议:虽然这个答案(我认为是第一次在stackoverflow上)现在是+6,它的历史已经低至-4了,这意味着很多有经验的rails开发者都会觉得很热情约不是希望你这样做。

UPDATE: 3年后,另一种方式来做到这一点 - 再次,并不安全,但比上述的解决方案可能是因为你必须这样做,每个模型

class ModelName < ActiveRecord::Base 
    column_names.each do |col| 
    attr_accessible col.to_sym 
    end 
    ... 
end 
+32

即使有“早期编码”的警告,这也是一个非常糟糕的建议。开发人员何时有机会回顾并重构他们的整个应用程序?从一开始就适当地做。 – toxaq 2012-06-13 09:17:50

+4

“记住这是一个安全漏洞,但你可以稍后处理”你打算什么时候处理它?后来,当它在生产?我刚刚添加了“你对attr_accessible的看法?”到我的面试问题列表。 – toxaq 2012-06-19 00:09:02

+0

我可以提出一个修改来澄清你的答案吗?从您的文章中,并不完全清楚默认值是更安全的方法,并将其更改为false可轻松访问模型属性,但会打开不良的安全漏洞。 – Excalibur 2012-07-18 23:11:41

0

添加attr_accessible : variable1, variable2,以更好地你表路由文件。

0

同意@Robert Speicher的回答但我会强烈建议您使用Strong parameter而不是attr_accessible来防止大规模排队。

干杯!

相关问题