0

There is a form that a user submits which then gets validated by the model. I only want the field "Province / State" to validate if the "Country" is either "CA" (Canada) or "US" (USA)

The form is set up a little differently because we are doing a multiple step from process.

Here is the controller.

    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

I hard coded optional: true but I only want optional:true if the user selected CA/US OR the field saved is CA/US.

I took a look at lambda and it could be something I need.

For Example:

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

2 Answers2

1

Unfortunately, you cannot (currently) provide a lambda to optional - see the source code:

required = !reflection.options[:optional]

If required, Rails just adds a presence validation like this:

model.validates_presence_of reflection.name, message: :required

Therefore as a workaround, you could do this in two parts: First specify the association as optional; then explicitly make it required for your condition:

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

If the logic gets significantly more complicated, you may wish to move this into a separate method/class instead of an inline lambda. See: Performing Custom Validations

Tom Lord
  • 27,404
  • 4
  • 50
  • 77
0

You can make validation with lambda condition like this:

validates :state, presence: true, if: -> { %w[US CA].include?(country) }
mechnicov
  • 12,025
  • 4
  • 33
  • 56