Ruby Activerecord IN clause - ruby

I was wondering if anyone knew how to do an "IN" clause in activerecord. Unfortunately, the "IN" clause is pretty much un-googleable so I have to post here. Basically I want to answer a question like this "Give me all the college students that are in these dormitories where the dormitory id is in this array [id array]". I know how to write the query given a single dormitory id, but I don't know how to do it given an array of ids.
Any help is greatly appreciated. I'm sure this is a repost of a question somewhere, so I'll delete this once an answer/better search term is found.

From §3.3.3 Subset Conditions of the Rails Guides:
If you want to find records using the IN expression you can pass an
array to the conditions hash:
Customer.where(orders_count: [1,3,5])
This code will generate SQL like this:
SELECT * FROM customers WHERE
(customers.orders_count IN (1,3,5))
You can also use the arel syntax:
Client.where(Client.arel_table[:order_count].in([1,3,5]))
will generate the same SQL.

Related

column "likes.id" must appear in the GROUP BY clause or be used in an aggregate function

So I am trying to add top posts functionality for my Sinatra project using postgresql with the following statement Like.group(:exercise_id).order('COUNT(exercise_id) DESC').each do |like|
But when I try this I get an error saying column "likes.id" must appear in the GROUP BY clause or be used in an aggregate function
And when I add this
Like.group(:exercise_id, :id).order('COUNT(exercise_id) DESC')
It gives me the whole table when all I want is to group by likes. Is there a workaround for this?
What the error is telling you, is that you're selecting for "likes.id", but there is no single likes.id that the database can give you.
This is because by default when you don't tell Rails what you need, Rails will select EVERYTHING.
Think, do you actually need "likes.id"? Looks to me that you're grouping by exercise_id so what you're trying to get is exercises and their like counts. (correct me if I'm wrong.) You don't actually need specific like id-s.
If that's so, we need to tell rails about our intention.
Like.group(:exercise_id).order('COUNT(exercise_id) DESC').select(:exercise_id)
If you also need the count itself, just add it to the select.
Something else you might want to try is just .count. It's pretty smart and will respect your grouping. See if this helps.
Like.group(:exercise_id).count

Calling PostGIS functions within Ruby

I need to execute the PostGIS function st_intersection within an SQL SELECT clause in Ruby. At the moment I am doing it as raw SQL query:
sql_query = "SELECT id, ST_ASEWKT(ST_INTERSECTION(geometry, ?)) FROM trips WHERE status='active';"
intersections = Trip.execute_sql(sql_query, self[:geometry].to_s)
This way has the disadvantage that I receive the result as text and I need to parse the objects out of the strings. Much nicer would be the use of the ActiveRecord interface to make queries. However, I could not find any solution yet to run PostGIS functions (e.g. st_intersection) within ActiveRecord.
An earlier version of the activerecord-postgis-adapter's README showed a nice example using the gem squeel:
my_polygon = get_my_polygon # Obtain the polygon as an RGeo geometry
MySpatialTable.where{st_intersects(lonlat, my_polygon)}.first
As this is not part of the current README anymore, I am wondering whether this is not recommended or if there are any better alternatives.
There are two problems to solve here.
The first is using an SQL function within a .select clause. Ordinarily this is pretty easy—you just use AS to give the result a name. Here's an example from the ActiveRecord Rails Guide:
Order.select("date(created_at) as ordered_date, sum(price) as total_price").group("date(created_at)")
The resulting Order objects would have ordered_date and total_price attributes.
This brings us to the second problem, which is that Rails doesn't give us an easy way to parameterize a select (i.e. use a ? placeholder), so (as far as I can tell) you'll need to do it yourself with sanitize_sql_array:
sql_for_select_intersection = sanitize_sql_array([
"ST_ASEWKT(ST_INTERSECTION(geometry, ?)) AS intersection",
geometry,
])
This will return a sanitized SQL fragment like ST_ASEWKT(ST_INTERSECTION(geometry, '...')), which you can then use to specify a field in select:
Trip.where(status: "active").select(:id, sql_for_select_intersection))
The resulting query will return Trip objects with id and intersection attributes.

Freemarker Help: Pass Data to List Directive for Sorting

First time poster and a Freemarker novice. I'm hoping someone can assist on this. I am currently referencing data from a 1-to-many table using the <#data> directive. I want to sort the results in a particular field order, but I think that can only be done by the <#list> directive. Here's what I have so far:
There's a CART_ABANDONMENT table with the following fields:
CUSTOMER_ID_
PRODUCT_ID
PRODUCT_NAME
PRODUCT_PRICE
ABANDONED_DATE
<#data CART_ABANDONMENT as abandonment><br>
<#filter CUST_ID="${CONTACTS_LIST.CUSTOMER_ID_}"><br>
<#fields PRODUCT_ID PRODUCT_NAME PRODUCT_PRICE ABANDONED_DATE><br>
${abandonment.PRODUCT_NAME} ${abandonment.PRODUCT_PRICE}<br>
</#data>
What I want to do is to list all related results (by CUSTOMER_ID_) and sort them by PRODUCT_PRICE, descending.
It may be something simple, but I haven't been able to find the answer.
Any guidance would be appreciated.
Freemarker is powerful tool tool but it's just template engine.
It has the sort directive for list, but it can be applied only to built-in types: String, Number and Date.
You may convert list of you complex type to one or more lists of built-in types and use ?sort in template.
Another way is to pass already sorted(as you want) list to template before processing.
What you want sounds like something that should be solved on the database (SQL) level, especially where you say "list all related results (by CUSTOMER_ID_)". FreeMarker is only the V (for View) in MVC.

hibernate - using 'having' without group by clause in hql

im trying to run an hql query which aggragets (sum) number of transactions made on a specific account, i dont need a group by since my where clause has a specific account filter (where account = :account)
i do, however, want to return the aggregated value only if it is smaller/bigger than some given value.
when im adding 'having' after the where clause without 'group by' im getting an error -
unexpected token: having
in native sql i succeeded adding 'having' without group by
any ideas on how to make it work with hql?
thanks alot
The reason why databases don't let you mix grouped columns with non-grouped and non-aggregated ones is, that for non-grouped/non-aggregated columns it would have to choose one row's value per group, but doesn't know how to pick one.
If you don't care, then you could just leave it away and if it doesn't matter because they're all the same, you could group by them, too.
It is not hql, but if you have native query, then run it like:
Query query = session.createSQLQuery("select, *** ,... blah blah")
//set If you need
query.setParameter("myparam", "val");
List result = query.list();
In my eyes this is nonsense. 'having' is done for conditions on a 'group by' result. If you don't group, then it does not make much sense.
I would say HQL can't do it. Probably the Hibernate programmers didn't think of this case because they considered it as not important.
And anyway, you don't need it.
If it is a simple query, then you can decide in your java code if you want the result or if you don't need it.
If it is in a subselect, then you can solve the problem with a where condition in the main select.
If you think it is really necessary then your invited to give a more concrete example.

SQLITE3 strings in where clauses seem confused

I'm wondering if anyone has any clarification on the difference between the following statements using sqlite3 gem with ruby 1.9.x:
#db.execute("INSERT INTO table(a,b,c) VALUES (?,?,?)",
some_int, other_int, some_string)
and
#db.execute("INSERT INTO table(a,b,c) VALUES (#{some_int},"+
+"#{some_int}, #{some_string})")
My problem is: When I use the first method for insertion, I can't query for the "c" column using the following statement:
SELECT * FROM table WHERE c='some magic value'
I can use this:
"SELECT * FROM table WHERE c=?", "some magic value"
but what I really want to use is
"SELECT * FROM table WHERE c IN ('#{options.join("','")}')"
And this doesn't work with the type of inserts.
Does anyone know what the difference is at the database level that is preventing the IN from working properly?
I figured this out quite a while ago, but forgot to come back and point it out, in case someone finds this question at another time.
The difference turns out to be blobs. Apparently when you use the first form above (the substitution method using (?,?)) SQLite3 uses blogs to enter the data. However, if you construct an ordinary SQL statement, it's inserted as a regular string and the two aren't equivalent.
Insert is not possible to row query but row query used in get data that time this one working.
SQLite in you used in mobile app that time not work bat this row query you write in SQLite Browse in that work

Resources