ActiveRecord#save_only_valid_attributes

时间:2020-03-05 18:57:53  来源:igfitidea点击:

我正在寻找只会保存的#save方法的变体
没有添加错误的属性。
因此,可以在不整体有效的情况下更新模型,这将
仍然可以防止将无效数据保存到数据库。

"有效属性"是指那些在调用@ model_instance.errors.on(:attribute)时给出nil的属性

任何人都有一个如何实现此目标的想法?

到目前为止,我有以下内容:

def save_valid_attributes 
 valid? 
 update_atrtibutes attributes.inject({}){|k, v, m| m[k] = v unless errors_on(k.to_sym); m} 
end

如果没有对赋值进行任何处理(在我的情况下就是这样),则此方法有效。
例如,我有一个数据库列" start_date",并定义了两个方法:

def nice_start_date=(startdate)
 self.start_date = Chronic.parse(startdate) || startdate
end

def nice_start_date
 self.start_date.to_s
end

这两种方法使我可以在保存之前使用"慢性"正确解析用户输入的日期。因此,第二种方法是一次设置一个属性:

def save_valid_attributes(attrib) 
  valid?
  attrib.each{|(k,v)| send("${k}=", v); save; reload)
end

每次都需要重新加载模型,因为如果其中一个日期无效且不保存,则它将阻止保存所有其他属性。

有一个更好的方法吗?我敢肯定,这在Rails界不是一个普遍的问题,我似乎在Google知识领域中找不到任何东西。

解决方案

回答

我不确定在没有太多混乱的情况下我们将获得多少运气。

不管DRY和OO如何轻松实现框架(在这种情况下,很多情况下=),我们都必须记住它运行在沼泽标准关系数据库的前面,该数据库具有原子提交,这是其定义功能之一。它是从头开始设计的,以确保所有更改都已提交或者不提交。

实际上,我们将过度使用此标准功能,而与Rails +的设计工作原理大相径庭。如前所述,这很可能导致数据不一致。

话说回来 。 。 。总是有可能的。我会仔细检查一下我们关心的属性,然后使用内置方法" object.update_attribute_with_validation_skipping"。

祝你好运!

回答

我们可以像这样覆盖#save

def save
  errors.each do |attr, msg|
    send("#{attr}=", send("#{attr}_was"))
  end
  super
end

这将重置所有属性,并在其原始值上添加错误。