Rails uniqueness => true encoding issue - ruby-on-rails

Ive run into an issue with rails uniqueness validator when using UTF character in rails 3.0.12 (Ruby 1.8.7).
Here's my little test:
CORRECT:
name = "dave"
count = User.where(:name => name).count
u = User.new(:name => name, :gender => "Male")
puts "Current: #{count} / Valid: #{u.valid?} / Errors: #{u.errors.to_a.to_sentence}"
Output: Current: 1 / Valid: false / Errors: Name is already taken
SQL (0.2ms) SELECT COUNT(*) FROM `users` WHERE `users`.`name` = 'dave'
SQL (0.1ms) SELECT 1 FROM `users` WHERE (`users`.`name` = BINARY 'dave') LIMIT 1
INCORRECT:
name = "angélique"
count = User.where(:name => name).count
u = User.new(:name => name, :gender => "Male")
puts "Current: #{count} / Valid: #{u.valid?} / Errors: #{u.errors.to_a.to_sentence}"
Output: Current: 3 / Valid: true / Errors:
SQL (0.1ms) SELECT COUNT(*) FROM `users` WHERE `users`.`name` = 'angélique'
SQL (0.1ms) SELECT 1 FROM `users` WHERE (`users`.`name` = BINARY 'angélique') LIMIT 1
It seems the where clause uses the correct encoding and finds the result but the check on the presence validator doesn't.
Any ideas how i could resolve this?

I think it's likely that your app is using UTF-8 but that your DB isn't:
http://guides.rubyonrails.org/getting_started.html#configuration-gotchas
That guide contains examples for doing this for MySQL and PostgreSQL earlier in the page.

Related

How to properly make a Raw SQL in Ruby on Rails?

I am into a Rails Console session trying to run a Raw SQL query. If I use Active Record like this, this is the result:
irb(main):006:0> count = Sf::Program.count
Sf::Program Count (132.8ms) SELECT COUNT(*) FROM "salesforce"."program__c"
=> 54348
If I try to run this same query, but with ActiveRecord
irb(main):007:0> sql = 'SELECT COUNT(*) FROM salesforce.program__c'
=> "SELECT COUNT(*) FROM salesforce.program__c"
irb(main):008:0> sql = 'SELECT COUNT(*) FROM "salesforce"."program__c"'
=> "SELECT COUNT(*) FROM \"salesforce\".\"program__c\""
irb(main):009:0> ActiveRecord::Base.connection.exec_query(sql)
IM getting an error
/Volumes/Laje/fmaymone/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/activerecord-7.0.4/lib/active_record/connection_adapters/postgresql_adapter.rb:768:in `exec_params': ERROR: relation "salesforce.program__c" does not exist (PG::UndefinedTable)
LINE 1: SELECT COUNT(*) FROM "salesforce"."program__c"
What IM doing wrong here???

ruby on rails: search through associations

I have little understanding problem:
I have Channel and Lecturer, where a Channel :has_and_belongs_to_many :lecturers.
I want to get all Channels where Lecturer.id is lect.id.
2.3.0 :235 > Channel.where(:lecturers => { :id => 2 })
Channel Load (0.1ms) SELECT "channels".* FROM "channels" WHERE "lecturers"."id" = 2
SQLite3::SQLException: no such column: lecturers.id: SELECT "channels".* FROM "channels" WHERE "lecturers"."id" = 2
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: lecturers.id: SELECT "channels".* FROM "channels" WHERE "lecturers"."id" = 2
This does not work and I feel like I don't understand the core concept, since I can do
2.3.0 :231 > Channel.first.lecturer
=> #<Lecturer id: 2, name: "Albert Einstein">
What am I missing?
You'll want to join the tables to do this query. See the docs
Channel.joins(:lecturer).where(lecturers: {id: lect.id})

Active Record calculations in Ruby

Could someone please help on how to use 'where' condition in this active record condition or why this throws error in rails 4.2?
p = Project.first
Project Load (34.6ms) SELECT `projects`.* FROM `projects` ORDER BY `projects`.`id` ASC LIMIT 1
=> #<Project id: 1, name: "First Project", created_at: "2015-12-29 16:27:42", updated_at: "2015-12-29 16:27:42">
2.2.1 :031 > p.tasks.sum(:priority)
(26.8ms) SELECT SUM(`tasks`.`priority`) FROM `tasks` WHERE `tasks`.`project_id` = 1
=> 9
2.2.1 :032 > p.tasks.sum(:priority).where(:complete => 0)
(0.2ms) SELECT SUM(`tasks`.`priority`) FROM `tasks` WHERE `tasks`.`project_id` = 1
**NoMethodError: undefined method `where' for 9:Fixnum**
sum returns Fixnum, not AR relation. You need to reverse where and sum order:
p.tasks.where(:complete => 0).sum(:priority)

Active Record "Where" Query Failing to find Record

So have a token model that has keys which are strings. I am doing a search for a token that exists and when i do a direct comparrison of the string with the record it should find i get an empty active record relation object.
Anyone know what is going on here? Am i stepping on a models toes by using the Model name 'Token'. I didn't find anything in the googles about it.
I've stored the key as 'a' below and Token.last.key is the database entry that has the matching key.
irb(main):023:0> a
=> "279684d7488254c41bb4039ad0962007"
irb(main):024:0> Token.last.key
Token Load (0.4ms) SELECT "tokens".* FROM "tokens" ORDER BY "tokens"."id" DESC LIMIT 1
=> "279684d7488254c41bb4039ad0962007"
irb(main):025:0> a == Token.last.key
Token Load (0.1ms) SELECT "tokens".* FROM "tokens" ORDER BY "tokens"."id" DESC LIMIT 1
=> true
irb(main):026:0> Token.where(key: a)
Token Load (0.2ms) SELECT "tokens".* FROM "tokens" WHERE "tokens"."key" = '279684d7488254c41bb4039ad0962007'
=> #<ActiveRecord::Relation []>
irb(main):027:0> Token.where(key: a.to_s)
Token Load (0.2ms) SELECT "tokens".* FROM "tokens" WHERE "tokens"."key" = '279684d7488254c41bb4039ad0962007'
=> #<ActiveRecord::Relation []>
Oddly enough, when i do a search through all the records i do return the correct user
#DOES WORK
def current_user(key)
Token.all.first {|t| return t.key == key }
end
What i have will work but what i would like it to do this in the database with something like this
#DOES NOT WORK
def current_user(key)
Token.where(key: key).try(:user)
end
Doing search based on suggestion below returning nil for find_by
irb(main):004:0> a = Token.last.key
Token Load (0.2ms) SELECT "tokens".* FROM "tokens" ORDER BY "tokens"."id" DESC LIMIT 1
=> "279684d7488254c41bb4039ad0962007"
irb(main):005:0> Token.find_by(key: a)
Token Load (0.2ms) SELECT "tokens".* FROM "tokens" WHERE "tokens"."key" = '279684d7488254c41bb4039ad0962007' LIMIT 1
=> nil
Solution was to do this
def find_user_by_api(key)
tokens = Token.arel_table
Token.where(tokens[:key].matches(key)).try(:first).try(:user)
end
Wish it helps
Token.find_by(key: a)

In Rails, why are these extra queries being run when saving a record?

In $ rails console I noticed that multiple queries are being run when I save a record:
ruby-1.9.2-p180 :001 > ActiveRecord::Base.logger = Logger.new(STDOUT)
=> #<...>
ruby-1.9.2-p180 :002 > p = Project.first
Project Load (0.3ms) SELECT `projects`.* FROM `projects` LIMIT 1
=> #<Project id: 1, category_id: 1, qualified_at: "2011-12-14 15:06:29", ...>
ruby-1.9.2-p180 :003 > p.qualified_at = Time.now
=> 2011-12-14 10:11:42 -0500
ruby-1.9.2-p180 :004 > p.save
SQL (0.2ms) BEGIN
SQL (1.5ms) SHOW TABLES
AREL (0.3ms) UPDATE `projects` SET `qualified_at` = '2011-12-14 15:11:42', `updated_at` = '2011-12-14 15:11:47' WHERE `projects`.`id` = 1
Category Load (0.3ms) SELECT `categories`.* FROM `categories` WHERE `categories`.`id` = 1 ORDER BY name LIMIT 1
ProjectPerson Load (0.4ms) SELECT `project_people`.* FROM `project_people` WHERE (`project_people`.project_id = 1 AND (project_people.is_client = 1)) LIMIT 1
Person Load (0.3ms) SELECT `people`.* FROM `people` WHERE (`people`.`id` = 2)
ProjectTag Load (0.4ms) SELECT DISTINCT `project_tags`.tag_id FROM `project_tags` WHERE (`project_tags`.project_id = 1)
SQL (0.5ms) COMMIT
=> true
I don't have before or after filters in my Project model, and I'm not using an Observer. Obviously these queries relate to associations of the Project model, but why are the queries being run? Not sure what else to consider. Thanks.
I just figured it out... I'm using the sunspot_rails gem and it was updating the index for that record :) These were associations that were referenced in my index definition.
I'll keep the question in case anyone else happens to come across a similar problem.

Resources