Question

I have a simple table for storing users accounts information (emails and passwords) with two additional columns:

  1. is_active - says if user account is enable or disabled - the column type is boolean and in the context of DB2 it is mapped with decimal(1)
  2. registration_date - says when the user was created - the column type is datetime and in the context ofDB2 it is mapped with datetime

As this fields will not be set by the user, I have deleted their inputs from the users _form.

I want to populated this fields in my users controller as follows:

def create

   @security_user = SecurityUser.new(params[:security_user])

   @security_user.is_active = 0
   @security_user.registration_date = DateTime.now

  ...

end

But I can not pass the validations that I have in the model. They looks like:

class SecurityUser < ActiveRecord::Base

  # Loading custom validators
  require 'lib/date_format_validator'
  ...

  # Accessible columns
  ...

  # Relationships
  ...

  # Validations
  validates :is_active, inclusion: { in: 0..1, message: "only '0' and '1' allowed"}, presence: true
  validates :registration_date, date_format:true , presence: true

end

where the 'lib/date_format_validator' looks like follows:

class DateFormatValidator < ActiveModel::EachValidator

  def validate_each(object, attribute, value)
    if (DateTime.parse(value) rescue ArgumentError) == ArgumentError
      object.errors[attribute] << (options[:message] || "is not valid datetime")
    end
  end

end

What I am doing wrong?

EDIT: The screenshot below displays the errors:

enter image description here

EDIT2: Sam Ruby's answer helps me to finish with something like this for my custom validator method:

class DateFormatValidator < ActiveModel::EachValidator

  def validate_each(object, attribute, value)
    unless value.kind_of? DateTime || (DateTime.parse(value) rescue ArgumentError) != ArgumentError
      object.errors[attribute] << (options[:message] || "is not valid datetime")
    end
  end

end

and to transform the validates method for the is_active column as follows:

validates :is_active, inclusion: { in: [ true, false ], message: "only 'true' and 'false' allowed"}

because as it is said in the official documentation:

Since false.blank? is true, if you want to validate the presence of a boolean field you should use validates :field_name, :inclusion => { :in => [true, false] }.
Was it helpful?

Solution

The problem is that you are trying to validate the ActiveRecord object as if the columns are of type String. But since you have defined your columns as boolean and datetime, what you will be validating will be of type TrueClass, FalseClass or ActiveSupport::TimeWithZone.

In other words, the values are already parsed.

true is never 0 or 1.

DateTime.parse(DateTime.now) will always raise ArgumentError

If you want to validate the unparsed values, do so in the controller.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top