Has "def validate" been taken out in Rails 3.1? - ruby-on-rails

Has "def validate" been taken out in Rails 3.1? I'm on Rails 3.1 pre and it doesn't seem to be working
class Category < ActiveRecord::Base
validates_presence_of :title
private
def validate
errors.add(:description, "is too short") if (description.size < 200)
end
end
The "title" validation works but the "description" validation doesn't.

Does something like this work for you?
class Category < ActiveRecord::Base
validates_presence_of :title
validate :description_length
def description_length
errors.add(:description, "is too short") if (description.size < 200)
end
end

class Category < ActiveRecord::Base
validates_presence_of :title
private
validate do
errors.add(:description, "is too short") if (description.size < 200)
end
end

For other types of validations, you can also add 'Validators' like the one listed here:
http://edgeguides.rubyonrails.org/3_0_release_notes.html#validations
class TitleValidator < ActiveModel::EachValidator
Titles = ['Mr.', 'Mrs.', 'Dr.']
def validate_each(record, attribute, value)
unless Titles.include?(value)
record.errors[attribute] << 'must be a valid title'
end
end
end
class Person
include ActiveModel::Validations
attr_accessor :title
validates :title, :presence => true, :title => true
end
# Or for Active Record
class Person < ActiveRecord::Base
validates :title, :presence => true, :title => true
end

Related

Using Roles for Validations in Rails

Is it possible to use the roles used for attr_accessible and attr_protected? I'm trying to setup a validation that only executes when not an admin (like this sort of http://launchware.com/articles/whats-new-in-edge-scoped-mass-assignment-in-rails-3-1). For example:
class User < ActiveRecord::Base
def validate(record)
unless # role.admin?
record.errors[:name] << 'Wrong length' if ...
end
end
end
user = User.create({ ... }, role: "admin")
After looking into this and digging through the source code, it appears that the role passed in when creating an Active Record object is exposed through a protected method mass_assignment_role. Thus, the code in question can be re-written as:
class User < ActiveRecord::Base
def validate(record)
unless mass_assignment_role.eql? :admin
record.errors[:name] << 'Wrong length' if ...
end
end
end
user = User.create({ ... }, role: "admin")
Sure can would be something like this:
class User < ActiveRecord::Base
attr_accessible :role
validates :record_validation
def record_validation
unless self.role == "admin"
errors.add(:name, "error message") if ..
end
end
You could do this
class User < ActiveRecord::Base
with_options :if => :is_admin? do |admin|
admin.validates :password, :length => { :minimum => 10 } #sample validations
admin.validates :email, :presence => true #sample validations
end
end
5.4 Grouping conditional validations

Model creation depends on other model creation

I have an Item model:
class Item < ActiveRecord::Base
attr_accessible :author, :title
end
And a Book model:
class Book < ActiveRecord::Base
attr_accessible :item_id, :plot
belongs_to_ :item
end
I want to be able to create a book by using
Book.new(:title=>"Title", :author=>"Author", :plot=>"BlaBla")
Book.save
And it will create an Item with the title and author, and also create a Book with the created Item ID.
How is it possible?
You need to use :after_create callback and virtual_attributes as follows.
In you book model write this
attr_accessor :title, :author
attribute_accessible :title, :author, :plot
after_create :create_item
def create_item
item = self.build_item(:title => self.title, :author => self.author)
item.save
end
Using before_save or before_create
class Book
attr_accessor :title, :author
before_save :create_item
#before_create :create_item
def create_item
if self.title.present? && self.autor.present?
item = Item.new(:title => self.title, :author => self.author)
item.save(:validate => false)
self.item = item # or self.item_id = item.id
end
end
end

Rails 3: Uniqueness validation for nested fields_for - Part2

I am new to coding - and have not enough reputation to comment this answer:
Rails 3: Uniqueness validation for nested fields_for
So I am creating this question as "Part 2" :)
I am a web designer but curious to learn coding, held with this from my days.
# app/validators/nested_attributes_uniqueness_validator.rb
class NestedAttributesUniquenessValidator < ActiveModel::EachValidator
record.errors[attribute] << "Products names must be unique" unless value.map(&:name).uniq.size == value.size
end
end
above code with "ActiveModel::EachValidator" throw this error:
"undefined method `map' for "Area 1":String"
# app/validators/nested_attributes_uniqueness_validator.rb
class NestedAttributesUniquenessValidator < ActiveModel::Validator
record.errors[attribute] << "Products names must be unique" unless value.map(&:name).uniq.size == value.size
end
end
above code with "ActiveModel::Validator" throw this error:
"Subclasses must implement a validate(record) method. "
this is model file:
class Area < ActiveRecord::Base
validates :name,
:presence => true,
:uniqueness => {:scope => :city_id},
:nested_attributes_uniqueness => {:field => :name}
belongs_to :city
end
You can find complete code over here:
https://github.com/syed-haroon/rose
#Syed: I think you are trying to do this. else reply to my comment.
# app/models/city.rb
class City < ActiveRecord::Base
has_many :areas
validates :areas, :area_name_uniqueness => true
end
# app/models/area.rb
class Area < ActiveRecord::Base
validates_presence_of :name
validates_uniqueness_of :name
end
# config/initializers/area_name_uniqueness_validator.rb
class AreaNameUniquenessValidator < ActiveModel::Validator
def validate_each(record, attribute, value)
record.errors[attribute] << "Area names must be unique" unless value.map(&:name).uniq.size == value.size
end
end
I found the answer over here :
https://rails.lighthouseapp.com/projects/8994/tickets/2160-nested_attributes-validates_uniqueness_of-fails
&
validates_uniqueness_of in destroyed nested model rails
This is for rails 2, one line need to me modified over here:
add_to_base has been deprecated and is unavailable in 3.1. Use self.errors.add(:base, message)

Custom validation, on two lines?

Is there a way to validate an input field using just a few lines of code?
Right not I've to do this when using a custom validation.
Model
class Search < ActiveRecord::Base
validates :email, :presence => true, :email => true
end
Validator
class EmailValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
record.errors[attribute] << (options[:message] || "is not an email") unless
value =~ /\A([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
end
end
end
This is what I really want to do.
class Search < ActiveRecord::Base
validates :email, :email => lambda do |record, value|
record.errors[:email] << "invalid field" unless value =~ /\A([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
end
end
Is that possible?
Take a look at ActiveModel's validates_format_of http://api.rubyonrails.org/classes/ActiveModel/Validations/HelperMethods.html#method-i-validates_format_of
class Person < ActiveRecord::Base
validates_format_of :email, :with => /\A([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, :on => :create
end
Or use the shortcut:
class Person < ActiveRecord::Base
validates :email, :format => { :with => /\A([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, :on => :create }
end
Here is my solution.
class Search < ActiveRecord::Base
validate :my_custom_validator
def my_custom_validator
if #email.to_s.match(/hello/)
self.errors[:email] << "Email can't contain the word 'hello'"
end
end
end

Mongoid reference uniqueness

I'm having this model:
class Vote
include Mongoid::Document
include Mongoid::Timestamps
field :vote, :type=>Integer
embedded_in :voteable, :inverse_of => :votes
referenced_in :user
attr_accessible :vote, :user, :voteable
validates :vote,:inclusion => [-1, 1]
validates :user ,:presence=> true,:uniqueness=>true
end
The problem is that the validation for user uniqueness per vote is not working, and the same user can create several votes, which is not what I want. Any ideas how to solve that?
Looks like this is a known problem.
http://groups.google.com/group/mongoid/browse_thread/thread/e319b50d87327292/14ab7fe39337418a?lnk=gst&q=validates#14ab7fe39337418a
https://github.com/mongoid/mongoid/issuesearch?state=open&q=validates#issue/373
It is possible to write a custom validation to enforce uniqueness. Here is a quick test:
class UserUniquenessValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
record.errors[attribute] << "value #{value} is not unique" unless is_unique_within_votes(record, attribute, value)
end
def is_unique_within_votes(vote, attribute, value)
vote.voteable.votes.each do |sibling|
return false if sibling != vote && vote.user == sibling.user
end
true
end
end
class Vote
...
validates :user ,:presence => true, :user_uniqueness => true
end

Resources