routes snippets

How to install the exception_logger Rails plugin and protect the logs with basic authentication

Tagged ruby, exception_logger, install, routes, rails, basic, authentication  Languages ruby

This snippet explains how to install and use the Rails exception_logger plugin. I'll also show you how to protect your logs by extending the plugin with basic authentication.

script/plugin source http://svn.techno-weenie.net/projects/plugins
script/plugin install exception_logger

I'm using Rails Edge on this project, so I had to install classic pagination also:

script/plugin install svn://errtheblog.com/svn/plugins/classic_pagination

Next create and execute the migration file:

./script/generate exception_migration
rake db:migrate

Before starting the server we need to setup the routes:

map.exceptions '/logged_exceptions/:action/:id', :controller => 'logged_exceptions', :action => 'index', :id => nil

You also need to include the ExceptionLoggable in your ApplicationController:

class ApplicationController < ActionController::Base
  include ExceptionLoggable
...

Start your server and access the exception log at /logged_exceptions.

Exceptions can contain email addresses, passwords, credit card numbers, so you'll want to protect /logged_exceptions from the public. This can be done by adding the following code to the end of environment.rb:

config.after_initialize do
  require 'application' unless Object.const_defined?(:ApplicationController)
  LoggedExceptionsController.class_eval do
    before_filter :authenticate

    protected

    def authenticate
      authenticate_or_request_with_http_basic do |username, password|
        username == "foo" && password == "bar"
      end
    end
  end
end

With this code we add a before filter that shows a login dialog to anyone trying to access /logged_exception/. Note that this requires Rails 2.0 basic authentication to work, so make sure you have the proper version installed.

How to SEO optimize your Rails URLs and routes

Tagged seo, rails, routes, permalink, crawlability  Languages ruby

My idea for achieving optimal content crawlability and SEO optimized URLs is to use permalinks instead of ids and the default Rails routes. The permalinks can contain whatever you decide is optimal from a SEO point of view.

As an example, let's take a recipe site that has a recipe at http://xxx/recipes/asia/china/beijing-duck.html.

First let's configure the .html extension to be handled by the RecipesController:

map.connect 'recipes/*permalink.html', :controller => 'recipes', :action => 'show'

In the code we use the URI, which is the permalink of the recipe, to retrieve the recipe from the database:

class RecipesController
  def show
    @product = Recipe.find_by_permalink(request.path)
  end
end

To handle the categories and subcategories, we use the following route:

map.connect 'recipes/*permalink/', :controller => 'categories', :action => 'show'

And create the CategoriesController:

class CategoriesController
  def show
    @category = Category.find_by_permalink(request.path)
  end
end

Now what's left is for you to figure out how to generate the permalinks... I recommend having a look at permalink_fu.

How to test Rails routing with RSpec

Tagged testing, rspec, routing, routes  Languages ruby
route_for(:controller => 'categories', :action => 'show', :permalink => ['one', 'two', 'three']).should.equal '/one/two/three'
route_for(:controller => 'categories', :action => 'index').should.equal '/'
      
params_from(:get, "/").should.equal {:controller => "categories", :action => "index"}
params_from(:get, "/something/").should.equal {:controller => "categories", :action => "show", :permalink => ["something"]}

The test_spec_on_rails plugin also allow you to test routing and much more, see the docs for more information.

How to generate URLs in your Rails model

Tagged to_uri, uri, routes, model  Languages ruby

You can use helpers in your model by first including them:

class Post < ActiveRecord::Base
  include ActionController::UrlWriter
  def to_uri
     post_path(self)
  end
end

Some might consider this heresy, I don't. In my opinion it's similar to the to_param method. You could of course move it to a delegate class or something similar.

Localizing URLs and Rails3 routes

Tagged i18n, routes, rails3, url, seo  Languages ruby

If you need to support localized URLs in a Rails application, you have at least two plugins to choose from: * i18n_routing NOTE: doesn't seem to work with Rails 3.2.8 * rails-translate-routes

I recommend the rails-translate-routes plugin because it allows me to create exactly the URLs I need.

For example, if these are the localized URLs I need:

http://xxx.com/news
http://yyy.com/uutiset
http://zzz.com/nyheter

How to render a view or partial from a Rake task, model or anywhere

Tagged actionview, render, rake, view, rails, routes  Languages ruby

This is tested with Rails 3.0.7 and will most likely change in future versions of Rails:

# @newsletter in the view file
assigns = { :newsletter => self }

routes = Rails::Application.routes # Rails => YourApp
routes.default_url_options = { :host => 'xxx.com' }

av = ActionView::Base.new(Rails::Application::Configuration.new(Rails.root).paths.app.views.first, assigns)
av.class_eval do
  include ApplicationHelper
  include routes.url_helpers
end

self.html = av.render :template => 'newsletters/show'

After some experimentation I ended up with this code:

class RenderHelper
  class << self
    def render(assigns, options, request = {})
      request = { 
        "SERVER_PROTOCOL" => "http", 
        "REQUEST_URI" => "/",
        "SERVER_NAME" => "localhost", 
        "SERVER_PORT" => 80
      }.merge(request)

      av = ActionView::Base.new(ActionController::Base.view_paths, assigns)
      
      av.config = Rails.application.config.action_controller
      av.extend ApplicationController._helpers
      av.controller = ActionController::Base.new
      av.controller.request = ActionController::Request.new(request)
      av.controller.response = ActionController::Response.new
      av.controller.headers = Rack::Utils::HeaderHash.new

      av.class_eval do
        include Rails.application.routes.url_helpers
      end

      av.render options 
    end
  end
end

And this is how I use it:

RenderHelper.render(:newsletter => self, :template => 'mailchimp/daily')