neezer
neezer

Reputation: 20570

Rails: Database records with custom route...?

I have a model, target, that holds a number of records that are timestamped. On the corresponding controller, I list the months of those records by doing the following:

In models/target.rb

def month
   self.recorded_on.strftime('%B')
end

In controllers/targets_controller.rb

@records = Target.find :all

In views/targets/index.html.haml

%ul
  - @records.group_by(&:month).sort.each do |month, data|
    %li= link_to month, ''

That all works great for listing the available months for the records that I have. Next, I want to be able to click on the month and get a report of all the records for that month, at the following path generated with year and the month: /targets/2009/04

How would I do this?

Upvotes: 0

Views: 868

Answers (1)

John Topley
John Topley

Reputation: 115372

Add some named scopes to your Target model to support finding by year and by month number. Something like:

class Target < ActiveRecord::Base
  named_scope :by_month,
    lambda { |month| { :conditions => ['MONTH(recorded_on) = ?',
                        month] }}

  named_scope :by_year,
    lambda { |year| { :conditions => ['YEAR(recorded_on) = ?', year] }} 
  .
  .
  .
end

(Note that the conditions here are using MySQL syntax.)

Assuming you're using RESTful routes, set up a named route like the one below in your config/routes.rb file (make sure it's declared before the default route):

map.targets_by_month '/targets/:year/:month', :controller => 'targets',
                :requirements => { :year => /\d{4}/, :month => /\d{1,2}/ },
                :conditions => { :method => :get }

—You can use this route in your view like this:

<%= link_to 'Show April 2009 Targets', targets_by_month_path('2009', '04') %>

(Note that the leading zero for the month is optional because of the :requirements regular expression in the named route defined above)

Finally, in your TargetsController, set up the index action to use the named_scopes defined earlier:

def index
  @records = Target.by_year(params[:year]).by_month(params[:month])
  .
  .
  .
end

Upvotes: 2

Related Questions