Finding records made 1 month ago - ruby-on-rails

I'm using a named scope to try and find records made 1 month ago, here's the code I have:
scope :six, -> {:conditions["records.created_at > ?", 1.month.ago]}
And the call:
#sixmonths = human.human_logins.six
Though I seem to be getting the following error:
`can't convert ActiveSupport::TimeWithZone into Intege`r
This is occurring on the scope line.
I'm new to scopes so not sure how I should go about this, any ideas would be awesome.

I am not familiar with :conditions method, but the syntax, :conditions[] and the exception suggests that it is trying to evaluate the expression as an Array.
If you want only records created exactly 1 month ago, use the following:
scope :six, -> { where(created_at: 1.month.ago) }
If you want records created more than a month ago (which your query syntax suggests), use:
scope :six, -> { where('created_at < ?', 1.month.ago) }

Related

rails joins query over has_many objects independently

I have parent model Project & children model ToDo.
A project has many ToDos with column starts_at & ends_at.
I would like to search for projects that have 'any' todos in the time range.
Here I wrote some codes, however, it is not as expected.
class Project
has_many :todos
scope :active, -> {joins(:todos).where("todos.starts_at < '#{Time.now}' AND todos.ends_at > '#{Time.now}'").distinct}
scope :waiting, -> {joins(:todos).where.not("todos.starts_at < '#{Time.now}' AND todos.ends_at > '#{Time.now}'").distinct}
scope :done, -> {where("project_due > ?", Time.now)}
end
Active one seems right, but waiting scope also contains the projects that have more than one todos.
I wonder if there any solution to compare starts_at & ends_at per each todo. Not like above.
Thanks ahead.
*# Update *
This is what I wanna achieve. but in one query.
scope :waiting, -> { joins(:todos).where.not(id: active.ids).where('finishing > ?', Time.now).distinct }
Try to the following
Update
For waiting you mean starts_at greater than NOW right? then it will be
scope :waiting, -> {joins(:todos).where("todos.starts_at >= ?", Time.now).distinct}
If the match with the first condition then you don't need to match the second condition, you can write with the second condition like this
scope :waiting, -> {joins(:todos).where("todos.starts_at > '#{Time.now}' AND todos.ends_at > '#{Time.now}'").distinct}
but don't need.
Update 2
Remove the not from where, here not means active
scope :waiting, -> {joins(:todos).where("todos.starts_at >= ?", Time.now).distinct}
Update 3 after Update 2 worked
scope :waiting, -> {joins(:todos).where("todos.starts_at >= ?", Time.now).distinct}
scope :finished, -> {where("finishing > ?", Time.now).distinct}
scope :waiting_n_progress, -> {where.not(id: active.ids).finished.waiting}
the waiting_n_progress scope, I think you will get your goal, remember that's not tested.
Hope it should work.
Your query for waiting basically translate from !(start < now && end > now) to this start >= now || end <= now which would most likely return a lot more projects than you wanted. See if that is the logic that you wanted.
Also, for best Rails practices, you should write query like the user fool-dev suggested in the other answer using question mark. This is to prevent SQL injection as explained in more details here
EDIT
So I think you mean waiting means projects that does not have any Todo or those that have awaiting Todo (start_at > now). I think this should work:
scope(:waiting) { includes(:todos).where('todos.project_id IS NULL OR todos.start_at > ?', Time.now).distinct }
The first part is to select projects that doesn't have any Todo and the second part is self explanatory.

RAILS : how to define scope with date range from column values?

I am trying to create a named scope in which I would like to receive records which are only updated within the first week after they are created.
As you can see I receive an error message for the column name created_at.
scope :shortlived, where("updated_at < ?", (created_at+7.days))
undefined local variable or method `created_at' for #<Class:0xb184725c>
I will appreciate if you can inform me what might be the problem.
You could use something database specific. For example for MySQL:
scope :shortlived, -> { where('updated_at < created_at + interval 3 day') }
this is similar to the answers posted here. if you're using postgreSQL, you can just compare the difference with '7 days' interval
scope :shortlived, -> { where("(updated_at - created_at) < '7 days'") }

Rails scope filter by date range

There are many questions relate to rails date range problem but mine is a little more complicated.
I have two models: house and booking. A House has_many bookings. A Booking has two attributes in date format: check_in and check_out.
What I want to achieve: Giving a valid date range, show all houses that are available during this range. In detail:
The start date of the range should not be in any booking.
The end date of the range should not be in any booking.
There should not be any booking between the start and the end.
Can this be done using the rails scope?
UPDATE:
I found the code below that can check scope date interval that overlaps.
named_scope :overlapping, lambda { |interval| {
:conditions => ["id <> ? AND (DATEDIFF(start_date, ?) * DATEDIFF(?, end_date)) >= 0", interval.id, interval.end_date, interval.start_date]
}}
How can I transfer this to my problem?
scope :overlapping, (lambda do |start_date, end_date|
House.includes(:bookings).where("bookings.check_in < ? AND bookings.check_out > ?",
start_date, end_date).references(:bookings).uniq
end)
I went ahead and deleted the >= and <= operators in favor of > and < to explicitly show these bookings being outside of the given range, but you can adjust them per your needs!
Update
Changed query to use #includes instead of #joins, since we're querying the attached table.
Yes it is possible to have this query through scope. Put this scope in house model.
scope :overlapping, -> (start_date, end_date) {
includes(:bookings).where('bookings.check_in < ? AND bookings.check_out > ?',
start_date.to_date, end_date.to_date)
}
And call as House.overlapping('2015-07-01', '2015-07-09')

Ambiguous table reference

This problem seems fairly simple, but I've never encountered one like this.
Here are the settings:
Post has_many :reader_links
Post has_many :readers, :through => :reader_links
I need to find out if there are readers reading a post.
#post.reader_links.where('created_at >= ?', 45.minutes.ago).any?
Works great.
#post.readers.where('created_at >= ?', 45.minutes.ago),any?
throws an ambiguous table column error because it's confused whether the created_at column means that of reader object or reader_link object. This happens because the class of a reader is actually User. How do I query readers who were created by reader_links 45 minutes ago?
I'm looking for something like..
#post.readers.where('reader_link.created_at >= ?', 45.minutes.ago)
If I get it right, you just need to specify which created_at column you're talking about:
#post.readers.where('reader_links.created_at >= ?', 45.minutes.ago).any?
You coul merge the scopes to get rid of ambigious errors, so each scope has it's own visibility range.
using meta_where:
Post.scoped & (ReaderLink.scoped & User.where(:created_at.gt => 45.minutes.ago))
without meta_where:
Post.scoped.merge(ReaderLink.scoped.merge(User.where('created_at >= ?', 45.minutes.ago))
This will result in arrays of Post objects containing the reader_links and readers data for all readers younger than 45 minutes. Please try it in the rails console.
Edit: for a single post
post_with_fresh_users = Post.where('id = ?', some_id).merge(ReaderLink.scoped.merge(User.where('created_at >= ?', 45.minutes.ago))
Edit: all fresh readers of a post (different order)
fresh_readers_for_post = User.where('created_at >= ?', 45.minutes.ago).merge(ReaderLink.scoped.merge(Post.where('id = ?', #post.id))
How it works:
http://benhoskin.gs/2012/07/04/arel-merge-a-hidden-gem

Get records where date.year == some_year in Rails

I have a date column in my database in a Rails 3.1 app, and I want to be able to get the records where the date's year matches a specific year.
I tried where(:date.year == year) but of course I got NoMethodError: undefined method 'year' for :date:Symbol. Is it possible to do this type of query?
You can use a scope to build something like:
scope :for_year, lambda {|date| where("date >= ? and date <= ?", "#{date.year}0101", "#{date.year}1231")}
In your Model:
scope :by_year, lambda { |year| where('extract(year from created_at) = ?', year) }
In your Controller:
#courses = Course.by_year(params[:year])
Jesse gave you, I think, the idea for the actual solution, but to explain why this failed - it's because it tried to evaluate ".year" as a method on the symbol you passed it: ":date".
The word :date is just a parameter to tell "where" which value it will later use to construct the SQL query to pass to the db.
It doesn't turn into the actual date of the record. But the ".year" will evaluate as you're passing it as a parameter, before anything has been done with the ":date" symbol.
Assuming your date format is: YYYY-MM-DD HH:MM:SS
Try this:
where(Date.strptime(:date, "%Y-%m-%d %H:%M:%S").year == year)
OR
where(["YEAR(?) = ?", :date, year])

Resources