How do you query a Model by parent ID & created at date - ruby-on-rails

I'm trying to find all the records that have a specific channel_id, and were made less than 1 day ago. The query finds the records with the given channel_id but does not respect the date restriction. Instead, it returns records created at any date.
#discussions = Discussion.where('channel_id = ? and created_at > ?', current_user.subscription.pluck(:channel_id), 1.days.ago )
I expected to only get the Discussions that had relevant subscriptions channel_id, and were made less than 1 day ago. But instead, this query ignores the created at restriction but returns the Discussions that had the corresponding subscriptions channel ID.

#discussions = Discussion.where("channel_id IN (?) AND DATE(created_at) >= ?", current_user.subscription.pluck(:channel_id), (Date.today - 1.day))
OR
#discussions = Discussion.where("channel_id IN (?) AND created_at >= ?", current_user.subscription.pluck(:channel_id), (Date.today - 1.day).end_of_day)
Or
Discussion.where("DATE(created_at) >= ?", (Date.today - 1.day))
.where("channel_id IN (?)", current_user.subscription.pluck(:channel_id))

#discussions = Discussion.where("channel_id = :channel AND created_at > :date", channel: current_user.subscription.pluck(:channel_id), date: Date.yesterday )

Related

Rails 4: Selecting records between current date and given specific date/number of days in past

I have a Customer table in my Rail app. In the customer table one field is customer_expiry_date.
I want to add a filter in my application, that means customers, who all are expires within the following criteria:
Expire within one(1) day.
Expire within seven(7) days.
Expire within one(1) month.
How should I write my query using where clause to achieve this ?
My current query is like:
#customers = Customer.where.not(customer_expiry_date: nil)
How to select customers into three collection based on my requirement ?
#customers_exp_1day = ?
#customers_exp_1week = ?
#customers_exp_1month = ?
Just write a scope in your model:
class Customer < ActiveRecord::Base
# your code
scope :expired_in, -> (from_now) {
where.not(customer_expiry_date: nil).where('customers."customer_expiry_date" >= ? AND customers."customer_expiry_date" <= ?', Time.now, Time.now + from_now)
}
end
Then use it:
#customers_exp_1day = Customer.expired_in(1.day)
#customers_exp_1week = Customer.expired_in(1.week)
#customers_exp_1month = Customer.expired_in(1.month)
Now it will work with the latest update.
#customers_exp_1day = Customer.where("customer_expiry_date <= ?",
Date.tomorrow)
#customers_exp_1week = Customer.where("customer_expiry_date <= ?",
Date.today + 1.week)
#customers_exp_1month = Customer.where("customer_expiry_date <= ?",
Date.today + 1.month)
You had "Customers" in your question and I used "Customer" here, assuming that your model name is actually singular.

Get impresions count from today, yesterday and this month, Impresionist gem

I am using gem called impressionist to log page views on show action.
Everythink works just great.I can get number of all pageviews with:
#advertisement.impression_count
But now I want to be able filter pageviews per today, yesterday and this month.
So far I came up with this solution.
#today = Impression.where( :conditions => { :created_at => Date.today...Date.today+1 }, :impresionable_id =>#advertisement.id)
There is no errors.
Then In view:
<%= "#{#today} views so far!" %>
gives me #<Impression::ActiveRecord_Relation:0x000000068d46f8>
then I tried to add like : <%= "#{#today.impression_count} views so far!" %> gives me this :
undefined method `impression_count'
then I tried just :<%= "#{#today.count} views so far!" %> and still error:
Mysql2::Error: Unknown column 'conditions.created_at' in 'where clause': SELECT COUNT(*) FROM `impressions` WHERE (`conditions`.`created_at` >= '2014-12-18' AND `conditions`.`created_at` < '2014-12-19') AND `impressions`.`impresionable_id` = 127
Any ideas ?
Thanks in advance!
#today = Impression.where( :conditions => { :created_at => Date.today...Date.today+1 }, :impresionable_id =>#advertisement.id)
returns a #<Impression::ActiveRecord_Relation:0x000000068d46f8>.
Try this:
#today = Impression.where(created_at: Date.today...Date.today+1, impresionable_id: #advertisement.id).count
Add scopes in impression.rb
scope :today, -> {where("created_at >= ? AND created_at < ?", Time.now.beginning_of_day, Time.now.end_of_day)}
scope :yesterday, -> {where("created_at >= ? AND created_at < ?", 1.day.ago.beginning_of_day, 1.day.ago.end_of_day)}
scope :this_month, -> {where("created_at >= ? AND created_at < ?", Time.now.beginning_of_month, Time.now.end_of_month)}
in Controller:
#today = Impression.today.where(impresionable_id: #advertisement.id)
#yesterday = Impression.yesterday.where(impresionable_id: #advertisement.id)
#this_month = Impression.this_month.where(impresionable_id: #advertisement.id)
And you can use these scopes anywhere you need to filter Impressions by date today, yesterday or this month. It's better compared to writing the where clause everywhere.
There's no need for the conditions hash.
today = Date.today
range = today..today.next_day
#imp = Impression.where(created_at: range, impressionable_id: #advertisement.id)
And if an #advertisement can have impressions, then the following would be better:
#imp = #advertisement.impressions.where(created_at: range)
Then to get the count, you must:
#today = #imp.count
Also, just FYI, you might need to use DateTime.now instead of Date.today because you're comparing with a datetime field i.e. created_at.
It was easier than I though
In advertisement.rb
has_many :impressions, :as=>:impressionable
def view_count_yesterday
impressions.where("created_at >= ? AND created_at < ?", 1.day.ago.beginning_of_day, 1.day.ago.end_of_day).size
end
def view_count_today
impressions.where("created_at >= ? AND created_at < ?", Time.now.beginning_of_day, Time.now.end_of_day).size
# impressionist_count(:start_date => 1.day.ago)
end

Rails Date Query for setting Expiration

I'm creating a marketplace app where sellers can list items to sell. I want to set an expiry date so listings over 30 days old do not show on the site.
I found some similar examples online but can't get this query to work.
#listings = Listing.where('created_at <= ?', Date.created_at + 30.day)
You want to query items whose created_at time is >= the current date (Date.current) - 30 days (30.day). So the query should simply be:
#listings = Listing.where('created_at >= ?', Date.current - 30.day)
You can also replace Date.current with Time.now or DateTime.now.
UPDATE: as user3334690 mentioned in a comment, it's recommended that you make this a model method since it's something that should be in the Model layer:
# app/models/listing.rb
def self.not_expired
where('created_at >= ?', Date.current - 30.day)
end
# now in controllers you can do something like
#listings = Listing.not_expired

Get data from db relevant with today, yesterday, today -1.week, today -1.month

I have a object and a result table
Object has_many Results
Result belongs_to Object
Result has a column called kg.
I need to get for each object the kg data
where('DATE(created_at) = ?' Date.today AND Date.today - 1.day AND Date.today - 1.week AND Date.today - 1.month)
So my question is, which is my best option:
Get all the records for 1 month (date Between today and today - 1.month) and then get the result for today, yesterday, 1 week ago and 1 month ago)
today = result.where("DATE(created_at) BETWEEN ? AND ?", Date.today - 1.month, Date.today)
Or make 4 queries and get the data for each date?
today = result.where('DATE(created_at) = ?' Date.today)
y = result.where('DATE(created_at) = ?' Date.today - 1.day)
w = result.where('DATE(created_at) = ?' Date.today - 1.week)
m = result.where('DATE(created_at) = ?' Date.today - 1.month)
Depending on how you want to later use the results, it might make sense to query them individually using your second approach. That way, you don't have to further separate them in your resultset.
If you don't actually need the data you query in your first approach, it doesn't make sense to retrieve them from the database. You should then use another, more specific approach.
If your actual queries are more complicated that the one shown in the question or if you just want a single result set, it might make sense to use the following approach which just requires one query:
dates = [
Date.today,
Date.today - 1.day,
Date.today - 1.week,
Date.today - 1.month
]
resultset = Result.where('DATE(created_at) IN (?)', dates)
This query will result in a SQL query similar to this:
SELECT * from results WHERE DATE(created_at) IN ('2013-12-16', '2013-12-15', '2013-12-09', '2013-11-16');
You should be able to build an IN request.
result.where('DATE(created_at) IN (?)', [Date.today, Date.today - 1.day])
Which will retrieve the records which are in between the provided dates.

Rails Date compared to Date.today

I have a birth_date variable in the Date format. I want to compare it to Date.today as shown below. The problem is it is coming back false because it wants to compare the year as well. It is a birthday so I don't care about the year just trying to see if birth_date (month and day) is equal to Date.today.day.month.
Any ideas?
bdays = Soldier.find(:all, :conditions => ["birth_date LIKE ?", Date.today] )
You will need to break up your date, because you want to ignore the year. You will need to use some of the functions given by your SQL provider (the example below uses MySQL):
bdays = Soldier.find(:all, :conditions => ["DAY(birth_date) = ? AND MONTH(birth_date) = ?", Date.today.day, Date.today.month])
if you're using SQLite (rails' default database), it will be a bit more complicated because they don't have a real date type:
bdays = Soldier.find(:all, :conditions => ["STRFTIME('%d', birth_date) = ? AND STRFTIME('%m', birth_date) = ?", Date.today.day, Date.today.month])
Figured I would add postgres:
Soldier.where("EXTRACT(DAY FROM birth_date) = ? AND EXTRACT(MONTH FROM birth_date) = ?", Date.today.day, Date.today.month)

Resources