Posts Tagged ‘rails routing’

blog archive helper

# ------------------------------------------
#                 routes.rb
# ------------------------------------------

# show posts by date
map.connect ':year/:month/:day',
  :controller => 'posts',
  :action => 'index',
  :year => /\d{4}/,
  :month => /\d{1,2}/,
  :day => /\d{1,2}/

# show posts by month
map.connect ':year/:month',
  :controller => 'posts',
  :action => 'index',
  :year => /\d{4}/,
  :month => /\d{1,2}/

# ------------------------------------------
#            post_controller.rb
# ------------------------------------------

def index
  if params[:year] && params[:month]
    datestring = "#{params[:year]}-#{params[:month]}"
    datestring << "-#{params[:day]}" if params[:day]
      @posts = Post.find_all_by_date_like(datestring)
    else
      @posts = Post.find(:all)
    end

    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @posts }
      format.atom
    end
  end
end

# ------------------------------------------
#          post.rb
# ------------------------------------------

class Post < ActiveRecord::Base
  class << self
    def find_all_by_date_like(datestring)
      self.find(:all, :conditions => ['created_at LIKE ?', datestring + '%'])
    end
  end
  #...
end

# ------------------------------------------
#          application_helper.rb
# ------------------------------------------

MONTHS =
  [
    'January', 'February', 'March', 'April', 'May', 'June',
    'July', 'August', 'September', 'October', 'Novemeber', 'December'
  ]

def archive_content(posts)
  raise ArgumentError unless block_given?
  with_unique_dates_from_resource posts do |year, month|
    link_name = "#{MONTHS[month.to_i - 1]} #{year}"
    yield(link_to(link_name, "/#{year}/#{month}"))
  end
end

def with_unique_dates_from_resource(resource, timestamp = :created_at, find_options = {})
  if resource.is_a?(Array)
    collection = resource
  else
    proxy = resource.to_s.singularize.camelcase.constantize
    collection = proxy.find(:all, find_options)
  end
  collection.map do |model|
    model.send(timestamp).strftime("%Y/%m")
  end.uniq.each do |date|
    dates = date.split('/')
    yield(*dates)
  end
end

# ------------------------------------------
#               in some view
# ------------------------------------------

<% archive_content :posts do |archive_link| %>
  • <%= archive_link %>
  • <% end %> # or <% archive_content Post.find(:all) do |archive_link| %>
  • <%= archive_link %>
  • <% end %>