Confusion between hashes and symbols - ruby-on-rails

May you help me understand the concept behind the hash and especially when we use symbols.
:name is a symbol right ?
we can use symbol as a key for our hashed right ?
:name and name: for example : those are two syntaxes but it describes a symbol right ?
when we have this for example :
Geocode.configure(
units: :km
)
here units does a reference to a specified argument called units in the configure function right ? and :km is the symbol we want to send through the variable unit or am I wrong ?
A last example :
validates :home_type, presence: true
Here we try to send to the validates function the symbol home_type right ?
and the second argument is named "presence" and we want to send the boolean true through this variable right ?
I am sorry if you don't understand my question, don't hesitate to ask me.
I got many headeck nderstanding those syntaxes.
Thanks a lot !

Geocode.configure(units: :km)
We are passing an hash to the configure method. This hash {units: :km}. Convenient syntax for {:units => :km}. So an hash with a key value pair with key symbol (:units) and value symbol (:km).
validates :home_type, presence: true
Here we are passing to the validates method a symbol :home_type and an hash, {presence: true}, or {:presence => true}. So the key is :presence symbol, the value is the boolean true.

It is very basic & nothing but simplified convention in ruby
validates :home_type, presence: true, if: :check_user
is similar to
validates :home_type, { :presence => true, :if => :check_user }
So when I write as,
link_to 'Edit', edit_path(user), class: 'user_one', id: "user_#{user.id}"
In above, link_to is ActionHelper method which is taking 3 arguments where last one is hash { class: 'user_one', id: "user_#{user.id}" }

Related

Rails: get values from length validator for a field in template

I havel a model with validators on some fields. Example:
class Notation < ActiveRecord::Base
validates :name, presence: true, uniqueness: true
validates_length_of :name, minimum: 5, maximum: 128
end
is there a way to get those values from minimum and maximum for the :name field in the template (because I want to show there the value of min and max length to the user, and want to do this dynamically, with the template reflecting the values from the model)?
In the rails console, I can do something like
Notation.validators_on(:name)
which outputs
#<ActiveRecord::Validations::PresenceValidator:0x00000005428420 #attributes=[:name], #options={}>, #<ActiveRecord::Validations::UniquenessValidator:0x0000000541b8d8 #attributes=[:name], #options={:case_sensitive=>true}, #klass=Notation (call 'Notation.connection' to establish a connection)>, #<ActiveModel::Validations::LengthValidator:0x0000000540baf0 #attributes=[:name], #options={:minimum=>5, :maximum=>128}>
If I get using the array's index
Notation.validators_on(:name)[2]
I have:
#<ActiveModel::Validations::LengthValidator:0x0000000540baf0 #attributes=[:name], #options={:minimum=>5, :maximum=>128}>
but I was wondering if there is another way, maybe passing the type of validation I'm 'queryng', because I can't rely on the order of the array.
To get the validator, you can filter:
options = Notation.validators_on(:name)
.select { |v| v.is_a? LengthValidator }
.first.options
Then you can get options[:maximum] etc.
In case there is no such validator, you might have to rescue from the code, as otherwise the first will fail.

Validate number with rails 3

How can I validate if the input in a text field is a number? not_integer is not what I am looking for. It can be a decimal number.
You can check for numericality
validates :points, numericality: true
If you want a more general approach, you can use is_a?. The parent number class in Ruby is Numeric.
a = 4
a.is_a? Numeric
=> true
b = 5.4
b.is_a? Numeric?
=> true
c = "apple"
c.is_a? Numeric
=> false
d = "4"
d.is_a? Numeric
=> false
To restrict the user from entering non-numeric values at the form-level and avoid expensive server call just to check numericality.
Use this in the form:
<%= f.number_field :attribute_name, :step => 'any' %>
This will create an html element as below:
<input id="post_attribute_name" name="post[attribute_name]" step="any" type="number">
Upon form submission, the input value is checked at the form level. step = "any" will allow decimals.
I would also recommend adding validation at the Model level using,
validates :attribute_name, numericality: true ## As suggested by Justin Wood
This way you have double protection, i.e., one at the form-level itself and the other at Model level.

Ruby ActiveRecord: validate format of an integer field

I'm trying to validate the format of a field in an ActiveRecord. I want this field to either be empty, or contain a sequence of digits only (it is containing an optional port number for a database connection). I'm currently trying this:
validates_format_of :port, with: /\A[0-9]*\Z/, message: 'Only numbers allowed'
but without luck. I've found that adding a required number by using for example {1, 6} sort of works, but makes the field mandatory.
Any advice?
Many thanks in advance,
Joseph.
If you're looking to validate so that only numbers are allowed, then you should be able to use this:
validates :port, :numericality => {:only_integer => true}
You may want to try to validate the numericality of the field, like so:
validates_numericality_of :port, :only_integer => true
:only_integer will ensure that the value entered for :port is an integer.
You can also just add allow_blank: true
You can use this syntax as well
validates numericality: :only_integer

Rails : Validates_format_of for float not working

I am new at Ruby on Rails.
I was trying to validate format of one of the attribute to enter only float.
validates :price, :format => { :with => /^[0-9]{1,5}((\.[0-9]{1,5})?)$/, :message => "should be float" }
but when I enter only character in price, it accepts it and show 0.0 value for price.
can anybody tell, what is wrong in this or why this happens?
This is my solution,
validates :price,presence:true, numericality: {only_float: true}
when you fill in for example 7 it automatically transfer the value to 7.0
For rails 3:
validates :price, :format => { :with => /^\d+??(?:\.\d{0,2})?$/ },
:numericality =>{:greater_than => 0}
A float is a number and regular expressions are for strings.
It appears that when you enter a string for the float, it gets converted as 0.0 automatically by Rails.
Do you have a default (0.0) on the column? If yes, then you may try removing it and use validates_presence_of :price only.
Something to try: instead of putting the string directly into the price column, put it into a price_string attr and use a before_save callback to try to convert the string to price. Something like that:
attr_accessor :price_string
before_save :convert_price_string
protected
def convert_price_string
if price_string
begin
self.price = Kernel.Float(price_string)
rescue ArgumentError, TypeError
errors.add(ActiveRecord::Errors.default_error_messages[:not_a_number])
end
end
And in your form, change the name of the text_field to :price_string.

Rails: how do I validate that something is a boolean?

Does rails have a validator like validates_numericality_of for boolean or do I need to roll my own?
Since Rails 3, you can do:
validates :field, inclusion: { in: [ true, false ] }
I believe for a boolean field you will need to do something like:
validates_inclusion_of :field_name, :in => [true, false]
From an older version of the API: "This is due to the way Object#blank? handles boolean values. false.blank? # => true"
I'm not sure if this will still be fine for Rails 3 though, hope that helped!
When I apply this, I get:
Warning from shoulda-matchers:
You are using validate_inclusion_of to assert that a boolean column
allows boolean values and disallows non-boolean ones. Be aware that it
is not possible to fully test this, as boolean columns will
automatically convert non-boolean values to boolean ones. Hence, you
should consider removing this test.
You can use the shorter version:
validates :field, inclusion: [true, false]
Extra thought. When dealing with enums, I like to use a constant too:
KINDS = %w(opening appointment).freeze
enum kind: KINDS
validates :kind, inclusion: KINDS
Answer according to Rails Docs 5.2.3
This helper (presence) validates that the specified attributes are not empty. It uses the blank? method to check if the value is either nil or a blank string, that is, a string that is either empty or consists of whitespace.
Since false.blank? is true, if you want to validate the presence of a boolean field you should use one of the following validations:
validates :boolean_field_name, inclusion: { in: [true, false] }

Resources