I use in my model following regular expression for getting a number that must to have a length 8. I do it this way:
validates_uniqueness_of :my_number, :with => /^[0-9]{8}$/, :message => "error message"
But this doesn't works me, if I set into the input "hahaha", I will get the "error message", if I set there 123, so I will get a success output, but that's wrong... I try to get a regular expression that will accepted always exact 8 digits...
Probably:
validates_format_of :my_number, :with => /\A[0-9]{8}\Z/
validates_uniqueness_of :my_number
Update: As #tadman points out in the comment, in Rails 3 you can combine validators:
validates :my_number, :uniqueness => true, :format => { :with => /^[0-9]{8}$/ }
Using old-style validation:
validates_uniqueness_of does not accept a with option, just validates_format_of does. So you might try:
validates_format_of :my_number, :with => /^[0-9]{8}$/, \
:message => "8 digits, please."
To validate uniqueness you might want to add another constraint.
Related
What does the {TOKEN} and {ACCOUNT_ID} mean in the following Ruby?
my_function({
:amount => 2000,
:currency => "usd",
:source => {TOKEN},
:destination => {ACCOUNT_ID}
})
I have Ruby 2.3.1 and am getting an error syntax error, unexpected '}', expecting => (SyntaxError)
A hash needs to be defined as either empty or with key, value pairs (see here). I'm guessing if you are following some sort of a tutorial, you need to fill those values in with some constants.
Usually variables in CAPS are constants, but it is possible to define a method in caps. Even so, one would need to call it explicitly with braces, as in TOKEN() and I can't think of anything that could be put inside curly braces to initialize a hash of some sort.
You probably need to end up with a structure like this:
my_function({
:amount => 2000,
:currency => "usd",
:source => "THE TOKEN",
:destination => "THE ACCOUNT ID"
})
or
my_function({
:amount => 2000,
:currency => "usd",
:source => "ckjnsdncc98n9dnx93d372n",
:destination => 123456
})
The {X} syntax looks like it's used as a placeholder for either Strings or numbers (most likely Strings)
I'm rather new to Rails and simply love it's expressive modeling architecture. I'm currently building a routing system with a one to many link between two tables.
Consider the following schema:
class CreateTrips < ActiveRecord::Migration
def self.up
create_table :trips do |t|
t.string :name
end
end
...
end
class CreatePitStop < ActiveRecord::Migration
def self.up
create_table :pit_stops do |t|
t.references :trip
t.integer :stop_number
t.string :location
end
end
...
end
Now consider the following data for a single trip:
t = Trips.create!({ :name => "Christmas Visits Route" })
t.pit_stops.create!({ :stop_number => 1, :location => "Home" })
t.pit_stops.create!({ :stop_number => 2, :location => "Mom and Dads" })
t.pit_stops.create!({ :stop_number => 3, :location => "In-Laws" })
t.pit_stops.create!({ :stop_number => 4, :location => "Grandma's" })
t.pit_stops.create!({ :stop_number => 5, :location => "Time Square" })
What I'd like to do is show a list of all trip Name along with the Location of first and last PitStop in a single "trip" row for the 'trips/index' view. I don't care about the pit stops in between, I just want to know where I started and where I ended:
--------
My Trips
--------
--------------------------------------------------------
| Route Name | From | To |
--------------------------------------------------------
| Christmas Visits Route | Home | Time Square |
--------------------------------------------------------
I'd like to eliminate all the "in-between" PitStops from the query, as there will be quite a few for each Trip.
Question: What is the best way to pull this data from the db using ActiveRecord?
Solution: Jan. 3rd, 2012
I solved my problem by applying my PitStop logic to the Trip model. My From and To PitStops now have hard coded stop_number values. After working through it, I found that the solution actually makes sense for the real world as well (double win).
The From PitStop record will always have a stop_number value of 0.
The To PitStop record will always have a stop_number value of 99.
This makes sense because the first PitStop isn't really a "pit stop" at all, it's where you start from (ie. 0). The last PitStop isn't really a "pit stop" either, it's your end location (ie. 99). Of course this assumes that no route will ever have more than 98 "pit stops". :) Safe assumption for me...
These logically defined "stop_numbers" also solve my problem for querying all child PitStops for the 'trips/index' display, and I can query these values quickly and effectively per trip (no more sub queries for .first or .last):
class Trip
has_many :pit_stops
has_one :starting_from, :class => 'PitStop',
:conditions => 'pit_stops.stop_number == 0'
has_one :ending_at, :class => 'PitStop',
:conditions => 'pit_stops.stop_number == 99'
def add_pit_stop(location)
stop_num = #pit_stops.count - 1 # accounts for stop_number 99
#pit_stops.create!({ :stop_number => stop_num,
:location => location})
end
end
As you see, the trick to entering the stop_numbers is now a simple math equation after defining your starting_from and ending_at records (now a logical business rule). Now I can simply say:
trip = create_trip("Christmas Visits", "Home", "Time Square")
trip.add_pit_stop("Mom and Dads")
trip.add_pit_stop("In-Laws")
trip.add_pit_stop("Grandma's")
My (ordered) PitStop records now look like this:
{ :stop_number => 0, :location => "Home" }
{ :stop_number => 1, :location => "Mom and Dads" }
{ :stop_number => 2, :location => "In-Laws" }
{ :stop_number => 3, :location => "Grandma's" }
{ :stop_number => 99, :location => "Time Square" }
Very elegant in my opinion. Thanks #clyfe for the tip!
Add two extra relations to the Trip class:
clss Trip
has_many :pit_stops
has_one :start_pit_stop, :class => 'PitStop',
:conditions => 'pit_stops.order_number == 1'
has_one :end_pit_stop, :class => 'PitStop',
:conditions => 'pit_stops.order_number == trips.last_order_number'
end
For the start put_stop you can condition on == 1, for the last one you need an extra column on the trips table where you cache the last trip number. You could also cache the ids for these two pit_stops on the parent. This way you can do eager load.
Well, if it is ok to do it in two db trips, you could use
first_stop = t.pit_stops.order(:stop_number).first
last_stop = t.pit_stops.order(:stop_number).reverse_order.first
I want to validate a number :value to be within 1 or 2
validates :value, :format => { :with => /1|2/, :message => "Select number.." }
However, the above code is failing the validation when value == 1
Please ensure that your solution allows me to add a message for the validation.
validates :value, :inclusion => {:in => [1,2]}
See http://apidock.com/rails/ActiveModel/Validations/HelperMethods/validates_inclusion_of
You're looking for validates_inclusion_of:
validates_inclusion_of :value, :in => [1, 2],
:message => "Select one of %{value}"
You can also use the (fairly new) shothand form and a Range instead of an Array:
validates :value, :inclusion => { :in => 1..2 }
if you want it to be a number within 1 and 2 ( 1.5, 1.6839749, etc ) do
validates_numericality_of :value, :greater_than_or_equal_to => 1, :less_than_or_equal_to => 2, :message => "blah"
may not be what you are looking for but is worth noting,
If you use inclusion error messages are not good:
["Value is not included in the list"]
Use
validates :value, presence: true, numericality: { greater_than_or_equal_to: 1, less_than_or_equal_to: 10 }
For better error messages, like:
["Value must be less than or equal to 2"]
I'm running Sinatra 1.0 with HAML, my form has a number of checkboxes, for example books I like, and you would select all the books you want. The checkbox name is "books".
In sinatra params['books'] there should be an array of all the books that were checked, but it only has the last item that was checked, not an array.
How can I get all the checked items?
HAML:
%form{:action => "/test", :method => 'post'}
%input{:name=>'check',:type=>'checkbox',:value=>'item1'} item 1
%input{:name=>'check',:type=>'checkbox',:value=>'item2'} item 2
%input{:name=>'check',:type=>'checkbox',:value=>'item3'} item 3
%input{:type => "submit", :value => "send", :class => "button"}
Sinatra get method
post '/test' do
puts params['check'] #should be an array but is last item checked
end
Very close, but do not but numbers in the arrays
%form{:action => "/test", :method => 'post'}
%input{:name=>'check[]',:type=>'checkbox',:value=>'item1'} item 1
%input{:name=>'check[]',:type=>'checkbox',:value=>'item2'} item 2
%input{:name=>'check[]',:type=>'checkbox',:value=>'item3'} item 3
Now,
post '/test' do
puts params['check'] #puts an array of what was checked to stdout
end
Wouldn't that output a bunch of checkboxes with the same name? If so, params['check'] is probably getting replaced with each new checkbox.
Try naming each one something different. If you really want it in an array, try hacking the names:
%input{:name=>'check[1]',:type=>'checkbox',:value=>'item1'} item 1
%input{:name=>'check[2]',:type=>'checkbox',:value=>'item2'} item 2
%input{:name=>'check[3]',:type=>'checkbox',:value=>'item3'} item 3
Try
%input{:type => "checkbox", :value => "1", :name => "checkbox[]", :id => "id1"} Chk1
%input{:type => "checkbox", :value => "2", :name => "checkbox[]", :id => "id2"} Chk2
%input{:type => "checkbox", :value => "3", :name => "checkbox[]", :id => "id3"} Chk3
Then in the rails or sinatra
puts params[:checkbox]
Then you can see the checked items.
I'm constantly doing this
puts “The temperature is “ + String(temperature) + “.”
in my debugging code, and another option is to use interpolation
puts “The temperature is #{temperature}.”
is there any less cumbersome way to do this?
Edit: This is just for debugging, if that matters.
None that are all that worthwhile for small cases like that.
Though, you should prefer interpolation as it's less expensive than concatenation.
The best way to insert dynamic variables into strings is
#interpolation
"foo #{my_var} bar"
It will call the to_s method on whatever object the expression returns and insert that string. It really the same as
#concatenation
"foo " + my_var.to_s + " bar"
But, as wfarr metioned, its faster to do interpolation. Easier to read too.
A slightly different approach is to use assertions in automated tests.
For example using Test::Unit :-
assert_equal 25, temperature
I find that using automated tests dramatically cuts down on the amount of debugging code I have to write.
Use Kernel#p
p temperature #=> 10.25
When I'm debugging, I often label such statements just by copying the line, and using inserting a colon, making the variable into a symbol.
p :attributes #=> :attributes
p attributes #=> { :mood => "happy", 5 => [] }
Or
p [:location, location] #=> [ :location, "# work" ]
Note that Kernel#p calls #inspect on its arguments, instead of #to_s, but this normally provides more useful debugging info anyway.
I highly recommend to use irbtools gem which includes awesome_print or just awesome_print.
I personally find it faster and less cumbersome to use in dev, then using interpolated strings, thou sometimes that's the only way to go.
You can do this on any object and it will give you a nicely formatted otput be that array, string or hash or even any other complex object that you may have - like 3-dimentional array printted as a tree structure. In order to have it awailable in your rails env - just include it in the Gemfile in the development group, or add it to .irbrc - to always have it in your irb console. Then just do
require "awesome_print"
ap MyGreatObject
here is a sample output from one of my projects
ap Address
class Address < ActiveRecord::Base {
:id => :integer,
:address_line_1 => :string,
:address_line_2 => :string,
:address_line_3 => :string,
:city => :string,
:state => :string,
:zip => :string,
:country => :string,
:attn => :string,
:category_id => :integer,
:addressable_id => :integer,
:addressable_type => :string,
:created_at => :datetime,
:updated_at => :datetime
}
ap Address.first
Address Load (1.0ms) SELECT `addresses`.* FROM `addresses` LIMIT 1
#<Address:0x7bc5a00> {
:id => 1,
:address_line_1 => "1 Sample Drive",
:address_line_2 => nil,
:address_line_3 => nil,
:city => "Chicago",
:state => "IL",
:zip => "60625",
:country => "USA",
:attn => nil,
:category_id => 1,
:addressable_id => 1,
:addressable_type => "Warehouse",
:created_at => Tue, 10 Jan 2012 14:42:20 CST -06:00,
:updated_at => Tue, 17 Jan 2012 15:03:20 CST -06:00
}
There's always the possibility to use printf style formatting:
"The temperature is %s" % temperature
This would allow for finer formatting of numbers, etc. as well. But honestly, how much less "cumbersome" than using #{} interpolation can you expect to get?
Another way is to do something stupid like this:
"The temperature is %s." % temperature.to_s
Personally I'd use interpolation