仅当用户指定特定值时才使字段有效,否则可选

Making field validate only if user specified a certain value, otherwise optional

有一个用户提交的表单,然后由模型验证。我只希望字段 "Province / State" 验证 "Country" 是 "CA"(加拿大)还是 "US"(美国)

表单的设置略有不同,因为我们从流程中执行多个步骤。

这是控制器。

    def update
        case step
        when :step1
          wizard_params = profile_params()
          wizard_params[:wizard] = 'step1'

          @profile = current_user.profile
          @profile.update(wizard_params)

          render_wizard @profile
end

    private
        def profile_params
          # There are more params although I stripped them for the simplicity of this example
          params.require(:profile).permit(:state_id, :country)
        end

Profile.rb

  belongs_to :state, :class_name => "ProvinceState", :foreign_key => :state_id, optional: true

我硬编码了 optional: true 但我只想要 optional:true 如果用户选择 CA/US 或者保存的字段是 CA/US.

我看了一下 lambda,它可能是我需要的东西。

例如:

belongs_to :state, :class_name => "ProvinceState", :foreign_key => :state_id, optional: lambda | obj | self.country == CA || self.country == US ? true : false 

不幸的是,您不能(目前)向 optional 提供 lambda - 请参阅 source code:

required = !reflection.options[:optional]

如果需要,Rails 只需像这样添加存在验证:

model.validates_presence_of reflection.name, message: :required

因此,作为变通方法,您可以分两部分执行此操作:首先将关联指定为 optional;然后明确地使其成为您的条件所必需的:

belongs_to :state, :class_name => "ProvinceState", :foreign_key => :state_id, optional: true
validates :state_id, presence: true, if: ->{ %w[CA US].include?(country) }

如果逻辑变得复杂得多,您可能希望将其移至单独的 method/class 而不是内联 lambda。参见:Performing Custom Validations

您可以像这样使用 lambda 条件进行验证:

validates :state, presence: true, if: -> { %w[US CA].include?(country) }