【问题标题】:Better way to write before_save function to check all targeted attributes not blank?编写 before_save 函数以检查所有目标属性不为空的更好方法?
【发布时间】:2013-08-29 06:41:56
【问题描述】:

在我的项目中,我有一个具有四个属性的模型:名称、描述、内容和完成。

我想在保存之前检查所有属性,除了完成是否为空白。如果不为空,则设置完成为 1,否则为 0。

我使用 ActiveRecord 和 Mysql,所以它也会有 id、created_at 和 updated_at 列。

我写了一个这样的 before_save 回调:

def check_completed
  if self.attributes.except("id", "created_at", "updated_at").all? {|k, v| v.present?}
    self.completed = 1
  else
    self.completed = 0
  end
end

它有效,但看起来很难看。我想删除 except 函数调用。

有没有更好的方法来做到这一点?

【问题讨论】:

  • 相信我,还有很多丑陋的代码块。这个不错。 :)

标签: ruby-on-rails activerecord ruby-on-rails-3.2


【解决方案1】:

我假设使用了 .except 方法,因为 id、created_at 和 updated_at 都是由 MySQL 内部生成和管理的。因此,该列表扩展或更改将是不寻常的。我同意提供的代码很好。如果你想缩短它,你可以使用三元:

def check_completed
  self.attributes.except("id", "created_at", "updated_at").all? {|k, v| v.present?} ? 1 : 0
end

消除 .except 方法使您可以在模型更改时随时管理此方法。

扩展此讨论: 我很好奇您希望返回 1 还是 0?没有看到更多代码,我不确定您的意图。但是,如果“之前”回调返回 false,则停止执行并回滚事务。在任何其他情况下,继续执行。在 Ruby 中,0 不是假的。 False 仅由 false 或 nil 触发。我的期望是它更有可能使用 true 代替 1 和 false 代替 0?如果是这样,代码将是:

def check_completed
  self.attributes.except("id", "created_at", "updated_at").all? {|k, v| v.present?} ? true : false
end

这样,如果任何用户属性不存在,事务将被取消并回滚。但是,这取决于你。

【讨论】:

    【解决方案2】:

    我建议不要依赖self.attributes,因为您将来可能希望为您的模型添加其他属性。如果是这样,您必须将新属性添加到您的 except 列表中。

    相反,您可以这样做:

    self.completed = %w(name description content).all? { |attr| !send(attr).blank? } ? 1 : 0
    

    【讨论】:

    • 哇,酷。但是如果模型有更多的属性要检查,数组列表也会变得更长。也许我应该写一个模块来处理它。感谢您的拼写更正。
    • 嗯,是的。我假设在这里它会保持合理。你可能想把它翻译成一个方法,这样你就可以做类似self.completed = completable?
    • 是的,其他型号也会使用它。在其中一些中,应该排除更多属性。所以我会尝试编写一个类宏,我可以将它用作'check_completed, :except => [:scale, :version]'。
    猜你喜欢
    • 2018-01-15
    • 1970-01-01
    • 2018-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多