How to use collate option with rails3 migration? - ruby-on-rails-3

I am using Sqlite3 which comes default with rails 3.
How to change a particular column to collate NOCASE with a rails migration?
I tried out t.change :name, :string, :collate => "NOCASE", but the case insensitive search for find_by_name("test", :order => "name collate NOCASE") gives no result as expected?

I guess the format might be the issue. Try:
:COLLATE => :NOCASE

Related

ruby on rails , sphinxql: syntax error, unexpected QUOTED_STRING, expecting CONST_INT or '-' near ''5') AND `active` IN ('1') AND ....

I use sphinx 3.4.0 and rails 5, when i want to search i got this error !!
sphinxql: syntax error, unexpected QUOTED_STRING, expecting CONST_INT or '-' near ''5') AND `active` IN ('1') AND ....
index
ThinkingSphinx::Index.define :firm, with: :active_record do
# fields
indexes corporate_name, :sortable => true, :as => :rs
indexes [addresses.city.region.name, addresses.free_region], :as => :wilaya
indexes [addresses.street_1, addresses.street_2, addresses.street_3], :as => :adresse
end
It looks like you're passing in a string in your search request - perhaps as a filter value? - when it should be an integer. Thinking Sphinx requires filter values to be cast as their appropriate types.
e.g.
Firm.search "foo", :with => {:account_id => params[:account_id].to_i}
This is a relatively recent change, so old documentation and examples may be out-of-date and not do this.

How to populate a sql db with t.decimal precision and scale via rails c

t.decimal "eur", precision: 8, scale: 2
This is my Row in the Database table (name is wallet). How can I populate it with data in the rails console?
I have tried
wallet.eur=10 Ok this one is to easy and doesnt work.
wallet.eur=BigDecimal.new('154.00') This one throws something like
=> #<BigDecimal:56cadb8,'0.154E3',9(18)> But i cant save it and will stay at 0.0.
Any Idea or suggestion?
Use the built-in rails facilities, check the NumberHelper documentation for examples.
Use this code to add the migration:
add_column :items, :price, :decimal, :precision => 8, :scale => 2
and then use this method:
number_to_currency(price, :unit => "€")
If you've got an NoMethodError add this line:
include ActionView::Helpers::NumberHelper
If dealing with currency maybe money-rails gem might be worthwhile?
Or something similar just using an integer and storing it in pence/cents and creating helpers to display it.
Plays much nicer than using decimal or worse float.

Rails 3. Validating email uniqueness and case sensitive fails

I am developing an app in Rails 3 and upon signup I need the user to enter their email address and I need it to be unique and case sensitive. I.e. no one should be able to sign up with myEmail#yahoo.com when MyEmail#yahoo.com already exists in the database.
This is my code and it crashes the app:
validates :email, :presence => true, :uniqueness => true, :case_sensitive => true,
:format => {:with => /^([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})$/i}
What is wrong with it?
Please dont use case sensitive there!!!. It will fetch all the users! So if you have 100.000 users. first it will fetch them all with LOWER(email). This can be VERY slow and it wont use your index on email.
Here an article that i found just now about this topic: http://techblog.floorplanner.com/post/20528527222/case-insensitive-validates-uniqueness-of-slowness
My suggesting is: Run a query to make all the emails downcased and make a before validation filter to downcase the email attribute so you dont have any uppercased characters in that column.
User.update_all('email = LOWER(email)')
before filter:
before_validation :downcase_email
private
def downcase_email
self.email = email.downcase if email.present?
end
For the Rails 3 type of validation you need to nest the casse insensitive block like so
validates :email, :uniqueness => { :case_sensitive => false }
I don't have the reputation to comment on the accepted answer, but #medBo asked about how this behaves in Rails 4. For reference, when using Rails 4.2 + MySQL, if I specify
validates :username, uniqueness: { case_sensitive: true }
ActiveRecord performs this query:
SELECT 1 AS one FROM `users` WHERE `users`.`username` = 'TEST_USER' LIMIT 1
In this case the search is not case sensitive. But when I set:
validates :username, uniqueness: { case_sensitive: false }
it performs:
SELECT 1 AS one FROM `users` WHERE `users`.`username` = BINARY 'TEST_USER'
The BINARY operator ensures the search is case sensitive without fetching all users, meaning for my setup at least, the case_sensitive flag doesn't suffer from the performance issue that #Michael Koper notes for earlier versions of Rails. I can't comment on how ActiveRecord performs for other database setups.
I'm not sure if it is possible to do case insensitive validations using that syntax (at least, I haven't found any documentation for it).
You should be able to validate case insensitive uniqueness like this though:
validates_uniqueness_of :email, :case_sensitive => false
Without more detail on the crash you get, I can't help more than that.
You can use a callback in your model like "before_validation" on email attribute to make it lowercased like this:
before_validation { self.email = email.downcase }
This will make the email input lowercased, after that try uniqueness validation without case sensitive:
validates :email, uniqueness: true
For more info about callbacks: here is ruby guide
https://guides.rubyonrails.org/active_record_callbacks.html

Rails : migration for creating a fixed-length char(12) column

What is the best way to define a fixed-length SQL column (CHAR(12) for instance) through a Rails migration ?
Why this should not handled by the model is because of the performance of char() vs varchar(), and I'd like to avoid injecting raw SQL in the database.
Edit : I know the :limit modifier, however the field is still varchar (which is bad for performance) and does not allow a minimum size.
If Rails doesn’t understand the column type, it’ll pass it straight through to the database. So if you want a char instead of varchar, just replace:
t.column :token, :string
With:
t.column :token, "char(12)"
Of course, this may or may not make your migrations non-portable to another database.
(credit to http://laurelfan.com/2010/1/26/special-mysql-types-in-rails-migrations)
def self.up
add_column("admin_users", "username", :string, :limit => 25)
end
def self.down
remove_column("admin_users", "username")
end
You can use string type with limit option in your migration file like this:
t.string :name, :limit => 12, :null => false
For a database specific type, we can now use:
t.column(:column_name, 'char(12)')
And for a complete example:
class Foo < ActiveRecord::Migration
def change
create_table :foo do |t|
t.column(:column_name, 'custom_type')
t.timestamps
end
end
end

Rails ActiveRecord Find with Date

I'm having a hard time figuring this out but how do I tell my finder statement to ignore the time of the Datetime field in the db?
def trips_leaving_in_two_weeks
Trip.find(:all, :conditions => ["depart_date = ?", 2.weeks.from_now.to_date])
end
I want depart_date to come back as just a date but it keeps returning the time as well and causing this equality not to work. Is there someway to just compare against the dates? Thanks
Edit
Here's the code I'm using now that works:
Trip.find(:all, :conditions => ["DATE(depart_date) = ?", 2.weeks.from_now.to_date])
Not sure which DB you're using but does this work?
"depart_date = DATE(?)"
I would use this approach:
Rails 3.x
Trip.where(
:depart_date => 2.weeks.from_now.beginning_of_day..2.weeks.from_now.end_of_day
)
Rails 2.x
Trip.all(
:conditions => {
:depart_date => 2.weeks.from_now.beginning_of_day..2.weeks.from_now.end_of_day
})
If you index the depart_date column this solution will be efficient as the query uses the index. This solution is DB neutral.
When calculated fields are used in a where clause, the performance degrades(unless there is a special index).