【问题标题】:Prevent change of one field in Rails model防止更改 Rails 模型中的一个字段
【发布时间】:2013-02-08 19:23:54
【问题描述】:

我有两个相关的模型 - 比如说 ActivityStepActivity has_many :stepsStep belongs_to :activity 这意味着 steps 的表有一个 activity_id 列。

这是在 Hobo 1.3 中,所以在 Rails 3.0 中。

我想要的是确保在创建Step 之后不可能将步骤移动到另一个Activity。我们不希望 activity_id 字段发生变化。

我已从编辑表单中删除了该字段,但我正在寻找更强的约束。本质上,我想在update(而不是create)上验证该列没有被触及。 Hobo 的文档没有在 Hobo 内部提出任何建议,所以我正在查看 Rails validations,但到目前为止,我还没有找到我记得的“仅在更新时执行此操作”约束,也没有验证某些东西是'没有改变。

【问题讨论】:

    标签: ruby-on-rails-3 validation hobo


    【解决方案1】:

    验证包含:

      validates :activity_id,
                inclusion: { in: ->(i) { [i.activity_id_was] } },
                on: :update
    

    不需要额外的方法。

    【讨论】:

    • 这实际上效果很好。目前还不清楚发生了什么,因此为您的同事和未来的自己添加评论会有所帮助。此外,它生成的默认错误消息不是很好(例如“activity_id 未包含在列表中”),因此我建议在 inclusion 内添加一个 message 参数,上面写着“创建后无法更改” .
    【解决方案2】:

    您可以使用attr_readonly :your_field_name 将属性声明为只读。 但是,如果您尝试编写此属性,这不会产生错误,它会默默地失败。 (所有 SQL 更新都将忽略此属性)

    另一种选择可能是,为这种情况编写验证,可能如下所示:

    class Step < ActiveRecord::Base
      validate :activity_id_not_changed
    
      private
    
      def activity_id_not_changed
        if activity_id_changed? && self.persisted?
          errors.add(:activity_id, "Change of activity_id not allowed!")
        end
      end
    end
    

    persisted? 返回真,如果这不是一条新记录并且它没有被销毁。

    链接:

    http://api.rubyonrails.org/classes/ActiveRecord/ReadonlyAttributes/ClassMethods.html#method-i-readonly_attributes

    http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-persisted-3F

    【讨论】:

    • attr_readonly 像宣传的那样工作,但可能会导致应用程序的另一个方面出现问题。明天我会尝试验证方法,看看是否效果更好。
    • 如果您确实需要在应用程序的其他位置更改 ID,即使使用以下验证方法也可以这样做:step.save(:validate =&gt; false)
    • 这不是其他地方的变更问题;这是一个对象副本。 (所以,假设我们以一种同时复制所有Steps 的方式复制了Activity;由于某种原因这不起作用,而且我还没有深入研究复制代码以了解此更改是否破坏了它.)
    【解决方案3】:

    我认为你也可以使用 Hobo 权限系统做到这一点:http://hobocentral.net/manual/permissions

    例如:

    def update_permitted?
      acting_user.administrator && !activity_id_changed?
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-28
      • 2016-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多