RubyOnRails - search in the database by date - ruby-on-rails

I have in my db a attribute where i save the record creation date.
The saved date has this format:
2013/06/18 19:03:24
I need to search only for date and i am not interested the time
I have try in this mode but it's doesn't work:
Report.find_all_by_created_at("2013-06-18").each do |r| %>
[...]
end

Given that created_at is a Rails generated column you can't really and just for created at date. Reason for that is in database created_at is saved as timestamp (or Datetime) so records created on 18th of June may have values from 2013-06-18 00:00:00 to 2013-06-18 23:59:59.
So, if you'd like to select all objects created on specific day you should do something like
Report.where('created_at >= ? AND created_at <= ?, Date.new(2013,6,18).beginning_of_day, Date.new(2013,6,18).end_of_day)

You can pass a range to where:
date = Date.new(2013,6,18)
Report.where(created_at: date.beginning_of_day..date.end_of_day)
This creates a SQL statement like:
SELECT `reports`.* FROM `reports` WHERE `reports`.`created_at` BETWEEN '2013-06-18 00:00:00' AND '2013-06-18 23:59:59'

Probably not the best solution but you could do:
Report.where("created_at >= ? and created_at < ?","2013-06-18","2013,06-19").each do |r|
[...]
end

It looks like you are collecting it as a DateTime and you would probably be able to use the to_date() method to change it to a Date object which would be searchable.
http://api.rubyonrails.org/classes/DateTime.html#method-i-to_date

you can use like matcher in sql query
Report.where("created_at LIKE '2013-06-18%'")
or look at the Squeel gem it can call SQL functions in ruby like syntax then you could use something thati will generate query with
WHERE cast(created_at as date) = '2013-06-18'

Related

How to filter rails model by month

I want to get only those records of my model which belong to a particular month. I am using:
Order.where(created_at.strftime("%B"): "April")
where created_at is DateTime. created_at.strftime("%B") gives me month, but it does not work. Any alternative?
You'll probably have to do this in plan SQL (not the activerecord DSL):
Order.where("strftime('%m', created_at) = ?", 'April')
This uses the SQLite function to extract the month name
(I haven't done Rails in a while, let me know if this doesn't work)

How to get records by month

I have tried several solutions but the only one close enough to what i want is this
Sale.all.group("DATE_TRUNC('month', created_at)").count
but it returns something like this
{2016-07-01 00:00:00 UTC=>19, 2016-04-01 00:00:00 UTC=>70}
is there something that can do this format?
[month,number of sales] ??
using postgres db.
try use EXTRACT function of postgresql,
in Rails code
results = Sale.all.group("EXTRACT(MONTH FROM created_at").select("EXTRACT(MONTH FROM created_at) AS month, COUNT(*) as count")
p results[0].month if results[0]

Is it possible to convert the complex SQL into rails?

SPEC
I need to pick all rooms that don't have a single day with saleable = FALSE in the requested time period(07-09 ~ 07-19):
I have a table room with 1 row per room.
I have a table room_skus with one row per room and day (complete set for the relevant time range).
The column saleable is boolean NOT NULL and date is defined date NOT NULL
SELECT id
FROM room r
WHERE NOT EXISTS (
SELECT 1
FROM room_skus
WHERE date BETWEEN '2016-07-09' AND '2016-07-19'
AND room_id = r.id
AND NOT saleable
GROUP BY 1
);
The above SQL query is working, but I wonder how could I translate it into Rails ORM.
Let's say you have array of room_ids called room_ids:
needed_room_ids = room_ids - RoomSku.where(room_id: room_ids, date: '2016-07-09'..'2016-07-19', sealable: false).pluck(:room_id)
If your model of room_sku is called RoomSku
Updated version:
room_ids = Room.all.select { |record| record.room_skus.present? }.map(&:id)
And then:
needed_room_ids = room_ids - RoomSku.where(room_id: room_ids, date: '2016-07-09'..'2016-07-19', sealable: false).pluck(:room_id)
It won't be one query, but you avoid plain SQL like this.
I don't have any project here to test something like it, but it should work:
Room.where.not(id: RoomSku.where(date: DateTime.parse('2016-07-09').strftime("%Y-%m-%d")..DateTime.parse('2016-07-19').strftime("%Y-%m-%d"), saleable: false).pluck(:room_id))
I hope it helps!

Rails Where Created_at Equals specific number

I'm trying to figure out how to do a query where created_at.year == a given year, and created_at.month equals a given month.
However I can't figure out what I'm doing wrong.
Model.where("'created_at.month' = ? AND 'created_at.year' = ?", 7,2013)
results in nothing being shown.
However when I try Model.first.created_at.month ==7 and
Model.first.created_at.year ==2013 I get true for both.
Therefore theoretically my query should be at least be returning my first record.
Anyone know what I'm doing wrong or any alternative way to find records created on specific months?
Note that in my views the month / year will be parameters but for the purposes of this example I used actual values.
using ruby 1.9.3
rails 3.2.13
You can use the extract SQL function, that will extract the month and year of the timestamp:
Model.where('extract(year from created_at) = ? and extract(month from created_at) = ?', '2013','7')
This query should give you the desired result.
created_at is a timestamp; it is not a set of discrete fields in the database. created_at.year and such don't exist in your DB; it's simply a single timestamp field. When you call #model.created_at.year, Rails is loading the created_at field from the database, and creating a Time object from it, which has a #year method you can call.
What you want is to query on a range of dates:
Model.where("created_at >= ? and created_at < ?", Time.mktime(2013, 7), Time.mktime(2013, 8))
This will find any Model with a created_at timestamp in July 2013.

Rails & Postgresql: how to group queries by hour?

How do I group by hour in Postgres & Rails? I've read through quite a few SO answers but I'm getting errors.
This works when grouping by date:
Model.group("date(updated_at)").count
Then I tried the following for hour but they didn't work:
Model.group("hour(updated_at)").count
Model.group("date_format(updated_at, '%H')").count
Model.group("extract(hour from updated_at)").count
Once I've found certain hours I need to update, how would I then get the models with those hours? I.e:
Model.where("hour(updated_at) = ?", 5)
You could try the following
Model.group("DATE_PART('hour', updated_at)").count
UPDATE:
How to find records
Model.where("DATE_PART('hour', updated_at) = ?", 5)
PostgreSQL presents two ways to extract a part of date/time:
EXTRACT is SQL standard function that exists in other SQL based databases.
Model.group("EXTRACT(hour FROM created_at)").count
Model.where("EXTRACT(hour FROM created_at) = ?", 5)
date_part function
Model.group("date_part('hour', updated_at)").count
Model.where("date_part('hour', updated_at) = ?", 5)
The official documentation.
If you want both the date and the hour, you can use date_trunc:
Model.group("date_trunc('hour', created_at)").count
And if you want the answers in order:
Model.order("date_trunc('hour', created_at)").group("date_trunc('hour', created_at)").count
Yeah it's weird that you can't just do order(:created_at) but oh well.

Resources