Exclude records before a certain date - ruby-on-rails

I cannot seem to get the syntax correct on this. What I need to is grab all records after Feb 18 2021.
I feel like I have tried a million things so far but this is what I have at the moment which isn't working.
#exclusion_date = Date.parse('2021-02-18 00:00:01')
#surveys = Survey.closed.where('survey_type = ? AND created_at < ?','individual', #exclusion_date).order(created_at: :desc)
This still returns the exact same data as it did before I tried to exclude the older records.

You want to load records created after a specific time. That means the timestamp must be greater than the specific date. This should work:
#exclusion_date = Time.parse('2021-02-18 00:00:01')
#surveys = Survey
.closed
.where('survey_type = ? AND created_at > ?', 'individual', #exclusion_date)
.order(created_at: :desc)

In newer versions of Rails you can do this with a clever syntactic sugar using infinite ranges #exclusion_date..., meaning all possible future dates.
#exclusion_date = Time.parse('2021-02-18 00:00:01')
#surveys = Survey
.closed
.where(survey_type: 'individual')
.where(created_at: #exclusion_date...)

Related

how can I paginate records not by N value quantity, but by created_at.day?

I have a table Post.
Columns: created_at, title, body
Default pagination behaviour is to show n items per page and than add link_to prev/next.
How can I paginate not by n items, but by created_on a date?
I've figured out the gem https://github.com/ankane/groupdate, but it only helps to group, not to do the pagination.
In this case, it sound like you don't want pagination, you want query filtering based on a bucketed value. You will first need a distinct list of post days. You may need to use some database-specific query features to get that from timestamps. For example, with Postgres, you can use the date() function to extract just the date portion from your created_at timestamp, and we can get a distinct list of them:
dates = Post.pluck("distinct date(created_at)").sort
Note that this will induce a full table scan, so it'll be slow for a large number of posts.
How you use that list of dates is up to you. You might choose to render a list of them as links for the user to click, for example. You might then have your index method accept a date param, then use that to find posts on that date:
def index
scope = Post.all
if params[:date].present?
date = DateTime.parse(params[:date])
scope = scope.
where("created_at >= ? AND created_at <= ?",
date.beginning_of_day, date.end_of_day).
order("created_at ASC")
end
# For the given date, paginate the posts on that date in pages of 25
#posts = scope.page(1).per(25)
end

Ruby on Rails with sqlite, trying to query and return results from the last 7 days?

Noob here, I'm trying to query my SQLite database for entries that have been made in the last 7 days and then return them.
This is the current attempt
user.rb
def featuredfeed
#x = []
#s = []
Recipe.all.each do |y|
#x << "SELECT id FROM recipes WHERE id = #{y.id} AND created_at > datetime('now','-7 days')"
end
Recipe.all.each do |d|
#t = "SELECT id FROM recipes where id = #{d.id}"
#x.each do |p|
if #t = p
#s << d
end
end
end
#s
end
This code returns each recipe 6(total number of objects in the DB) times regardless of how old it is.
#x should only be 3 id's
#x = [13,15,16]
if i run
SELECT id FROM recipes WHERE id = 13 AND created_at > datetime('now','-7 days')
1 Rows returned with id 13 is returned
but if look for an id that is more than 7 days old such as 12
SELECT id FROM recipes WHERE id = 12 AND created_at > datetime('now','-7 days')
0 Rows returned
I'm probably over complicating this but I've spent way too long on it at this point.
the return type has to be Recipe.
To return objects created within last 7 days just use where clause:
Recipe.where('created_at >= ?', 1.week.ago)
Check out docs for more info on querying db.
Edit according to comments:
Since you are using acts_as_votable gem, add the votes caching, so that filtering by votes score is straightforward:
Recipe.where('cached_votes_total >= ?', 10)
Ruby is expressive. I would take the opportunity to use a scope. With Active Record Scopes, this query can be represented in a meaningful way within your code, using syntactic sugar.
scope :from_recent_week, -> { where('created_at >= ?', Time.zone.now - 1.week) }
This allows you to chain your scoped query and enhance readability:
Recipe.from_recent_week.each do
something_more_meaningful_than_a_SQL_query
end
It looks to me that your problem is database abstraction, something Rails does for you. If you are looking for a function that returns the three ids you indicate, I think you would want to do this:
#x = Recipe.from_recent_week.map(&:id)
No need for any of the other fluff, no declarations necessary. I also would encourage you to use a different variable name instead of #x. Please use something more like:
#ids_from_recent_week = Recipe.from_recent_week.map(&:id)

Search records between two dates - Ruby on Rails

I am trying to create a search that returns records between two dates (today and a future date).
I can get it to return several records no problem if I use the following code in my model (film.rb):
def self.date_search(search_string)
self.where("release_date >= ?", search_string )
However, when I try something like the following, I receive syntax errors:
def self.date_search(search_string)
date = Date.today
self.where("release_date = created_at > date.strftime("%F") AND created_at < ? ", search_string )
I am still very new to Ruby so any help sorting out my syntax and code would be much appreciated.
Try:
def self.date_search(search_string)
self.where({release_date: Time.now..search_string})
end
This will give you entries where release_date is between the current time and the search_string (inclusive of the search string since you use two dots(..), it would be exclusive of the search string if you used three dots (...)

How do I get the first row in a record after ordering it? Ruby On Rails

I am working with Ruby on Rails.
I make a query to the model, but I want to get the one register that has the highest value for the average attribute. This is my code:
#dish = Dish.where("day = ? and week = ?", params[:day], params[:week])
#dish.order(:average)
#sug = #dish.first
#sug gets the record with the lowest id, no the one with the highest average.
I have also tried it this way:
#sug = #dish.order(:average).limit(1)
but it's not working either. How can I get that one register?
You need to chain the calls like follows.
#dish.order(:average).first
The call to .order does not change the #dish instance, so when you call #dish.first the ordering no longer is there.
#dish.order does not order already found dishes, it changes the query to include an order clause.
#dish = Dish.where("day = ? and week = ?", params[:day], params[:week]).order(:average) would do what you wanted, and so would
#dish = Dish.where("day = ? and week = ?", params[:day], params[:week])
#dish = #dish.order(:average)
#sug = #dish.first
The ActiveRecord::QueryMethods#order method sorts in ascending order by default, so try explicitly asking for a descending order, then taking the first:
Dish.order(average: :desc)
.where("day = ? and week = ?", params[:day], params[:week])
.first
This assumes your average attribute is stored in the database, and not computed.

Ordering Records with Same Date Using Second Field

I have an application with many Galleries. Each gallery has a start_date DateTime field.
For legacy reasons, the time of all start_dates is midnight.
Thu, 10 Jul 2014 00:00:00 UTC +00:00
I need to order the galleries by date, so a user can shuffle back and forth across them using a 'older' and 'newer' link. Galleries are ordered based on start_date:
scope :start_date_ascending, -> { order(start_date: :asc) }
scope :start_date_descending, -> { order(start_date: :desc) }
My problem is that there is no clear older or newer gallery when there are multiple galleries with the same date. In such cases I cannot predict the order that Galleries with the same date are returned in, so moving across multiple galleries with the same date becomes random and error-prone.
I have scope set up to find newer and older galleries:
scope :newer_than, -> (gallery){ where.not(id:gallery).where('start_date >= :gallery_start_date', gallery_start_date:gallery.start_date) }
scope :older_than, -> (gallery){ where.not(id:gallery).where('start_date < :gallery_start_date', gallery_start_date:gallery.start_date) }
And I find the next and previous galleries like this:
def self.next_newer(gallery)
Gallery.newer_than(gallery).start_date_ascending.limit(1).first
end
def self.next_older(gallery)
Gallery.older_than(gallery).start_date_descending.limit(1).first
end
So it seems to me I need a secondary way to order the galleries that are the same date. It doesn't matter what order that is - it could simply be their ids.
How can I handle this situation so that galleries with the same date appear in the query in a predictable, fixed order so that next_newer and next_older move through them?
Perhaps you can sort with a second criteria, name for example and if available, or even id
scope :start_date_ascending, -> { order(start_date: :asc, name: :asc) }
scope :start_date_descending, -> { order(start_date: :desc, name: :asc) }
note on the start_date_descending scope it can be nice to keep name asc, so despite of the descending date order we keep a alphabetical order
And for the next and previous gallery, if you can store an array, you can get your ordered ids and iterate through them
ids = Gallery.start_date_ascending.pluck :id
Based on #BengaminSinclaire's suggestion:
def self.next_newer(gallery)
ascending_ids = Gallery.start_date_ascending.pluck :id
current_index = ascending_ids.index(gallery.id)
Gallery.find(ascending_ids[current_index+1]) if current_index < ascending_ids.length - 1
end
def self.next_older(gallery)
ascending_ids = Gallery.start_date_ascending.pluck :id
current_index = ascending_ids.index(gallery.id)
Gallery.find(ascending_ids[current_index-1]) if current_index > 0
end

Resources