Abhishek kumar
Abhishek kumar

Reputation: 159

Datatype validation in rails ActiveModel::Validations

I wanted to validate class attributes with respect to their data type.

I am writing an API in ruby and i need to check if a particular parameter data is of type String, hash, Array etc.

eg. we have

class ApiValidation
  include ActiveModel::Validations
  attr_accessor :fieldName

  validates :fieldName, :presence => true 
end 

so similar to :presence => true, i want to add one more validation like :datatype => :string

Please suggest me some custom validation or any other approach to achieve my requirement.

Upvotes: 2

Views: 2698

Answers (4)

Sharmin
Sharmin

Reputation: 21

According to the Rails Guides and Rails API docs, we could use validates_each method which is available in ActiveModel::Validations.

For example:

class Person
  include ActiveModel::Validations

  attr_accessor :first_name, :last_name

  validates_each :first_name, :last_name do |record, attr, value|
    record.errors.add attr, " must be a string." unless value.is_a? String
  end
end

Upvotes: 1

fylooi
fylooi

Reputation: 3870

Parameters are always received as text. Ruby doesn't have static types, but it does have classes, so your code needs to parse each attribute and convert them into the class you expect.

This could be as simple as riding on Ruby's inbuilt conversion methods, eg. to_i, to_sym, to_d, to_h, or you might need to add more logic, eg. JSON.parse.

Do note the difference between strict and non-strict parsing which will require different control flow handling.

>> "1one".to_i
=> 1

>> Integer("1one")
ArgumentError: invalid value for Integer(): "1one"

Upvotes: 0

nuaky
nuaky

Reputation: 2086

You can check out dry-rb stack.

There is https://github.com/dry-rb/dry-types (https://dry-rb.org/gems/dry-types/1.2/) gem which do exactly what you want.

From docs:

Strict types will raise an error if passed an attribute of the wrong type:

class User < Dry::Struct
  attribute :name, Types::Strict::String
  attribute :age,  Types::Strict::Integer
end
User.new(name: 'Bob', age: '18')
# => Dry::Struct::Error: [User.new] "18" (String) has invalid type for :age

Upvotes: 2

Mark Merritt
Mark Merritt

Reputation: 2695

In Ruby, "datatypes" are actually just classes. So, all you really have to do is check which class fieldName belongs to (fieldName.class) in your custom validation.

Upvotes: 0

Related Questions