In a Ruby on Rails tutorial, I am asked to type:
class Post < ActiveRecord::Base
validates :name, :presence => true
validates :title, :presence => true, :length => { :minimum => 5 }
end
I understand what this does, but I would like to know what the => operator is. In PHP-land, it links a key and a value in an associative array. Is it the same thing here? Is it a Ruby operator or a Rails operator?
It is mainly a ruby operator that sets the value of a key inside a hash. Thus :
{ :minimum => 5 }
Is a ruby hash that has the symbol :minimum as a key that maps to the value of 5. A hash with one entry, in this example. Same for :
:presence => true
Still a hash. However, in ruby, when you have a method, you can omit the {} that surround a hash. That is what happens with the validates method. It's a method and thus the passed hash does not explicitly need {}.
Related
My Requirement :
To Add validation to make sure that SITEMAP_URL keyword is always included in search_engines.url and it should be of format http://www.example.com/
class SearchEngine < ActiveRecord::Base
validates :name, :ping_url, :uniqueness => true, :presence => true
validates :ping_url, :format => {:with => /\=SITEMAP_URL$/}, :presence => true
end
Is the validation i have written is correct .
The validation looks fine.
Except if you expect /\=SITEMAP_URL$/ to interpolate it won't.
It will only match strings like;
"http://some.com?q=SITEMAP_URL"
Is that really what you mean?
If you have
SITEMAP_URL = "/sitemap.xml"
Then you can say
SITEMAP_REGEXP = /\=#{SITEMAP_URL}/
But this will interpret the "." as any character.
So you need to use Regexp.escape
Pretty much
Regexp.new(Regexp.escape("=#{SITEMAP_URL}")+"$")
Should do what you want.
I trying to spec validations of my model this is my model
class Account < CouchRest::Model::Base
property :user, String
property :password, String
property :name, String
property :email, String
property :activate, TrueClass, :default => true
validates_presence_of :user, :password, :name, :email
validates_length_of :password, :in => 6..15, :if => lambda{|account| !account.password.blank? }
validates_uniqueness_of :user, :if => (lambda{|account| !account.user.blank?})
end
and into my model_spec i'm trying to do this
account = Account.new
account.should have(1).error_on_presence_of(:email)
But instead 1 error, I'm getting 6
I think that might be caused by validates of couchrest but not sure.
Can someone clarify this for me please?
P.S.: If I validate the same model into console I get 4 errors corresponding the four empty properties
It seems you're expecting 1 error, but there are actually 6. To figure out what is in the error hash, you can set a temporary expectation:
`account.errors.should == {}
Then the example will fail and RSpec will print the value of the error hash, and you can see which errors are actually being generated.
Airports have four-letter ICAO codes. By convention, these are always uppercase. I'm creating a form for receiving user input, but this form needs to be able to accept user input in mixed case, and prevent them from creating dupes.
The default :uniqueness is case-sensitive, of course. I figured out how to transform the user's input to uppercase before it gets saved, but the problem is that this appears to be post-validation, instead of pre-validation.
For example, if there is already an Airport with ICAO of KLAX, a user can enter klax, it will get validated as unique, and then transformed to uppercase and stored, resulting in duplicates.
Here's my model code at present.
class Airport < ActiveRecord::Base
validates :icao, :name, :lat, :lon, :presence => true
validates :icao, :uniqueness => true
before_save :uppercase_icao
def uppercase_icao
icao.upcase!
end
end
Or a slightly different take: Write a setter for icao that converts anything thrown at it to uppercase:
def icao=(val)
self[:icao] = val.upcase
end
And then you can use regular uniqueness validation (back it up with a unique index in your DB). Might even make things a little easier for the DB during finds, 'cause it doesn't have to worry about case-insensitive comparisons any more.
Hope this helps!
try this:
validates :icao, :uniqueness => { :case_sensitive => false }
Updated answer for Rails 4.
class Airport < ActiveRecord::Base
validates :icao, :name, :lat, :lon, :presence => true
validates :icao, :uniqueness => { case_sensitive: false }
def icao=(val)
write_attribute :icao, val.upcase
end
end
Simply fixed (as many problems with Rails are) - as Danny pointed out above, although not in his own answer so I can't accept it :), changing before_save to before_validation fixes it perfectly.
I have the following validation of product's price:
class Product < ActiveRecord::Base
...
PRICE_REGEX = /^([1-9]\d{0,5}|0)(\.\d{1,2})?$/
validates :price, :presence => true, :format => PRICE_REGEX
...
end
It supposed to allow prices from 0 to 999999.99.
However, if I enter hello, the validation passes, and 0.00 is saved in the database.
The :presence validation works fine, though.
What am I missing here ?
The price column is a float, and so Rails will automatically convert the string "hello" to float, as per "hello".to_f # => 0.0. This is then converted back to the string "0.0", which obviously matches the regular expression.
In general, it's a bad idea to use regular expressions on non-string columns. Instead, use validates_numericality_of. If you wanted the same restriction as with the regex, do it like this:
class Product < ActiveRecord::Base
validates_numericality_of :price, :greater_than => 0, :less_than => 1000000
end
Not only is it safer, but it's easier to read and follow as well. Note that it'll automatically reject the price if blank as well.
I haven't tested this, but every description I saw from validates uses :format in this way:
validates :price, :presence => true, :format => { :with => PRICE_REGEX }
Maybe the problem is there
How would I validate a field only if another has been filled out In Ruby on Rails 2.3.5?
class Model < ActiveRecord::Base
validates_presence_of :address, :if => :city?
end
:address and :city are both attributes of Model.
validates_presence_of accepts an if attribute that take one of three things, according to the documentation: a string, a method, or a proc.
if - Specifies a method, proc or string to call to determine if the validation
should occur (e.g. :if => :allow_validation, or
:if => Proc.new { |user| user.signup_step > 2 }).
The method, proc or string should return or evaluate to a true or false value.
I ended up needing to use a proc, as I wanted to make sure that a certain parameter was filled out before validating:
validates_presence_of :bar, :if => Proc.new { |foo| !foo.age.blank? }