Overriding url_for for Fun and Profit
Published 2005-12-02 @ 13:38
Tagged rails
(guest authored by eric hodel)
A while back I was thinking about MVC and how URLs are built and came to the conclusion that every model should know what its URL is. I don’t think it is the responsibility of the Controller to know this, and certainly not the view.
Since Rails uses a Hash to represent a URL, I thought it would be easy to just add a method to every Model that would return a Hash representation of the URL and override url_for to perform the expansion from a model into its URL Hash.
It turns out that it was easy. After some enhancements by Ryan that adds defaults we came up with the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
class ApplicationController < ActionController::Base def url_for(options = {}, *params) if options.include? :model then model = options.delete(:model) defaults = { :action => 'show', :id => model.id, :controller => model.class.name.downcase, } defaults = defaults.merge model.url_params if model.respond_to? :url_params options.delete :only_path if defaults.include? :only_path options = defaults.merge options end return super(options, *params) end end |
You can use the modified url_for like this:
1 2 3 4 5 |
@model = Model.find some_id url_for :model => @model url_for :model => @model, :action => 'edit' redirect_to :model => @model link_to @model.name, :model => @model |
Sometimes the defaults aren’t good enough though. To override them you add a url_params method to your model. In Trackmap (now dead) I store enough information about a flickr photo to generate its flickr URL in the database and my url_for modification (with a bit of cheating) makes this very clean: