Antony Sastre
Antony Sastre

Reputation: 617

RESTful Archiving in Rails

I have a blog function in my rails app. Currently I only have 4 bloggers on the site and have a (pretty unsatisfied) way of routing them like this:

map.scarlet '/scarlet.:format', :controller => 'blogs', :action => 'show', :id => 'scarlet'
map.alba '/andreasweinas.:format', :controller => 'blogs', :action => 'show', :id => 'alba'

So that they are nicely accessible by typing: mysuperwebsite.com/scarlet

Now I would like to provide archives for the blogs accessible like so:

mysuperwebsite.com/scarlet/2009 - shows all entries from 2009

mysuperwebsite.com/scarlet/2009/06 - shows all entries from june 2009

Would anyone recommend how to a) improve my blog routing having in mind that in the future I'll have far more bloggers, and b) how to route for the archives without breaking the paths? I'm thinking an archives controller?

Models:

# Blog.rb
class Blog < ActiveRecord::Base
  has_many :entries, :dependent => :destroy
  belongs_to :user
end

class Entry < ActiveRecord::Base
   named_scope :published, :conditions => ["published_at < ?", Time.zone.now], :order => 'published_at DESC' 
   belongs_to :blog
end

Blog Controller:

 def show
    @blog = Blog.find_by_slug(params[:id])
    @entries = @blog.entries.published, :order => 'published_at DESC'

    respond_to do |format|
      format.html # show.html.erb
      format.xml  { render :xml => @blog.entries }
      format.rss
    end
  end 

Upvotes: 1

Views: 264

Answers (1)

bstiles
bstiles

Reputation: 31

This is untested, but should be very close. Not the DRYest solution, but you can refactor it. This will make the date filter work AND allow you have new blogs and support the existing routes. Enjoy

routes.rb

#(you don't need the .format) bit
# (if you have other routes, like /help, you need to have them before these, since these match /*, /\*/\*, and /\*/\*/\*

map.blogs '/:id/:year/:month', :controller => 'blogs', :action => 'show'
map.blogs '/:id/:year', :controller => 'blogs', :action => 'show'
map.blogs '/:id.:format', :controller => 'blogs', :action => 'show'

Blogs controller:

def show
    @blog = Blog.find_by_slug(params[:id])

   if (params[:year])
       if (!params[:month])
           date_begin = Date.new(params[:year],1,1)
           date_end = Date.new(params[:year],12,31)
           date_end = Time.zone.now if date_end < Time.zone.now  # to prevent grabbing future posts
           @entries = Entries.find(:conditions => [blog => @blog, :published_at => date_begin..date_end ],
              :order => 'published_at DESC'
       else
           date_begin = Date.new(params[:year],params[:month],1)
           date_end   = date_being.end_of_month
           date_end = Time.zone.now if date_end < Time.zone.now  # to prevent grabbing future posts
           @entries = Entries.find(:conditions => [blog => @blog, :published_at => date_begin..date_end ],
              :order => 'published_at DESC'
       end
    else
        @blog.entries.published, :order => 'published_at DESC'
    end

    respond_to do |format|
      format.html # show.html.erb
      format.xml  { render :xml => @entries }         # I changed this too
      format.rss
    end
  end

Upvotes: 1

Related Questions