0
votes

I have a validation happening during the input process like so:

validates :solids, :numericality => { :greater_than_or_equal_to => 0 }, :if => lambda { 
  if self.lab_method_id
    lab_method = LabMethod.find(self.lab_method_id)
    lab_method.solids?
  end
}

I want this condition to change based on the selected id of a drop down box.

I tried this in my model:

if self.lab_method_id == 1
validates :solids, :numericality => { :greater_than_or_equal_to => 0 }, :if => lambda { 
  if self.lab_method_id
    lab_method = LabMethod.find(self.lab_method_id)
    lab_method.solids?
  end
}
elsif
validates :solids, :numericality => { :greater_than_or_equal_to => 5 }, :if => lambda { 
  if self.lab_method_id
    lab_method = LabMethod.find(self.lab_method_id)
    lab_method.solids?
  end
}
end

However this returned the error on page load:

undefined method `key?' for nil:NilClass

I figured this had to do with the fact that the validations in the model get loaded on page load and this an if statement checking for the id at that time would not work. Although this error doesn't quite make sense to me.

So I am wondering how to set it up in a way that the specific validation is chosen based on the id of the drop down box item selected (am I even getting the id properly)?

Bonus: could someone explain the relationship to this particular error?

EDIT - stack trace:

vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.1/lib/action_controller/metal/hide_actions.rb:36:in visible_action?' vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.1/lib/action_controller/metal/hide_actions.rb:18:inmethod_for_action' vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.1/lib/action_controller/metal/implicit_render.rb:14:in method_for_action' vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.1/lib/action_controller/metal/compatibility.rb:61:inmethod_for_action' vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.1/lib/abstract_controller/base.rb:115:in process' vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.1/lib/abstract_controller/rendering.rb:45:inprocess' vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.1/lib/action_controller/metal.rb:203:in dispatch' vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.1/lib/action_controller/metal/rack_delegation.rb:14:indispatch' vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.1/lib/action_controller/metal.rb:246:in block in action' vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.1/lib/action_dispatch/routing/route_set.rb:66:incall' vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.1/lib/action_dispatch/routing/route_set.rb:66:in dispatch' vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.1/lib/action_dispatch/routing/route_set.rb:30:incall' vendor/bundle/ruby/1.9.1/gems/journey-1.0.4/lib/journey/router.rb:68:in block in call' vendor/bundle/ruby/1.9.1/gems/journey-1.0.4/lib/journey/router.rb:56:ineach' vendor/bundle/ruby/1.9.1/gems/journey-1.0.4/lib/journey/router.rb:56:in call' vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.1/lib/action_dispatch/routing/route_set.rb:589:incall' vendor/bundle/ruby/1.9.1/gems/warden-1.2.1/lib/warden/manager.rb:35:in block in call' vendor/bundle/ruby/1.9.1/gems/warden-1.2.1/lib/warden/manager.rb:34:incatch' vendor/bundle/ruby/1.9.1/gems/warden-1.2.1/lib/warden/manager.rb:34:in call' vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.1/lib/action_dispatch/middleware/best_standards_support.rb:17:incall' vendor/bundle/ruby/1.9.1/gems/rack-1.4.1/lib/rack/etag.rb:23:in call' vendor/bundle/ruby/1.9.1/gems/rack-1.4.1/lib/rack/conditionalget.rb:25:incall' vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.1/lib/action_dispatch/middleware/head.rb:14:in call' vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.1/lib/action_dispatch/middleware/params_parser.rb:21:incall' vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.1/lib/action_dispatch/middleware/flash.rb:242:in call' vendor/bundle/ruby/1.9.1/gems/rack-1.4.1/lib/rack/session/abstract/id.rb:205:incontext' vendor/bundle/ruby/1.9.1/gems/rack-1.4.1/lib/rack/session/abstract/id.rb:200:in call' vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.1/lib/action_dispatch/middleware/cookies.rb:338:incall' vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.1/lib/active_record/query_cache.rb:64:in call' vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:443:incall' vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.1/lib/action_dispatch/middleware/callbacks.rb:28:in block in call' vendor/bundle/ruby/1.9.1/gems/activesupport-3.2.1/lib/active_support/callbacks.rb:405:inrun_803795940_call_68852270__callbacks' vendor/bundle/ruby/1.9.1/gems/activesupport-3.2.1/lib/active_support/callbacks.rb:405:in __run_callback' vendor/bundle/ruby/1.9.1/gems/activesupport-3.2.1/lib/active_support/callbacks.rb:385:in_run_call_callbacks' vendor/bundle/ruby/1.9.1/gems/activesupport-3.2.1/lib/active_support/callbacks.rb:81:in run_callbacks' vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.1/lib/action_dispatch/middleware/callbacks.rb:27:incall' vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.1/lib/action_dispatch/middleware/reloader.rb:65:in call' vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.1/lib/action_dispatch/middleware/remote_ip.rb:31:incall' vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.1/lib/action_dispatch/middleware/debug_exceptions.rb:16:in call' vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.1/lib/action_dispatch/middleware/show_exceptions.rb:56:incall' vendor/bundle/ruby/1.9.1/gems/railties-3.2.1/lib/rails/rack/logger.rb:26:in call_app' vendor/bundle/ruby/1.9.1/gems/railties-3.2.1/lib/rails/rack/logger.rb:16:incall' config/initializers/quiet_assets.rb:6:in call_with_quiet_assets' vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.1/lib/action_dispatch/middleware/request_id.rb:22:incall' vendor/bundle/ruby/1.9.1/gems/rack-1.4.1/lib/rack/methodoverride.rb:21:in call' vendor/bundle/ruby/1.9.1/gems/rack-1.4.1/lib/rack/runtime.rb:17:incall' vendor/bundle/ruby/1.9.1/gems/activesupport-3.2.1/lib/active_support/cache/strategy/local_cache.rb:72:in call' vendor/bundle/ruby/1.9.1/gems/rack-1.4.1/lib/rack/lock.rb:15:incall' vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.1/lib/action_dispatch/middleware/static.rb:53:in call' vendor/bundle/ruby/1.9.1/gems/railties-3.2.1/lib/rails/engine.rb:479:incall' vendor/bundle/ruby/1.9.1/gems/railties-3.2.1/lib/rails/application.rb:220:in call' vendor/bundle/ruby/1.9.1/gems/rack-1.4.1/lib/rack/content_length.rb:14:incall' vendor/bundle/ruby/1.9.1/gems/railties-3.2.1/lib/rails/rack/log_tailer.rb:14:in call' vendor/bundle/ruby/1.9.1/gems/rack-1.4.1/lib/rack/handler/webrick.rb:59:inservice' /usr/lib/ruby/1.9.1/webrick/httpserver.rb:138:in service' /usr/lib/ruby/1.9.1/webrick/httpserver.rb:94:inrun' /usr/lib/ruby/1.9.1/webrick/server.rb:191:in `block in start_thread'

1
Can you post your stack trace?Leo Correa

1 Answers

1
votes

NumericalityValidator (the underlying validator for this helper) doesn't work with dynamic conditions as you want them. Use a custom validator:

validate :solids_validation

def solids_validation
  if self.lab_method_id
    lab_method = LabMethod.find(self.lab_method_id)
    if lab_method.solids?
      if (val = Kernel.Float(solids) rescue nil)
        min = (self.lab_method_id == 1 ? 0 : 5)
        errors.add(:solids, "must be greater than or equal to #{min}") if val < min
      else
        errors.add(:solids, :not_a_number)
      end
    end
  end
end