【问题标题】:Using parameter to control Rails validations使用参数控制 Rails 验证
【发布时间】:2009-12-21 02:06:49
【问题描述】:

我有一个 Event 模型,其中包含一个 finish_time 字段和一个名为 whenever 的表单复选框。当whenever 被选中时,我想将finish_time 设置为nil,而不管它在参数中的值如何,当whenever 未被选中时,我想确保finish_time 是一个有效日期,然后再将其保存在数据库。


目前我正在使用whenever attr_accessor on Event:

params[:event][:finish_time] = nil if whenever = params[:event].delete(:whenever)
@event = Event.new(params[:event])
@event.whenever = whenever

如果wheneverfalse,则使用条件验证来检查finish_time

validates_presence_of :finish_time, :unless => @whenever

我对这造成的重复不满意。 finish_time 可以是nil 的唯一方法是whenevertrue,如果您更改其中一个,则通常必须更改另一个。如果Event 更新为新的finish_time,则whenever 也必须更改为false

理想情况下,我想将验证移至我的控制器。这样,在进行直接模型访问时,whenever 可以通过将finish_time 设置为null 来轻松指示,但是如果用户没有指示选择,发布到 /events 的用户会被骂。但是,我想不出一种方法来有条件地从控制器中添加或删除对Event 的验证,或者即使这是最好的方法。

删除这种重复的最佳方法是什么?

【问题讨论】:

    标签: ruby-on-rails refactoring controller dry


    【解决方案1】:

    您可以尝试以“Ruby 方式”解决问题,而不是尝试通过验证来解决问题。

    除了验证之外,您可能还想挂钩finish_timewhenever 方法的mutators。

    class Event < ActiveRecord::Base
      # Validate presence
      validates_presence_of :finish_time, :unless => @whenever
    
      def whenever=(yes)
        write_attribute(:whenever, yes)
        write_attribute(:finish_time, nil) if yes?
      end
      def finish_time=(time)
        write_attribute(:whenever, false)
        write_attribute(:finish_time, time)
      end
    end
    

    那你可以试试(不过,我不确定它是否有效):

    @event = Event.new(params[:event])
    

    编辑:但是,这将使结果字段取决于发生的顺序分配,因此如果分配顺序发生变化,相同参数集的结果可能会有所不同.这不太可能是你想要的。所以你必须按照你想要的方式调整你的操作符。

    而且您还应该了解,除非您使您的需求干燥,否则您将无法使您的代码干燥。

    编辑#2:如果whenever 设置为true,我认为您应该考虑放弃finish_timenil 的要求。然后,您可以按照上述相同的方式修改访问器。

    【讨论】:

    • 保持我的要求干燥的好点。也许除了 null 之外还有一些 Date 值可能表示“不关心”而不是空的?我认为问题在于使一个值意味着两件事。我想不出任何不使用幻数的方法。
    • 这很有意义。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-17
    • 1970-01-01
    • 2011-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多