I try to add a validation from a blog category only limited at 1 word.
But I try this length: { maximum: 1 }
I doesn't work. Is there a validation to validaes only one word and not uniqueness?
Thank you for your answers
You can make a custom validation:
validates :category, uniqueness: true
validate :category_in_1_word
private
def category_in_1_word
if category.to_s.squish.split.size != 1
errors.add(:category, 'must be 1 word')
end
end
you can try:
validates :category, :format => { :with => /^[A-Za-z]+$/, :message => "Must be single word" }
No Rails doesn't have the validation you need, but you can easily create a custom one:
Try something like this:
class Post < ActiveRecord::Base
validate do
if ... # any custom logic goes here
errors.add :title, "is wrong"
end
end
end
Related
I have field date in the User model. It shuld have only future dates (from registration moment). What is the best way to validation it in the model?
I think about something like this:
class User < ActiveRecord::Base
validates :name, presence: true
validates :date, presence: true
validate :future_event
private
def future_event
errors.add(:date, "Can't be in the past!") if date < Time.now
end
end
Is it OK?
Can you think about some more simple and elegant solution?
# lib/future_validator.rb
class FutureValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
if record[attribute] < Time.now
record.errors[attribute] << (options[:message] || "can't be in the past!")
end
end
end
class User < ActiveRecord::Base
validates :name, presence: true
validates :date, presence: true
validates :future_event, future: true
end
http://guides.rubyonrails.org/active_record_validations.html#custom-validators
Take a look at the Date Validator Gem
validates :start_date,
date: { after: Proc.new { Date.current }, message: 'must be after today' },
on: :create
You might always want to investigate the differences between Date.current and Date.today - Date.current is timezone aware and will use the Timezone of your Rails app. Date.today uses system time. There can be odd differences if one is UTC and one is Eastern.
Use inclusion.
Something like this:
validates :date, inclusion: { in: Proc.new{ 1.day.from_now.. }, message: "has to be in the future" }
I have the following validation:
class User < ActiveRecord::Base
...
validates :email, uniqueness: { message: "Email already associated with an account" }
...
end
My class User as a boolean attribute called active, and I would like to incorporate it into the validation logic using conditional. What is the best way to throw a custom validation error message if the conditional user.active? == false?
I would try adding the following two validations:
validates :email, uniqueness: { message: "message 1", if: 'active?' }
validates :email, uniqueness: { message: "message 2", if: '!active?' }
Validations can be represented as instance methods. For example, I have a Student model with first_name and last_name attributes. I want to introduce a validation, which will throw custom errors when either one, or both of the names are empty. I can do this by:
calling the custom method in validate:
class Student < ActiveRecord::Base
...
validate :full_name_validation, on: :create
...
end
and adding my full_name_validation method:
def full_name_validation
if first_name.blank? && last_name.blank?
errors.add(:full_name, 'Full name is required')
elsif first_name.blank?
errors.add(:full_name, 'First name is required')
else
errors.add(:full_name, 'Last name is required')
end
end
I use minitest on Ruby on Rails. Below is my model.
require 'mongoid'
class Person
include Mongoid::Document
index({ pin: 1 }, { unique: true, name: "pin_index" })
field :first_name
field :last_name
field :pin
validates :pin, presence: true, uniqueness: true
validates :first_name, presence: true
validates :last_name, presence: true
end
I try to write model test.I want to write a test that controls whether pin field is unique or not. How can i do this? Any idea?
I try to write a test like below:
it 'must not be valid' do
person_copy = person.dup
person.save
person_copy.save
end
You can write the test like this:
it 'must have unique pin' do
person_copy = person.dup
proc { person_copy.save! }.must_raise(Mongoid::Errors::Validations)
person_copy.errors.must_include(:pin)
end
You can use assert_includes and assert_same to test the error is the right one (about uniqueness):
it 'must not be valid' do
person_copy = person.dup
person.save
person_copy.save
assert_includes person.errors, :pin
assert_same person.errors[:pin], "pin is not unique (replace with actual error message)"
end
Considering you have a fixture already set, you can just do this:
test 'pin must be unique' do
new_person = Person.new(#person.attributes)
refute new_person.valid?
end
I have a User model
is there a difference between
class User < ActiveRecord::Base
validates :name, :presence => true
end
and
class User < ActiveRecord::Base
def validate
errors.add_to_base "name should not be nil" if name.nil?
end
end
The validates macro is more flexible, as it also allows you to do things like:
validates :name, :format => { :with => /\A[a-zA-Z]+\z/,
:message => "Only letters allowed" }, :length => { :in => 6..20 }
The validate method is really a quick and easy way to do custom validations when existing ones do not exist. (When custom validations get too complex, then you should usually move them into custom validators and use the validates macro).
See more at http://guides.rubyonrails.org/active_record_validations_callbacks.html
Yes -- the first will fail to save an empty string, whereas the second will allow it.
So I was wondering if we can have a conditional allow_nil option for a validation on a rails model.
What I would like to do is to be able to allow_nil depending upon some logic(some other attribute)
So I have a product model which can be saved as draft. and when being saved as draft the price can be nil, but when not a draft save the price should be numerical. how can I achieve this. The following doesn't seem to work. It works for draft case but allows nil even when status isn't draft.
class Product<ActiveRecord::Base
attr_accessible :status, price
validates_numericality_of :price, allow_nil: :draft?
def draft?
self.status == "draft"
end
end
Looking at rails docs I looks like there isn't an option to pass a method to allow_nil?
One possible solution is to do separate validations for both cases
with_options :unless => :draft? do |normal|
normal.validates_numericality_of :price
end
with_options :if => :draft? do |draft|
draft.validates_numericality_of :price, allow_nil: true
end
Any other ways to get this working ?
Thanks
You can use if and unless to do the following
class Product<ActiveRecord::Base
attr_accessible :status, price
validates_numericality_of :price, allow_nil: true, if: :draft?
validates_numericality_of :price, allow_nil: false, unless: :draft?
def draft?
self.status == "draft"
end
end
With the above, you will have 2 validations set up, one that applies when draft? == true, which will allow nils, and one where draft? == false which will not allow nils
You don't need allow_nil then, just use if:
class Product < ActiveRecord::Base
attr_accessible :status, price
validates_numericality_of :price, if: -> { (draft? && !price.nil?) || !draft? }
def draft?
self.status == "draft"
end
end