对于大量值分配到ActiveRecord模型而不保存,使用assign_attributes或attributes=方法。这些方法在Rails 3和更新版本中可用。但是,有一些小的差异和版本相关的陷阱需要注意。
这两种方法都遵循以下用法:
@user.assign_attributes{ model: "Sierra", year: "2012", looks: "Sexy" }
@user.attributes = { model: "Sierra", year: "2012", looks: "Sexy" }
注意,这两个方法都不会执行验证或执行回调;调用save时将发生回调和验证。
Rails 3
attributes=与Rails 3中的assign_attributes略有不同。attributes=将检查传递给它的参数是否为哈希,如果不是则立即返回;assign_attributes没有这样的哈希检查。有关attributes=,请参阅ActiveRecord属性赋值API文档。
下面的无效代码将在不设置属性的情况下直接返回,从而无声地失败:
@user.attributes = [ { model: "Sierra" }, { year: "2012" }, { looks: "Sexy" } ]
Attributes =会默默地表现得好像赋值成功了一样,但实际上并没有。
当assign_attributes试图string化封闭数组的哈希键时,这段无效的代码将引发异常:
@user.assign_attributes([ { model: "Sierra" }, { year: "2012" }, { looks: "Sexy" } ])
assign_attributes将为stringify_keys引发一个NoMethodError异常,表明第一个参数不是哈希。异常本身并不能很好地说明实际的原因,但是异常确实发生的事实是非常重要的。
这些情况之间的唯一区别是用于批量分配的方法:attributes=无声地成功,而assign_attributes引发一个异常,通知发生了错误。
这些例子看起来可能是人为的,而且在某种程度上确实如此,但是当从API转换数据时,或者甚至只是使用一系列数据转换而忘记对最终的.map结果进行Hash时,这种类型的错误很容易发生。维护一些超过50行的代码,并从属性赋值中删除3个函数,就会导致失败。
Rails 3的教训是:总是使用assign_attributes而不是attributes=。
Rails 4
在Rails 4中,attributes=只是assign_attributes的别名。有关attributes=,请参阅ActiveRecord属性赋值API文档。
在Rails 4中,这两种方法都可以互换使用。未能将哈希作为第一个参数传递将导致一个非常有用的异常:ArgumentError:当分配属性时,您必须将哈希作为参数传递。
验证
如果你正在为保存而准备飞行任务,你可能也有兴趣在保存前进行验证。你可以使用有效的?和无效的?方法。两者都返回布尔值。有效吗?如果未保存的模型通过所有验证,则返回true;如果未通过验证,则返回false。无效的?仅仅是有效的逆吗?
有效吗?可以这样使用:
@user.assign_attributes{ model: "Sierra", year: "2012", looks: "Sexy" }.valid?
这将使您能够在调用save之前处理任何验证问题。