I must connect from my Rails app to a remote database on a Java application.
I have a query like this:
find_by_sql("select c_templateid, c_templateinfoid, c_startdate, c_enddate, c_active,
campaign, shortcode, prefix, c_descriptivename, c_description, c_templatename
from (active_services aser join activity a on aser.c_primaryprefixid =
a.c_primaryprefixid ) join matrix_templateinfo using(c_templateinfoid)
where campaign is not null)")
I need to refactor it to the AR#find() method, because I want later add complex :conditions on it. I dont want convert them into string to append then later to the find_by_sql method.
find(:all,
:select => "c_templateid, c_templateinfoid, c_startdate, c_enddate, c_active,
campaign, shortcode, prefix, c_descriptivename, c_description, c_templatename",
# :joins => WHAT I SHOULD DO HERE ?
:conditions => "campaign is not null"
)
You can also specify complex joins in :joins
:joins => "matrix_templateinfo ON <conditions go here> AND campaing IS NOT NULL"
but you should really start padronizing your field names if you're using rails :]
Related
I have a CakePHP API backend service and I want to add a new service that queries a database with the following SQL query:
SELECT
cs.number,
cs.date,
relation_vs_cs.relation_vs_cs_id,
relation_vs_cs.vr_id,
relation_vs_cs.cn_id,
vs.vr_id,
vs.first_name,
vs.last_name,
vs.document_id
FROM cs
INNER JOIN relation_vs_cs
ON relation_vs_cs.cn_id = cs.cn_id
INNER JOIN vs
ON relation_vs_cs.vr_id = vs.vr_id
WHERE vs.document_id = 'O416680668750'
So i do something like this in CakePhp side but it didn't work for me :
$options['conditions'] = array(
'Vs.document_id' => $vrIdByDocumentId);
$options['joins'] = array(
array('table' => 'relation_vs_cs',
'alias' => 'Relationvscs',
'type' => 'INNER',
'conditions' => array(
'Relationvscs.cn_id = Cs.cn_id')
),
array(
'table' => 'vs',
'alias' => 'Vs',
'type' => 'INNER',
'conditions' => array(
'Relationvscs.vr_id = Vs.vr_id')
));
$cnTable = TableRegistry::get("Cs");
$queryResult = $cnTable->find('all', $options)
When I sent a request using postman I got the following error :
"message": "SQLSTATE[42S22]: Column not found: 1054 Unknown column 'vs.document_id' in 'where clause'",
Could you please help Thank you in advance
The option is named join (singular), not joins, just like the corresponding query builder method.
I would also suggest that you look into setting up associations for your relationships, which would then allow you to use the innerJoinWith() and leftJoinWith() methods (among others), making your query building much easier.
Also note that you need to manually specify the fields the fields that you want to select from the joins.
See also
Cookbook > Database Access & ORM > Retrieving Data & Results Sets > Using Finders to Load Data
Cookbook > Database Access & ORM > Associations - Linking Tables Together
Cookbook > Database Access & ORM > Query Builder > Loading Associations
I am trying to do a like query like so
def self.search(search, page = 1 )
paginate :per_page => 5, :page => page,
:conditions => ["name LIKE '%?%' OR postal_code like '%?%'", search, search], order => 'name'
end
But when it is run something is adding quotes which causes the sql statement to come out like so
SELECT COUNT(*)
FROM "schools"
WHERE (name LIKE '%'havard'%' OR postal_code like '%'havard'%')):
So you can see my problem.
I am using Rails 4 and Postgres 9 both of which I have never used so not sure if its and an activerecord thing or possibly a postgres thing.
How can I set this up so I have like '%my_search%' in the end query?
Your placeholder is replaced by a string and you're not handling it right.
Replace
"name LIKE '%?%' OR postal_code LIKE '%?%'", search, search
with
"name LIKE ? OR postal_code LIKE ?", "%#{search}%", "%#{search}%"
Instead of using the conditions syntax from Rails 2, use Rails 4's where method instead:
def self.search(search, page = 1 )
wildcard_search = "%#{search}%"
where("name ILIKE :search OR postal_code LIKE :search", search: wildcard_search)
.page(page)
.per_page(5)
end
NOTE: the above uses parameter syntax instead of ? placeholder: these both should generate the same sql.
def self.search(search, page = 1 )
wildcard_search = "%#{search}%"
where("name ILIKE ? OR postal_code LIKE ?", wildcard_search, wildcard_search)
.page(page)
.per_page(5)
end
NOTE: using ILIKE for the name - postgres case insensitive version of LIKE
While string interpolation will work, as your question specifies rails 4, you could be using Arel for this and keeping your app database agnostic.
def self.search(query, page=1)
query = "%#{query}%"
name_match = arel_table[:name].matches(query)
postal_match = arel_table[:postal_code].matches(query)
where(name_match.or(postal_match)).page(page).per_page(5)
end
ActiveRecord is clever enough to know that the parameter referred to by the ? is a string, and so it encloses it in single quotes. You could as one post suggests use Ruby string interpolation to pad the string with the required % symbols. However, this might expose you to SQL-injection (which is bad). I would suggest you use the SQL CONCAT() function to prepare the string like so:
"name LIKE CONCAT('%',?,'%') OR postal_code LIKE CONCAT('%',?,'%')", search, search)
If someone is using column names like "key" or "value", then you still see the same error that your mysql query syntax is bad. This should fix:
.where("`key` LIKE ?", "%#{key}%")
Try
def self.search(search, page = 1 )
paginate :per_page => 5, :page => page,
:conditions => ["name LIKE ? OR postal_code like ?", "%#{search}%","%#{search}%"], order => 'name'
end
See the docs on AREL conditions for more info.
.find(:all, where: "value LIKE product_%", params: { limit: 20, page: 1 })
I have some problem with this mongoid. It's my first time to use mongoDB, Before, I always use mySQL.
Here is my problem.
I have model "User". In model "User" has embedded one "Profile",
and I want to search users data with criteria name "dummy" for field "profile.first_name",
"profile.last_name", and "username".
I already use this syntax, but I got empty result:
#filter = "dummy"
#users = User.any_of({'profile.first_name' => /#{#filter}/i, 'profile.last_name' => /#{#filter}/i, :username => /#{#filter}/i})
Try this
#filter = "dummy"
#users = User.any_of({:profile.first_name => "/#filter/i"},{:profile.last_name="/#filter/i"}, {:username => "/#filter/i"})
look at the brackets.
Pls i have the following code in my model
Letter.count(:id, :conditions => ["language_id = #{lang} AND :created_at => '#{start_date.to_date.strftime('%Y-%m-%d')}'..'#{end_date.to_date.strftime('%Y-%m-%d')}' " ])
I am trying to get the count of letters.id of different letters between the given dates.
This is the error an having...
Please those anyone know what am doing wrong...Thanks
SQLite3::SQLException: near ">": syntax error: SELECT COUNT("letters"."id") FROM "letters" WHERE ("letters".language_id = 1) AND (language_id = 1 AND :created_at => '2011-05-01'..'2011-05-08
This can be much simplified. A couple points:
You don't use the :created_at => ... format within a string
You need to use between ? and ? for dates.
You don't need to manually strftime your dates, Rails will handle this automatically.
In Rails 3, the preferred way is to use where(...) instead of a :conditions Hash for your count(...).
You should probably use Rails' safe interpolation for your language_id field too
Letter.where("language_id = ? AND created_at between ? and ?", lang, start_date.to_date, end_date.to_date).count
I just moved from MySQL to Postgres 9.0.3. I have a brand new app with a little data (game data).
Anyway, I can't seem to get partial words to search. Here is my search method:
def self.search(query)
conditions = <<-EOS
to_tsvector('english', title) ## plainto_tsquery('english', ?)
EOS
find(:all, :conditions => [conditions, query])
end
I'm sure I need a wildcard in there but I'm just learning Postgres.
When I search for Shinobi I get the correct results:
Alex Kidd in Shinobi World - Sega Master System
Shinobi - Sega Master System
Shinobi - Nintendo Entertainment System
The Cyber Shinobi: Shinobi Part 2 - Sega Master System
But when I search for Shin I get nothing?
Thanks for any clues.
I think that to allow prefix matching you need to use to_tsquery instead of plainto_tsquery
that says http://www.postgresql.org/docs/current/static/textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES
so your code could be something like
def self.search(query)
conditions = <<-EOS
to_tsvector('english', title) ## to_tsquery('english', ?)
EOS
find(:all, :conditions => [conditions, query + ':*'])
end
You can also use a regular expression search as shown below.
find( :all, :conditions => [ 'name ~* ?', "SEARCH TERM" ] )
Append a * to your query string.
Search for Shin*.
def self.search(query)
conditions = <<-EOS
to_tsvector('english', title) ## plainto_tsquery('english', ?)
EOS
find(:all, :conditions => [conditions, query.concat("*")])
end
Use the prefix:
pg_search_scope :search, against: [:name, :email],
using: {tsearch: {prefix: true}}