Enum validation in Rails 4.2 doesn't work - ruby-on-rails

My User model looks similar to this:
class User < ActiveRecord::Base
enum type: [:admin, :reviewer, :super_admin ]
validates :type, presence: true
validates :type, inclusion: { in: User.types.keys }
end
When I submit anything outside the enum values, the validation doesn't stop the code from running, and I get a 500 error as a response with the following error:
'something submitted' is not a valid type
If I submit a blank field, the validation works:
"type": [
"can't be blank",
"is not included in the list"
]
What am I doing wrong? My code looks identical to this answer

Rails enum doesn't have in-built validation.
The current focus of AR enums is to map a set of states (labels) to an
integer for performance reasons. Currently assigning a wrong state is
considered an application level error and not a user input error.
That's why you get an ArgumentError.
You still can set nil or an empty string to the enum attribute without raising an error.

Related

Is there something like .NET's data annotations in rails?

I was looking for something similar to .net's data annotations in rails, something like this.
What I want to achieve by this is: I have some fields (they could be nil also) for which I want to check the length and if the length exceeds I want to display an error message.
I want to club all the error messages related to, say all blog posts (which again have many separate fields) and then display them at once.
Rails uses ActiveRecord validations. In many cases the default validations are easy to set up. But if you want/or need customized validations that can all be done as well. Read the documentation here:
http://guides.rubyonrails.org/active_record_validations.html
In your case this type of validation is built in to rails so it's simple as adding 1 line to your model:
class MyModel
validates :my_field_name, length: { maximum: 3 }, allow_blank: true
end
This will validate the maximum length of your field. You can also customize the validation error message:
class MyModel
validates :name, presence: {message: "Title can't be blank." }, uniqueness: {message: "Title already exists."}, length: { maximum: 5, message: "Must be less than 5 characters"}
end

Rails validates acceptance not validating

I would like to simply validate a terms checkbox on my form. I have implemented the folowing:
http://guides.rubyonrails.org/active_record_validations.html#acceptance
class User < ActiveRecord::Base
validates :terms, acceptance: true
end
I have stripped the form back to the checkbox only for debugging purposes.
Regardless of the entry passed the :terms does not validate. The form parameters appear to being passed correctly.
Parameters: {"utf8"=>"✓", "authenticity_token"=>"+1dzwEMajQN4cL7KdGjlIw2kFSyVk/36eAhNhdydUXhLfzyT7LnCiUGdfzYt3hD/dD7evIVMiVWePv+7p+scyA==", "user"=>{"terms"=>"1"}, "commit"=>"Register"}
When I update the validation to the following I receive an error stating "Terms must be accepted" regardless of the terms value submitted. This leads me to believe the value from the form is not being passed to the validation.
validates :terms, acceptance: true, :allow_nil => false
OK...
The problem was that the validation helper validates the contents of the row within the table before saving. For this to trigger I needed to assign the ":terms" value to the model for validation.
I was only passing the params hash with the "terms" item within it expecting that to be validated.

Add validates_uniqueness_of error to another attribute

I have a validator in a class like the following
validates_uniqueness_of :email, {message: 'this is not a unique email :('}
What I would like is for this error to add a custom attribute to the errors object, like
{errors: {already_invited: true}}
How can I make this work?
You could do something like this
validates_uniqueness_of :email, {message: 'this is not a unique email :('}
validate :previous_invite
def previous_invite
#if already_invited is an attribute of the model then use
# errors.add(:already_invited, "true") otherwise add it to base
errors.add(:base, "already invited") if errors.added?(:email,'this is not a unique email :(')
end
You should not just add arbitrary keys to the errors but you can if you'd really like it is just considered poor form according to the docs:
attribute should be set to :base if the error is not directly associated with a single attribute.
Also messages will be treated as Strings not booleans. so it would not be already_invited: true but rather already_invited: "true"

Validate array name as not nil in Rails

I'm newbie and and wondering if its possible to validate the presence of an array name not nil. Actually on my model I have
validates :name, presence: true
this prevents that from a web form is not possible to send the name blank, but as as soon name[] is an string_array and nil is an string, when I try to send [nil,nil] from curl it succeeds.
I found this: rails validation of presence not failing on nil and this ActiveRecord validation for nil and read the api http://edgeguides.rubyonrails.org/active_record_validations.html but I didn't found the clue.
Does anyone can help?
Thanks in advance.
Edit: with validates :name, presence: true, allow_nil: false doens't work. If I send and invalid name it succeeds. Example:
curl -X POST -d 'patient[name[]]=["Mathew","de Dios]"&patient[email]=mat#gmail.com&patient[password]=123456&patient[password_confirmation]=123456&patient[sex]="female"&patient[doctor]=9' http://localhost:3000/api/patients.json
{**"success":true**,"data":{"active":null,"age":null,"created_at":"2013-08-15T11:19:03Z","dao":null,"day_active":null,"doctor_id":9,"email":"mat#gmail.com","geo_ini":null,"id":2124,"migraine_triggers":null,**"name":[null]**,"password_digest":"$2a$10$say8LiNmnazWL/EWKBKtL.fa5pJLKe4mo8Sn.HD6w2jeUrc5vmTe2","phone":null,"remember_token":"iX4Ohuj_Z6c2mDQZ_5e2vw","rich":null,"sex":"\"female\"","updated_at":"2013-08-15T11:19:03Z"},"status":"created"}
In the case that name is an array and that you want to check for nil elements, you can write a custom validation method. Here is an example :
validate :check_name_array_for_nil
def check_name_array_for_nil
self.name.split(",").each do |x|
if x.nil?
errors.add(:name, "nil in name array")
end
end
end
EDIT:
On second thought,this requires you to be storing the name as a string separated by commas.
I'm not sure but with a strict validation maybe?
In the rails guide
class Person < ActiveRecord::Base
validates :name, presence: { strict: true }
end
Person.new.valid? # => ActiveModel::StrictValidationFailed: Name can't be blank
More info about the strict validation.

Why my validation does not pass

I am developing Rails 3 app.
I would like to validate the "Cake" model's "size" attribute input field to only allow user to input +1,-1,+10,-10 and +25,-25, nothing else.
I use the following validation to validate "size":
class Cake < ActiveRecord::Base
validates_format_of :size, :with => /^[-+]?(1|10|25)$/, :message=>'size not allowed.'
...
end
(The "size" attribute in my database "cakes" table is a "double" type.)
In the UI, I always get fail message of the validation even I input 1 or 10 or 25 or +1 or whatever. Why my validation does not pass even the value is right?
I'm not sure if validating an Integer with a Regex works.
You could try validates_inclusion_of :size, :in=>[-1,+1,-10,+10,-25,+25], :message=>'size not allowed.'

Resources