To pass params in a GET request that are not a part of the path in Rails (and in general) you use the query string:
/photos?page=2&foo=bar
One of the simplest ways to add query parameters is by passing a hash to the link helper:
link_to( "More photos", photos_path(page: 2, foo: 'bar') )
To query for records in a certain span of time you would use .where
with a range:
@this_week = Photo.where(created_at: [Date.today.beginning_of_week..Time.now])
# SELECT "photos".* FROM "photos"
# WHERE ( "photos"."created_at" BETWEEN '2016-05-22' AND '2016-05-26 07:43:49.331188')
While you could pass times like so:
link_to( "More photos", photos_path(from: Date.today.beginning_of_week, to: Time.now) )
Its not very efficient from a caching point of view since it requires the view to be rendered for each request.
Instead you might want to have a set of keywords.
Lets setup a class that gives us a range from keywords:
# lib/time_range.rb
class TimeRange < Range
KEYWORDS = [:today, :yesterday, :this_week,
:last_week, :this_month, :last_month,
:this_year, :last_year]
# @param [Symbol] keyword such as :today, :yesterday :this_week, :last_week ...
def initalize(keyword)
keyword = keyword.to_sym
# the * (splat) operator turns the array into a list of arguments
super( *from_beginning_to_end(base_time(keyword), unit_of_time(keyword)) )
end
self.valid?(keyword)
KEYWORDS.include?(keyword.to_sym)
end
private
# strips this_ or last_ from the keyword
def unit_of_time(keyword)
[:today, :yesterday].include?(keyword) ? 'day' : keyword[5..-1]
end
def base_time(keyword)
if keyword == :yesterday || keyword.to_s.starts_with? 'last_'
DateTime.now.send(keyword)
else
DateTime.now
end
end
# creates an array by dynamically calling for example
# `beginning_of_week` and `beginning_of_week` on the base time.
def from_beginning_to_end(base, unit)
[
base.send("beginning_of_#{unit}"),
base.send("end_of_#{unit}"),
]
end
end
Now you can do:
link_to 'Todays photos', photos_path( keyword: 'today' )
link_to 'Last years photos', photos_path( keyword: 'last_year' )
@photos = Photo.all
@photos = @photos.where(
created_at: TimeRange.new(params[:keyword])
) if TimeRange.valid?(params[:keyword])
chaining scopes.
In active record you can chain scopes together:
Photo.all.where(foo: 'bar').where(baz: 3)
You can use that together with params to build a set of filters:
@photos = Photo.all
if params[:orientation]
if params[:orientation] == 'landscape'
@photos = @photos.landscape
else if params[:orientation] == 'p'
@photos = @photos.portrait
end
end
Etc - can get a bit messy if you have a lot of filter. So don't be afraid to create scopes in your models.