I have the (simplified) model structure below:
class Customer < ApplicationRecord
validates :full_name, format: { without: /[^a-zA-Z .,']+/, message: "cannot contain " + /[^a-zA-Z .,']+/.match(self.full_name).to_s}
end
I want to validate the user-provided full_name with a regular-expression and if the validation fails, I want to show which part of the full_name fails the regular-expression validation.
However, this returns "undefined method full_name" and I tried a bunch of other things for self.full_name but can't seem to figure out how to pass that data there.
How can I do this? Thanks for any feedback and answer, in advance.
According to the docs, Rails allows to pass a Proc message. Thus, in your case it's possible to customise the message:
class Customer < ApplicationRecord
validates :full_name,
format: {
without: /[^a-zA-Z .,']+/,
message: ->(object, data) do
"cannot contain " + /[^a-zA-Z .,']+/.match(object.full_name).to_s
end
}
end
Related
I have the following validation:
class Event < ActiveRecord::Base
attr_accessible :starts, :ends
validates :no_multi_day_events
private
def no_multi_day_events
if (ends.day != starts.day)
errors.add(:ends, "No multi-day events")
end
end
end
However, when I try to load a page with this text, I get an error: You need to supply at least one validation
How do I supply the validation?
You should be calling:
validate :no_multi_day_events
and not
validates :no_multi_day_events
On any given model:
class MyTestModel
include Mongoid::Document
include Mongoid::Timestamps
field :my_field
validates : my_field, inclusion: { in: proc { |my_instance| [ my_instance.some_stuf ] } }
def some_stuff
'some generated value'
end
end
So this works and validates properly, if my_field does not contain 'some generated value'
But the error validation is not really explicit and I have the feeling that I am using inclusion for no good reason here. What I would like to write for the validation is:
validates : my_field, acceptance: { accept: proc { |my_instance| my_instance.some_stuf } }
But this will never pass validation ? and I haven't found a way to see what the validation is expecting as a value to check what is wrong. Any idea why one is working and not the other ? Is that a mongoid bug ?
why not write a custom validator method. Then it's clear what you're doing - rather than having multiple layers of obscuring procs.
validate :my_field_in_some_stuff
def my_field_in_some_stuff
errors.add(:my_field, "my field must... but it wasn't") unless ['some generated value'].include?(self.my_field)
end
or if the some_stuff method is used elsewhere
validate :my_field_in_some_stuff
def my_field_in_some_stuff
errors.add(:my_field, "my field must... but it wasn't") unless some_stuff.include?(self.my_field)
end
def some_stuff
'some generated value'
end
In order to access the same array in different parts of my app, I stored the array in the corresponding Model, using class method to retrieve the array.
In the code bellow, codes are used in views (to generate the select drop down) and in the same model (to validate passed value).
class Request < ActiveRecord::Base
validates :code, presence: true, inclusion: { in: self.codes }
def self.codes
return ["OBJ", "SER", "REC"]
end
end
But using this, generates the following error:
undefined method `codes' for #<Class:0x000001074ddc50>
Even removing the self. in the inclusion, doesn't solve the problem (undefined local variable).
Do you have an idea?
Your codes method is declared after you've used it in your validation - when the validation line is executed the method has not yet been defined, hence the error.
If you place the validation after the codes method it should work.
You can define it as a constant at a top of your model
class Request < ActiveRecord::Base
CODES = ["OBJ", "SER", "REC"]
Than you can access it like this Request::CODES
validations will look like this
validates :code, presence: true, inclusion: { in: CODES }
I am trying to add a validation to exclude a list of reserved usernames:
validates :rss_mailbox, exclusion: { in: %w(admin support info), message: " %{value} is not available" }
But the list is extremely long. Is there a way to call a method for the in: property instead of hardcoding a huge list?
This is what the docs for validates_exclusion_of says about :in:
:in - An enumerable object of items that the value shouldn't be part of. This can be supplied as a proc, lambda or symbol which returns an enumerable. If the enumerable is a range the test is performed with
This makes it quit flexible, I think you can also use a class constant:
RESERVED = %w(admin support info etc)
validates :rss_mailbox, exclusion: { in: RESERVED, message: " %{value} is not available" }
Not tested, but I think you can use a method by referring to it with a symbol:
validates :rss_mailbox, exclusion: { in: :reserved_names, message: " %{value} is not available" }
def reserved_names
# Lookup and return all reserved names, can be array or db-call
end
You can polish this implementation using a separate custom validator class as show in this guide.
class MyModel < ActiveRecord::Base
validates_with CustomValidator
end
class CustomValidator < ActiveModel::Validator
def validate(record)
if invalid_condition_implementation(record)
record.errors[:rss_mailbox] << "My custom error message"
end
end
end
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.