[Rails] Avoid parsing URL in Apache conf?
Marten Veldthuis
marten at standardbehaviour.com
Sat Nov 20 20:10:25 GMT 2004
David Heinemeier Hansson wrote:
> We are. It was one of the first wishes to make it on the list:
> http://www.rubyonrails.org/show/DispatcherRewritingWish
I've discussed an approach with David shortly on IRC, and promised to
put up a full example. So here it is:
# Suggestion for a Rails Rewriting Engine.
# By Marten Veldthuis, 20041120
def rewrite
# Given a raw url /path/to/somewhere, url.<name> compares from the
# start of the currently remaining url (less a "/" prefix if it
# exists), and if it matches:
#
# * it sets @params[<name>] to the matched string unless the second
# argument +dont_set_param+ to the call url.<name> is +true+.
# Second argument defaults to false.
# * removes the matched string from the remaining url
# * executes the given block, passing the MatchData
url.section_name(/([-_a-zA-Z0-9]+)/) do |match|
# (match contains an instance of MatchData)
# In this case, my requirement is to match a given section name
# to it's type. For instance, some section may be called "weblog"
# and be of the "journal" type, but another could be "see-also",
# and of the "links" type. So to find out what controller to use
# I must either pre-define all possible names and their types
# (which is what I do now by writing a .htaccess automatically),
# or I could look up the section here.
#
# I can fully understand if David finds this too smelly to allow it
# in Rails.
# @active_section would be passed into the controller#action (and
# later the view) just like passing instance vars from action to
# view.
@active_section = Section.find_by_name(match[0])
# This sets what controller to use. Eg. <tt>vendor_journal</tt> or
# <tt>vendor_links</tt>. Action
@controller = "vendor_" + @active_section.type
@action = "index"
url.year(/\d{4}/) do
# If a year is given, we want to display the archive instead. So,
# we override the action.
@action = "archive_year"
url.month(/\d{1,2}/) do
@action = "archive_month"
url.day(/\d{1,2}/) do
@action = "archive_day"
url.entry_name(/([-_a-zA-Z0-9]+)/) do
@action = "archive_entry"
end
end
end
end
end
# This is reachable only if the outmost match (url.section_name)
# failed. Ofcourse, the same applies to any url.<name> call.
url.admin(/admin/, false) do
url.section(/sections\/([-_a-zA-Z0-9]+)/, false) do |match|
@params["section_name"] = match[0]
@active_section = Section.find_by_name(match[0])
# Notice how I'm ending this without having set a controller
# anywhere. If by the end no controller or action has been set,
# autodetection is attempted at the remaining url, following the
# normal basic rules. If it fails, a HTTP 404 would occur.
end
end
# Equivalent for the default rewriting rules
@controller = "weblog"
@action = "index"
# No match has ever been made. At this point autodetection is started
# trying to fill in the controller, action and id. If the url is
# blank, the defaults from above are used, otherwise if it fails a 404
# occurs. If it's successful in detecting at least a controller
# (action would default to "index") obviously the controller is
# called.
end
Comments?
--
Marten Veldthuis
More information about the Rails
mailing list