PostgreSQL Ruby Heroku Problems - ruby-on-rails

This search condition works fine in MySQL, and SQLite but fails in PostgreSQL:
CONTROLLER:
#inventories = Inventory.search(params[:search], params[:page])
MODEL:
def self.search
paginate :per_page => 10,
:page => page,
:conditions => ['part_number = ? OR item LIKE ? OR catalognumber LIKE ?', "#{search}", "%#{search}%", "%#{search}%"],
:order => 'item'
end
IT produces this error in HEROKU's PostgreSQL log:
ActiveRecord::StatementInvalid (PGError: ERROR: invalid input syntax for integer: ""
2011-06-11T20:25:46+00:00 app[web.1]: : SELECT * FROM "inventories" WHERE (part_number = E'' OR item LIKE E'' OR catalognumber LIKE E'') ORDER BY item LIMIT 10 OFFSET 0):
How can I fix this?
SOLUTION... This is an issue of using LIKE rather than ILIKE
http://www.postgresql.org/docs/8.3/static/functions-matching.html

Presumably, one of those fields is expecting an integer, and Postgres is a lot less permissive on this front than MySQL. I shouldn't have any quotes. (It should be zero, or no field at all, instead.)

Related

Rails: SQLite3::SQLException: near "from": syntax error

I have an issue with a sort by year filter on my rails app; when i attempt to select a year from my view, the app crashes with this error: SQLite3::SQLException: near "from": syntax error
The code(passed down from the previous dev who has moved on) for the filter in my control is this:
#posts = Post.where('extract(year from sort_date) = ?', params[:year])
.paginate(page: params[:page], per_page: 5)
.order('sort_date DESC')
render 'index'
end
i might be wrong but i am assuming it's the 'extract(year from sort_date) = ?' in the code? but i am unsure, also for reference the reference parameter is: {"year"=>"2017"}
I attempted to make it look more like a postgres query("EXTRACT(year FROM sort_date) = ?" but still it fails, with the exact same SQL error(Rails: SQLite3::SQLException: near "from")
SQLITE3 does not support the extract() function. You have to use strftime().
#posts = Post.where("strftime('%Y', sort_date) = ?", params[:year])
.paginate(page: params[:page], per_page: 5)
.order('sort_date DESC')
render 'index'
end

Sorting a result defined by remote parameters

i have this index action:
def index
limit = params[:limit]
page = params[:page]
sort = params[:sort].split(',')
#term = nil
if params[:search]
#term = params[:search]
#lessons = policy_scope(Lesson).search(#term)
.order("#{sort[0]} #{sort[1].upcase}")
.paginate(page: page, per_page: limit)
else
#lessons = policy_scope(Lesson).order("#{sort[0]} #{sort[1].upcase}")
.paginate(page: page, per_page: limit)
end
end
which is fed by a vuejs frontend with a vuetify datatable and its purpose is to send out an array of lesson objects, filtered and sorted by the frontend.
this works pretty good with default rails..
however, with the mobility gem involved there is no fieldname "title" for example or "title_en", so the order stops working. in mobility you have some "fake column names" and it automagically handles it to search for the value in a key-value table ( https://github.com/shioyama/mobility#getting-started )
so i sat me down and fired up the console and figured out that:
.order(title: :desc) - works
.order(title_en: :asc) - works
everything with strings involved, like .order('title DESC') or .order('title_en ASC') does not work and results in an error like
ActionView::Template::Error (PG::UndefinedColumn: ERROR: column
"title_en" does not exist LINE 1: SELECT "lessons".* FROM "lessons"
ORDER BY title_en ASC LIMI...
is there a way i could get this working? maybe there is something to generate title: out of 'title'? Or some other magic?
thanks!
You can call the order method like this instead:
.order(sort[0] => sort[1])
Passing "a" => "b" to a method is the same as passing "a": "b".

Active Record Query Using Associated Model in Find Clause

I'm having a blonde moment and probably a brain freeze.
In my rails3 app, I have users and tasks. My users have many tasks...
I have due and overdue tasks as follows:
#due = Task.find(:all, :conditions => ["dueddate >= ? AND AND status = ?", Date.today, false], :include => :taskcategories, :order => "dueddate asc")
What I want to do in my tasks view, is list the users with due tasks...
For some reason, I can't get my head around it. I have tried this, but it's not working:
#task = Task.all
#user = User.find(:all, :conditions => ["#task.dueddate <= ? AND
#task.status = ?", Date.today + 7.days, false])
I'm sure this is easy, can anyone help me!!?
I guess this should work
updated
User.joins(:tasks)
.where("tasks.dueddate <= ? AND tasks.status = ?", Date.today + 7.days, false).group(:id)
This should work with SQLite and MySQL. However, PostgreSQL requires that you supply all the columns of the table. If it's a small table, you could simply type the names. Or you could add this method to the model:
def self.column_list
self.column_names.collect { |c| "#{self.to_s.pluralize.downcase}.#{c}"}.join(",")
end
and change .group(:id) to .group(User.column_list)

:select with find_in_batches in rails

How can I include a :select clause with find_in_batches. The following throws an error " Mysql::Error: Unknown column 'users.id' in 'field list': .
Post.find_in_batches(:batch_size => 100, :select => "users.id, users.name, categories.name, posts.id", :include => [:user, :category]) do |group|
#stuff with group
end
So, if you're considering using find_in_batches it probably means you have a lot of records to go through and you very well might only want select fields to be returned to you from the DB.
In Rails 3/4 you can chain find_in_batches with any other type ActiveRecord::Relation method (or at least, most... I have not tested all of them personally).
This is probably what you're looking for
User.select(:id).find_in_batches(:batch_size => 100) do |group|
# do something with group...
# like print all the ids
puts group.map(&:id)
end
If you try this in the console it generates SQL like this...
SELECT id FROM `users` WHERE (`users`.`id` > 895846) ORDER BY `users`.`id` ASC LIMIT 100
See more info here: http://api.rubyonrails.org/classes/ActiveRecord/Batches.html
Your life with Rails will be much easier if you just retrieve all of the fields for each model queried, like so:
Post.find_in_batches(:batch_size => 100, :include => [:user, :category]) do |post|
u = post.user
c = post.category
# do stuff
end
A trimmed select list, as in your question, provides a limited DB performance improvement, but in most cases not enough to be worth the clunkier code.

Rails SQL query with % Wildcards works in SQLite but not PostgreSQL?

I have a query I'm using for a search with :conditions like this:
:conditions => ['family_name LIKE ? OR given_name LIKE ?', "%#{params[:search]}%", "%#{params[:search]}%"]
The query works fine locally on SQLite, but when I push to Heroku on PostgreSQL, only the first % works for both family_name and given_name. In other words, it will match a keyword that occurs at the end of a word but not the beginning or middle.
Example:
There is an existing record with :family_name => "Washington" and :given_name => "George"
A search for "ington" or "rge" will retrieve this record. A search for "Wash" or "Geo" will not.
I'm a new user and am pretty new to rails. Thanks in advance for your help.
Solution
Related threads:
1
2
Here's the fix I am using:
:conditions => ['LOWER(family_name) LIKE ? OR LOWER(given_name) LIKE ?', "%#{params[:search].downcase}%", "%#{params[:search].downcase}%"]
LIKE is a case-sensitive operator in Postgres. For case-insensitive pattern matching use ILIKE or other standard methods.

Resources