Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save joshuaflanagan/2223161 to your computer and use it in GitHub Desktop.
Save joshuaflanagan/2223161 to your computer and use it in GitHub Desktop.
SmartUrlHelper - configurable replacement for url_for. See http://lostechies.com/joshuaflanagan/2012/03/27/a-smarter-rails-url_for-helper/
SmartUrlHelper.configure do |url|
url.for ->model{ model.is_a?(Comment) } do |helpers, model|
helpers.post_comment_path(model.post, model)
end
# TODO: Add a convenience method for matching on type:
# url.for(Comment) do |helpers, model|
# helpers.post_comment_path(model.post, model)
# end
end
module SmartUrlHelper
# A smarter replacement for #url_for. First checks to see if a
# special-case handler has been registered for the given model. If so,
# use that to generate the URL. If not, fall back to Rails' #url_for helper.
# Special-case handlers should be registered in a config/initializer that
# calls SmartUrlHelper.configure.
#
# Returns the default URL for the given model.
def smart_url_for(model, *args)
url = ::SmartUrlHelper::SmartUrlConfiguration.lookup_smart_url(self, model, *args)
return url if url.present?
url_for(model, *args)
end
# Call in config/initializer to register model handlers.
# Takes a block for an instance of SmartUlrConfiguration.
def self.configure
Rails.application.config.smart_url_handlers = []
yield ::SmartUrlHelper::SmartUrlConfiguration.new
end
# Provides the DSL for registering model handlers in SmartUrlHelper.configure
class SmartUrlConfiguration
# Registers a handler to generate a URL for a model that matches the predicate
#
# predicate - A lambda that takes in a model instance and returns true
# if the handler can generate a URL for the given model.
# url_generator - A block that builds a url for the given model.
# The block will receive a helper object and the model
# as parameters.
def for(predicate, &url_generator)
self.class.handlers << [predicate, url_generator]
end
def self.handlers
Rails.application.config.smart_url_handlers
end
def self.lookup_smart_url(context, model, *args)
handler = self.handlers.detect{|h| h[0].call(model)}
return nil unless handler.present?
handler[1].call(context, model)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment