<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Push cx &#187; URLs</title>
	<atom:link href="http://push.cx/tag/urls/feed" rel="self" type="application/rss+xml" />
	<link>http://push.cx</link>
	<description>A tea-drinking web geek's coffee-flavored blog</description>
	<lastBuildDate>Fri, 09 Jul 2010 12:37:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Redirecting Users&#8217; URLs</title>
		<link>http://push.cx/2009/redirecting-users-urls</link>
		<comments>http://push.cx/2009/redirecting-users-urls#comments</comments>
		<pubDate>Tue, 16 Jun 2009 18:46:38 +0000</pubDate>
		<dc:creator>Peter Harkins</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[human-readable]]></category>
		<category><![CDATA[URLs]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://push.cx/?p=1196</guid>
		<description><![CDATA[I got an email in response to an old post on how I designed NearbyGamer&#8216;s discussion URLs. It asked how to create readable URLs for a community site where users might edit those URLs. What happens after users have made lots and lots of edits? There are two basic strategies for keeping a changing URL [...]]]></description>
			<content:encoded><![CDATA[<p>
I got an email in response to an old post on how I designed <a href="http://push.cx/wp-content/plugins/feed-statistics.php?url=aHR0cDovL05lYXJieUdhbWVycy5jb20=">NearbyGamer</a>&#8216;s <a href="http://push.cx/wp-content/plugins/feed-statistics.php?url=aHR0cDovL3B1c2guY3gvMjAwNy9kaXNjdXNzaW9uLXVybHMtb3BhcXVlLXVzYWJsZS1hbmQtcmVhZGFibGU=">discussion URLs</a>. It asked how to create readable URLs for a community site where users might edit those URLs. What happens after users have made lots and lots of edits?
</p>

<p>
There are two basic strategies for keeping a changing URL pointing to the same content. Either only part of the URL changes and you look things up by the stable piece (as with the slugs in my previous blog post) or you keep track of old identifiers with pointers to their current identifiers.
</p>

<p>
On NearbyGamers, <a href="http://push.cx/wp-content/plugins/feed-statistics.php?url=aHR0cDovL05lYXJieUdhbWVycy5jb20vdGFncw==">tags</a> are used to identify what games players are open to playing. But there are a huge number of variations: the game Dungeons and Dragons might be listed as D&#038;D, DND, D&#038;D 4, D&#038;D 4th ed., or many more (and that&#8217;s before spelling errors).
</p>

<p>
To deal with this, I borrowed a mechanism from Wikipedia. Users can edit a tag to redirect it to another (which may not have a redirect set to a third, to prevent all sorts of annoying problems). In short, the Tag object might just be used for its column pointing to another Tag.
</p>

<p>
This is functionally equivalent to having a table of redirects. When a request comes in for a particular Tag, I could check a TagRedirect table to see if that tag appears in the <kbd>from</kbd> column and redirect the visitor to the Tag named by the <kbd>to</kbd> column.
</p>

<p>
Redirects are one of the ways your app will have to scale to meet users&#8217; activity. Thinking about redirects as an explicit table makes it clear you have options for how to deal with it: you could add a date column and expire old entries, or limit the number of redirects one user is allowed to make (perhaps over time), or limit the number of redirects one entity allows. You could even replace this database table with a distributed key/value store like memcached (or preferably something more permanent).
</p>

<p>
So allowing users to edit URLs leads to one of three things: either you don&#8217;t allow them to edit the real identifier, you maintain a table of redirects, or you accept broken links.
</p>

<p>
NearbyGamers also uses the third strategy: if a gamer changes their handle, the URL is updated without any kind of redirecting. I considered redirects, but then no one could ever relinquish a handle.
</p>

<p>
URL design is not easy. Allowing users to influence what a URL will be is often really valuable but adds to the difficulty of designing your URLs. This is one of the interesting bits of computer programming where there isn&#8217;t a single answer, you have to pick your tradeoffs to match your needs.
</p> <img src="http://push.cx/wp-content/plugins/feed-statistics.php?view=1&post_id=1196" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://push.cx/2009/redirecting-users-urls/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Rails URL Params as Types</title>
		<link>http://push.cx/2008/rails-url-params-as-types</link>
		<comments>http://push.cx/2008/rails-url-params-as-types#comments</comments>
		<pubDate>Tue, 26 Aug 2008 22:36:43 +0000</pubDate>
		<dc:creator>Peter Harkins</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[strings]]></category>
		<category><![CDATA[typing]]></category>
		<category><![CDATA[URLs]]></category>

		<guid isPermaLink="false">http://push.cx/?p=314</guid>
		<description><![CDATA[Yesterday I (belatedly) took my friend Nola Stowe&#8216;s advice and picked up a book she tech-reviewed, The Rails Way by Obie Fernandez. It&#8217;s been a great read so far (about 85 pages in), and I just realized that routing is largely about type conversion. In the explanation of named routes, there&#8217;s a series of examples [...]]]></description>
			<content:encoded><![CDATA[<p>
Yesterday I (belatedly) took my friend <a href="http://push.cx/wp-content/plugins/feed-statistics.php?url=aHR0cDovL3J1YnlnZWVrLmNvbS8=">Nola Stowe</a>&#8216;s advice and picked up a book she tech-reviewed, The Rails Way by Obie Fernandez. It&#8217;s been a great read so far (about 85 pages in), and I just realized that routing is largely about type conversion.
</p>

<p>
In the explanation of named routes, there&#8217;s a series of examples demonstrating the increasing amounts of syntactic sugar Rails provides:
</p>

<pre>&nbsp;
<span style="color: #808080; font-style: italic;"># The most explicit way, before you define the named route:</span>
&lt;%= link_to <span style="color: #ff0000;">"Auction for #{h(auction.item.description)}"</span>,
    :controller =&gt; <span style="color: #ff0000;">"auctions"</span>,
    :action     =&gt; <span style="color: #ff0000;">"show"</span>,
    :id         =&gt; auction.<span style="">id</span> %&gt;
&nbsp;
<span style="color: #808080; font-style: italic;"># The first use of the named route, no need to specify controller or action:</span>
&lt;%= link_to <span style="color: #ff0000;">"Auction for #{h(auction.item.description)}"</span>, auction_path<span style="color: #66cc66;">&#40;</span>:id =&gt; auction.<span style="">id</span><span style="color: #66cc66;">&#41;</span> %&gt;
&nbsp;
<span style="color: #808080; font-style: italic;"># If you just have an :id argument to fill in, you can just pass the value:</span>
&lt;%= link_to <span style="color: #ff0000;">"Auction for #{h(auction.item.description)}"</span>, auction_path<span style="color: #66cc66;">&#40;</span>auction.<span style="">id</span><span style="color: #66cc66;">&#41;</span> %&gt;
&nbsp;
<span style="color: #808080; font-style: italic;"># And you could just pass the object and Rails will get its id:</span>
&lt;%= link_to <span style="color: #ff0000;">"Auction for #{h(auction.item.description)}"</span>, auction_path<span style="color: #66cc66;">&#40;</span>auction<span style="color: #66cc66;">&#41;</span> %&gt;</pre>

<p>
In Rails it&#8217;s just syntactic sugar, but the underlying mechanism here is type coercion. Instead of thinking of a URL having the type &#8216;string&#8217;, think of it having the type &#8216;URL&#8217;. (Here&#8217;s where all the Haskell guys are saying &#8220;Uh, it does already.&#8221; and rolling their eyes. You already get it, so this post is not for you.) The syntactic sugar is quietly converting an <kbd>auction</kbd> object into a <kbd>url</kbd> object (or part of one, really).
</p>

<p>
In Rails you can define a <kbd>to_param</kbd> method on your object that&#8217;s called by <kbd>url_for</kbd> (the method underlying <kbd>link_to</kbd>), and the name gives away that you&#8217;re converting type like the <kbd>to_i</kbd>, <kbd>to_s</kbd>, <kbd>to_f</kbd> methods you already know from Ruby&#8217;s builtin types.
</p>

<p>
The reverse is less seamless. There is no <kbd>Model.from_param</kbd>. Rails&#8217; routing unpacks the URL into variables for the code you write in your controller to find the object(s). In a RESTful style, it seems odd that Rails doesn&#8217;t default to doing something like <kbd>@<i>model_name</i> = <i>Model</i>.find(params[:id])</kbd> if you don&#8217;t define your own <kbd>load_object</kbd> <kbd>before_filter</kbd>.
</p>

<p>
I&#8217;ve been thinking a lot about <a href="http://push.cx/wp-content/plugins/feed-statistics.php?url=aHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9SZXByZXNlbnRhdGlvbmFsX1N0YXRlX1RyYW5zZmVy">REST</a> lately. The URL of a resource is that resource converted to a URL type. A view presenting an object could be considered converting it to an HTML type. Controllers and actions&#8230; I can&#8217;t quite see putting them into my models, but they seem much less distinct to me than they did a few hours ago.
</p> <img src="http://push.cx/wp-content/plugins/feed-statistics.php?view=1&post_id=314" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://push.cx/2008/rails-url-params-as-types/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Discussion URLs: Opaque, Usable, and Readable</title>
		<link>http://push.cx/2007/discussion-urls-opaque-usable-and-readable</link>
		<comments>http://push.cx/2007/discussion-urls-opaque-usable-and-readable#comments</comments>
		<pubDate>Thu, 05 Apr 2007 13:03:30 +0000</pubDate>
		<dc:creator>Peter Harkins</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[ActiveResource]]></category>
		<category><![CDATA[human-readable]]></category>
		<category><![CDATA[named routes]]></category>
		<category><![CDATA[nested routes]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[resources]]></category>
		<category><![CDATA[RESTful]]></category>
		<category><![CDATA[routes]]></category>
		<category><![CDATA[routing]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[URLs]]></category>

		<guid isPermaLink="false">http://push.cx/2007/discussion-urls-opaque-usable-and-readable</guid>
		<description><![CDATA[I just wrote about Human-Readable ActiveResource URLs, and now I want to examine one example of them more in-depth. Discussion forum URLs have several conflicting goals: human-readable I should get some idea of what the discussion&#8217;s about when I hover over a link permanent bookmarks, incoming links, and search engines all need reliable URLs editable [...]]]></description>
			<content:encoded><![CDATA[<p>
I just wrote about <a href="http://push.cx/wp-content/plugins/feed-statistics.php?url=aHR0cDovL3B1c2guY3gvMjAwNy9odW1hbi1yZWFkYWJsZS1hY3RpdmVyZXNvdXJjZS11cmxz">Human-Readable ActiveResource URLs</a>, and now I want to examine one example of them more in-depth. Discussion forum URLs have several conflicting goals:
</p>

<dl>
  <dt>human-readable</dt> <dd>I should get some idea of what the discussion&#8217;s about when I hover over a link</dd>
  <dt>permanent</dt> <dd>bookmarks, incoming links, and search engines all need reliable URLs</dd>
  <dt>editable</dt> <dd>If a discussion drifts, it needs a new subject, which means it needs a new URL</dd>
  <dt>opaque</dt> <dd>I&#8217;d rather not roll out the carpet for someone to scrape all the discussions</dd>
</dl>

<p>
After a bit of pondering, I decided that URLs should look like this:
</p>

<p>
http://nearbygamers.com/discussions/<b>{slug}</b>-<b>{post count}</b>-<b>{subject}</b>
</p>

<dl>
  <dt>slug</dt> <dd>An unchanging random 5-character string.</dd>
  <dt>post count</dt> <dd>The number of posts in this discussion, so that when you look at the <a href="http://push.cx/wp-content/plugins/feed-statistics.php?url=aHR0cDovL25lYXJ5YmdhbWVycy5jb20vZGlzY3Vzc2lvbnM=">discussions index</a> you know at a glance if you&#8217;ve read a thread because your browser colors visited links. I snagged this off <a href="http://push.cx/wp-content/plugins/feed-statistics.php?url=aHR0cDovL3d3dy5qb2Vsb25zb2Z0d2FyZS5jb20vYXJ0aWNsZXMvQnVpbGRpbmdDb21tdW5pdGllc3dpdGhTby5odG1s">the Joel</a>.</dd>
  <dt>subject</dt> <dd>Just the alphanumerics, <a href="http://push.cx/wp-content/plugins/feed-statistics.php?url=aHR0cDovL3d3dy5tYXR0Y3V0dHMuY29tL2Jsb2cvZGFzaGVzLXZzLXVuZGVyc2NvcmVzLw==">dash-separated</a>, updated as the subject is edited</dd>
</dl>

<p>
So two parts (post count and subject) on a discussion can change, and the controller uses the slug to load the discussion and redirect to the correct URL if either has changed. Bookmarks and search engines can update, and outside links never stop working.
</p>

<h3>The Code</h3>

<p>
First, a little snippet of code to generate slugs lives in <kbd>lib/slug.rb</kbd>:
</p>

<pre>&nbsp;
def random_slug<span style="color: #66cc66;">&#40;</span><span style="color: #000066;">length</span>=<span style="color: #cc66cc;">5</span><span style="color: #66cc66;">&#41;</span>
  chars = <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">"a"</span>..<span style="color: #ff0000;">"z"</span><span style="color: #66cc66;">&#41;</span>.<span style="">to_a</span> + <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">"A"</span>..<span style="color: #ff0000;">"Z"</span><span style="color: #66cc66;">&#41;</span>.<span style="">to_a</span> + <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">"1"</span>..<span style="color: #ff0000;">"9"</span><span style="color: #66cc66;">&#41;</span>.<span style="">to_a</span>
  Array.<span style="">new</span><span style="color: #66cc66;">&#40;</span><span style="color: #000066;">length</span>, <span style="color: #ff0000;">''</span><span style="color: #66cc66;">&#41;</span>.<span style="">collect</span><span style="color: #66cc66;">&#123;</span>chars<span style="color: #66cc66;">&#91;</span><span style="color: #000066;">rand</span><span style="color: #66cc66;">&#40;</span>chars.<span style="">size</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#125;</span>.<span style="">join</span>
<span style="color: #b1b100;">end</span></pre>

<p>
The Discussion model uses this to set a slug on itself if it doesn&#8217;t have one yet, and then uses that slug to generate URLs (note that I remove multiple and leading/trailing hyphens from the subjects):
</p>

<pre>&nbsp;
<span style="color: #000066;">require</span> <span style="color: #ff0000;">'slug'</span>
&nbsp;
class Discussion &lt; ActiveRecord::<span style="color: #006600;">Base</span>
  def to_param
    <span style="color: #ff0000;">"#{slug}-#{posts.count}-#{subject.gsub(/[^[:alnum:]]+/i, '-').gsub(/-+/, '-').gsub(/^-|-$/, '')}"</span>
  <span style="color: #b1b100;">end</span>
&nbsp;
  protected
  def before_validation
    <span style="color: #b1b100;">if</span> self.<span style="">slug</span>.<span style="">empty</span>?
      begin
        self.<span style="">slug</span> = random_slug
      <span style="color: #b1b100;">end</span> <span style="color: #b1b100;">while</span><span style="color: #66cc66;">&#40;</span>Discussion.<span style="">count</span><span style="color: #66cc66;">&#40;</span>:conditions =&gt; <span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'slug = ?'</span>, self.<span style="">slug</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span> &gt; <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #b1b100;">end</span>
  <span style="color: #b1b100;">end</span>
end</pre>

<p>
Finally, the DiscussionsController loads discussion objects, throws 404 errors, and redirects appropriately:
</p>

<pre>&nbsp;
class DiscussionsController &lt; ApplicationController
  before_filter :load_discussion, :except =&gt; <span style="color: #66cc66;">&#91;</span> :<span style="color: #000066;">index</span> <span style="color: #66cc66;">&#93;</span>
&nbsp;
  private
  def load_discussion
    slug = params<span style="color: #66cc66;">&#91;</span>:id<span style="color: #66cc66;">&#93;</span>.<span style="">split</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'-'</span><span style="color: #66cc66;">&#41;</span>.<span style="">first</span> <span style="color: #b1b100;">if</span> params<span style="color: #66cc66;">&#91;</span>:id<span style="color: #66cc66;">&#93;</span>
    <span style="color: #0000ff;">@discussion</span> = Discussion.<span style="">find_by_slug</span><span style="color: #66cc66;">&#40;</span>slug<span style="color: #66cc66;">&#41;</span> <span style="color: #b1b100;">if</span> slug
    raise ::<span style="color: #006600;">ActionController</span>::<span style="color: #006600;">RoutingError</span>, <span style="color: #ff0000;">"Recognition failed for #{request.path}"</span> <span style="color: #b1b100;">if</span> <span style="color: #0000ff;">@discussion</span>.<span style="">nil</span>?
    redirect_to discussion_path<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">@discussion</span><span style="color: #66cc66;">&#41;</span> <span style="color: #b1b100;">and</span> <span style="color: #000066;">return</span> <span style="color: #b1b100;">if</span> <span style="color: #0000ff;">@discussion</span>.<span style="">to_param</span> != params<span style="color: #66cc66;">&#91;</span>:id<span style="color: #66cc66;">&#93;</span>
  <span style="color: #b1b100;">end</span></pre> <img src="http://push.cx/wp-content/plugins/feed-statistics.php?view=1&post_id=233" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://push.cx/2007/discussion-urls-opaque-usable-and-readable/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Human-Readable ActiveResource URLs</title>
		<link>http://push.cx/2007/human-readable-activeresource-urls</link>
		<comments>http://push.cx/2007/human-readable-activeresource-urls#comments</comments>
		<pubDate>Tue, 03 Apr 2007 21:15:07 +0000</pubDate>
		<dc:creator>Peter Harkins</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[ActiveResource]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[human-readable]]></category>
		<category><![CDATA[named routes]]></category>
		<category><![CDATA[nested routes]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Rails 1.1]]></category>
		<category><![CDATA[Rails 1.2]]></category>
		<category><![CDATA[RESTful]]></category>
		<category><![CDATA[routes]]></category>
		<category><![CDATA[URLs]]></category>

		<guid isPermaLink="false">http://push.cx/2007/human-readable-activeresource-urls</guid>
		<description><![CDATA[I&#8217;ve got URLs on the brain this week. I started NearbyGamers using Rails 1.1 with just gamers and tags. I upgraded to Rails 1.2 (and liked it) , and added discussions after I updated to Rails 1.2. I was able to use ActiveResource for Discussions with Posts as a nested resource. I&#8217;m really happy with [...]]]></description>
			<content:encoded><![CDATA[<p>
I&#8217;ve got URLs on the brain this week. I started <a href="http://push.cx/wp-content/plugins/feed-statistics.php?url=aHR0cDovL25lYXJieWdhbWVycy5jb20=">NearbyGamers</a> using Rails 1.1 with just gamers and <a href="http://push.cx/wp-content/plugins/feed-statistics.php?url=aHR0cDovL25lYXJieWdhbWVycy5jb20vdGFncw==">tags</a>. I upgraded to Rails 1.2 (and <a href="http://push.cx/wp-content/plugins/feed-statistics.php?url=aHR0cDovL3B1c2guY3gvMjAwNy9yYWlscy0xMjEtaW1wcmVzc2lvbg==">liked it</a>)
, and added <a href="http://push.cx/wp-content/plugins/feed-statistics.php?url=aHR0cDovL25lYXJieWdhbWVycy5jb20vZGlzY3Vzc2lvbnM=">discussions</a> after I updated to Rails 1.2. I was able to use ActiveResource for Discussions with Posts as a nested resource. I&#8217;m really happy with this code, as it&#8217;s very tidy.
</p>

<p>
On Sunday I updated gamers and tags to use ActiveResource. It wasn&#8217;t hard, mostly just renames (the &#8216;view&#8217; action became &#8216;show&#8217;, for example) and removing url_for hashes (<kbd>:controller => 'gamers', :action => 'view', :handle => @gamer.handle</kbd>) with much nicer named routes (<kbd>gamer_path(@gamer)</kbd>). A gripe I have about ActiveResource is that it has poor URLs, with internal record IDs leaking out. I&#8217;ve had nice URLs (<a href="http://push.cx/wp-content/plugins/feed-statistics.php?url=aHR0cDovL25lYXJieWdhbWVycy5jb20vZ2FtZXJzL0hhcmtpbnM=">/gamers/Harkins</a> and <a href="http://push.cx/wp-content/plugins/feed-statistics.php?url=aHR0cDovL25lYXJieWdhbWVycy5jb20vdGFncy9SUEdz">/tags/RPGs</a>) for gamers and tags and I wanted to keep them.
</p>

<p>
Joshua Schacter gave a presentation on building and growing <a href="http://push.cx/wp-content/plugins/feed-statistics.php?url=aHR0cDovL2RlbC5pY2lvLnVz">del.icio.us</a> that included the gems (among <a href="http://push.cx/wp-content/plugins/feed-statistics.php?url=aHR0cDovL3NpbW9uLmluY3V0aW8uY29tL25vdGVzLzIwMDYvc3VtbWl0L3NjaGFjaHRlci50eHQ=">many other gems</a>):
</p>

<blockquote>
<ul>
  <li>Dont expose your unique id&#8217;s to the outside world (php?id=1 etc.) people can
scrape through everything very easily. This is why del.icio.us uses MD5 hashes
of links instead.
</li>
  <li>URLs are prime real estate &#8211; respect them</li>
</ul>
</blockquote>

<p>
It turns out this is not just possible but easy, though I blew an hour or so finding it (Rails docs still need love). In my Gamer and Tag objects, I just define a <kbd>to_param</kbd> method and the URL builder picks it up:
</p>

<pre>&nbsp;
class Gamer &lt; ActiveRecord::<span style="color: #006600;">Base</span>
  def to_param
    self.<span style="">handle</span>
  <span style="color: #b1b100;">end</span>
end
class Tag &lt; ActiveRecord::<span style="color: #006600;">Base</span>
  def to_param
    self.<span style="">name</span>
  <span style="color: #b1b100;">end</span>
end
&nbsp;
<span style="color: #808080; font-style: italic;"># and over in config/routes.rb I do the usual:</span>
<span style="color: #000066;">map</span>.<span style="">resources</span> :gamers
<span style="color: #000066;">map</span>.<span style="">resources</span> :tags, :memger =&gt; <span style="color: #66cc66;">&#123;</span> :history =&gt; :get, :variantes =&gt; :get <span style="color: #66cc66;">&#125;</span>
<span style="color: #808080; font-style: italic;"># and now gamer_path(@gamer) and tag_path(@tag) work in my views</span></pre>

<p>
My controller looks like:
</p>

<pre>&nbsp;
class GamersController &lt; ApplicationController
  before_filter :load_gamer, :except =&gt; <span style="color: #66cc66;">&#91;</span> :<span style="color: #000066;">index</span> <span style="color: #66cc66;">&#93;</span>
&nbsp;
  <span style="color: #808080; font-style: italic;"># The regular index, show, edit, and update actions here</span>
&nbsp;
  private
  def load_gamer
    <span style="color: #0000ff;">@gamer</span> = Gamer.<span style="">find_by_handle</span><span style="color: #66cc66;">&#40;</span>params<span style="color: #66cc66;">&#91;</span>:id<span style="color: #66cc66;">&#93;</span>, :include =&gt; <span style="color: #66cc66;">&#91;</span>:location, :tags<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>
    raise ::<span style="color: #006600;">ActionController</span>::<span style="color: #006600;">RoutingError</span>, <span style="color: #ff0000;">"Recognition failed for #{request.path}"</span> <span style="color: #b1b100;">if</span> <span style="color: #0000ff;">@gamer</span>.<span style="">nil</span>?
    <span style="color: #808080; font-style: italic;"># canonicalize case</span>
    redirect_to gamer_path<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">@gamer</span><span style="color: #66cc66;">&#41;</span> <span style="color: #b1b100;">and</span> <span style="color: #000066;">return</span> <span style="color: #b1b100;">if</span> <span style="color: #0000ff;">@gamer</span>.<span style="">handle</span> != params<span style="color: #66cc66;">&#91;</span>:id<span style="color: #66cc66;">&#93;</span>
  <span style="color: #b1b100;">end</span></pre>

<p>
And every action that needs it has the @gamer object loaded from the URL param, with 404 errors handled and mistaken case fixed. There&#8217;s <a href="http://push.cx/wp-content/plugins/feed-statistics.php?url=aHR0cDovL2Rldi5ydWJ5b25yYWlscy5vcmcvdGlja2V0LzY4MTQ=">a patch</a> that will let you rename the :id parameter. I can&#8217;t say I mind if it&#8217;s not accepted; I don&#8217;t mind calling it :id instead of :handle or :name because I think of it as the public id of the object.
</p>

<p>
Come back Thursday, I&#8217;ll tell you how I made my discussion URLs even more useful.
</p> <img src="http://push.cx/wp-content/plugins/feed-statistics.php?view=1&post_id=232" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://push.cx/2007/human-readable-activeresource-urls/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Rails: Semicolons Out, Slashes In</title>
		<link>http://push.cx/2007/rails-semicolons-out-slashes-in</link>
		<comments>http://push.cx/2007/rails-semicolons-out-slashes-in#comments</comments>
		<pubDate>Sun, 01 Apr 2007 21:50:23 +0000</pubDate>
		<dc:creator>Peter Harkins</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[map]]></category>
		<category><![CDATA[mapping]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[resources]]></category>
		<category><![CDATA[routes]]></category>
		<category><![CDATA[routing]]></category>
		<category><![CDATA[semicolon]]></category>
		<category><![CDATA[slash]]></category>
		<category><![CDATA[slashes]]></category>
		<category><![CDATA[URLs]]></category>

		<guid isPermaLink="false">http://push.cx/2007/rails-semicolons-out-slashes-in</guid>
		<description><![CDATA[As of r6485, Edge Rails resource routes use / as the URL separator for actions instead of ;. This will be in Rails 2.0 (and I like / more), so I wanted to get prepared for the change by updating my URLs now. I didn&#8217;t want to move to Edge Rails (too exciting for me), [...]]]></description>
			<content:encoded><![CDATA[<p>
As of <a href="http://push.cx/wp-content/plugins/feed-statistics.php?url=aHR0cDovL2Rldi5ydWJ5b25yYWlscy5vcmcvY2hhbmdlc2V0LzY0ODU=">r6485</a>, Edge Rails resource routes use <b>/</b> as the URL separator for actions instead of <b>;</b>. This will be <a href="http://push.cx/wp-content/plugins/feed-statistics.php?url=aHR0cDovL3ByYWdkYXZlLnByYWdwcm9nLmNvbS9wcmFnZGF2ZS8yMDA3LzAzL2NoYW5nZV90b19yZXN0Xy5odG1s">in Rails 2.0</a> (and I like / more), so I wanted to get prepared for the change by updating my URLs now. I didn&#8217;t want to move to Edge Rails (too exciting for me), so I grabbed the change, dropped it into a source file, and loaded it into my app (thank you, open classes).
</p>

<p>
If you want to get ready now, grab 
<a href="http://push.cx/wp-content/plugins/feed-statistics.php?url=L3dwLWNvbnRlbnQvdXBsb2Fkcy8yMDA3LzA0L3NsYXNoX3VybHMucmI="><kbd>slash_urls.rb</kbd></a> and drop it in your <kbd>lib</kbd> directory. At the top of your <kbd>config/routes.rb</kbd>, add the line:
</p>

<pre>&nbsp;
<span style="color: #000066;">require</span> <span style="color: #ff0000;">'slash_urls'</span></pre>

<p>
And now all my URLs on <a href="http://push.cx/wp-content/plugins/feed-statistics.php?url=aHR0cDovL25lYXJieWdhbWVycy5jb20=">NearbyGamers</a> use slashes instead of semicolons. I only had one or two actions on my ActiveResource routes besides the built-in CRUD, so I&#8217;m not worried about doing a 301 redirects.
</p> <img src="http://push.cx/wp-content/plugins/feed-statistics.php?view=1&post_id=231" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://push.cx/2007/rails-semicolons-out-slashes-in/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
