我试图为管理员编写一个上传完整法官的CSV的功能。当我尝试这样做时,我得到了一个AssignmentError。这对我来说真的很困惑,因为我在所有相关变量上使用了attr_accessible。我所做的所有研究都表明,如果你使用attr_accessible,你应该可以批量分配变量。
我还是铁杆新手,请原谅我,如果我做的事情真的很愚蠢。
测试CSV:
Name,Email,Competition_ID,Password
Brandon Schultz,b@schultz.com,1,12345678
Mr. Foo,foo@foo.com,1,12345678
Mr. Bar,bar@bar.com,1,12345678
错误讯息:
ActiveModel::MassAssignmentSecurity::Error in JudgesController#import
Can't mass-assign protected attributes: Name, Email, Competition_ID, Password
应用程序跟踪:
app/models/judge.rb:17:in `block in import'
app/models/judge.rb:16:in `import'
app/controllers/judges_controller.rb:32:in `import'
以下是相关模型:
class Judge < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :email, :password, :password_confirmation, :remember_me, :name, :competition_id
belongs_to :competition
def self.import(file)
CSV.foreach(file.path, headers: true) do |row|
Judge.create! row.to_hash
end
end
end
Relevent Controller:
def import
Judge.import(params[:file])
redirect_to admin_portal_path, notice: "Products imported."
end
答案 0 :(得分:2)
row.to_hash
给你的哈希值如下:
{ 'Name' => 'Mr. Foo', 'Email' => 'foo@bar.com', ... }
这里的问题是键是大写的字符串。 'Email'!='email'。
如果要将哈希直接传递给create!
,它需要完全符合属性名称,可以是字符串或符号:
{ 'name' => 'Mr. Foo', :email => 'foo@bar.com', ... }
在将密钥传递给create!
之前,您应该将密钥清理为snake_case(与其各自的可访问属性相同),或者在CSV中更改它们。
您可能还会考虑从行哈希中单独分配每个属性,如果找不到值,则指定默认值。
hash = row.to_hash
judge = Judge.new
judge.name = hash['Name'] || hash['name'] || 'No name'
judge.email = hash['Email'] || hash['email']
judge.competition_id = hash['Competition_ID'] || hash['competition_id']
在这种情况下,这可能不是最好的做法,但如果您不能严格控制CSV文件的格式,它可以使您的导入脚本更加强大。它还使您有机会在将值写入数据库之前对其进行清理。