【问题标题】:Rails - how to protect an attribute against updating from outside of the modelRails - 如何保护属性不从模型外部更新
【发布时间】:2017-03-11 17:46:18
【问题描述】:

在 Rails 5 中,我有一个带有属性的模型,其值永远不会直接设置,而是始终在 before_save 回调中计算。我想保护这个属性不被从模型外部更新,所以调用像 f. e. update_attribute() 会失败。我在模型中使用了attr_readonly 来实现我想要的效果,并且效果很好,直到我意识到它会阻止所有 更新!也来自模型本身。因为,根据Rails API docs,这是正确的行为,那么拒绝对特定属性进行修改但仅从外部修改的最佳方法是什么?

【问题讨论】:

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


    【解决方案1】:

    您可以覆盖设置器。在模型上:

    def protected_attr_name=(val)
      # raise SomeException
    end
    

    这会禁用:

    model.protected_attr_name = "value"  # => raise exception
    model.update_attributes(protected_attr_name: "value")  # => raise exception
    

    然后在您的before_save 方法/块中:

    write_attribute(:protected_attr_name, calculated_value)
    

    补充意见

    attr_readonly 一样,您可以选择不引发异常,而是不做任何事情。这可能会让使用相同代码库的其他人感到困惑/沮丧,并且可能是非常不明显的行为。

    另外——如果在before_save总是计算,考虑这种保护是否必要,或者更清晰的属性命名是否可以有效地解决问题。

    【讨论】:

    • 我正要自己写这个答案。我将提供一个链接! apidock.com/rails/ActiveRecord/ReadonlyAttributes/ClassMethods/…
    • @FrederikSpang - 不幸的是,该链接没有为主题添加任何新内容。
    • @gwcodes - 这很有趣。虽然我显然知道我可以覆盖设置器,但我不知道如何从模型内部绕过此类自定义设置器,所以您说 write_attribute() 是仅从模型内部绕过此类自定义设置器的可行方法并且不能从外面工作?嗯,需要仔细检查一下。顺便说一句 - 使用attr_readonly 时,我在执行update_attribute() 时确实会抛出异常。我想保持这种状态。
    • @silverdr: 与其说write_attribute 不能在模型外部工作,不如说它可以防止意外更新,因为使用write_attribute 的人需要专门使用它并偏离既定规范。绝对保护是不切实际的,因为privateprotected 在Ruby 中比规则更具有指导意义……只要您可以更新属性,另一个类可以通过send 发送消息来实现相同的目的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-04
    • 1970-01-01
    • 1970-01-01
    • 2016-06-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多