Just A Summary : Tag railsguts, everything about railsguts http://www.bofh.org.uk/articles/tag/railsguts.rss en-us 40 Piers Cawley Practices Punditry Initial release of acts_as_resource <p>Right. I&#8217;ve bundled <code>acts_as_resource</code> up and stuck it on the typosphere <span class="caps">SVN</span> server. You can grab it from http://svn.typosphere.org/typo/plugins/acts_as_resource if you&#8217;re interested.</p> <p>It&#8217;s currently in what I&#8217;d call an all convention, no configuration state &#8211; if your resources don&#8217;t look pretty similar to the kind of things you get from the resource scaffolding, you&#8217;ll probably have some pain, but I expect to rectify that with coming releases. One thing I want/need to do for instance is to allow for &#8216;relative&#8217; ids in your resource url. For instance, if you&#8217;re looking at <code>/albums/10/tracks/982</code>, it&#8217;s not the most readable of permalinks&#8230; next trick is to allow you to have urls like <code>/albums/because-its-there/tracks/1</code>, ie: the first track on the album &#8216;Because it&#8217;s There&#8217;. I&#8217;m sort of expecting that you&#8217;d do that by doing:</p> <pre><code>class Album has_many :tracks acts_as_resource :uri_field =&gt; :name_dasherized end</code></pre> <pre><code>class Track belongs_to :album acts_as_list acts_as_resource :uri_field =&gt; :position, :parent =&gt; :album end</code></pre> <p>However, my first priority is to add some tests (or, more likely,Rspec specifications) so I&#8217;ve got some confidence that I&#8217;m not breaking things as I go.</p> <p>Anyhow, go grab the plugin, have a play, let me know what you think.</p> Thu, 25 Jan 2007 12:56:00 -0600 urn:uuid:4f48a68b-136b-40c4-bc5b-f885580ba284 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/01/25/initial-release-of-acts_as_resource#comments Ruby rails railsguts acts_as_resource http://www.bofh.org.uk/articles/2007/01/25/initial-release-of-acts_as_resource 'acts_as_resource' progress <p>I&#8217;m very nearly ready to release <code>acts_as_resource</code>, I just have to pull up and tidy code that&#8217;s currently in my working directory&#8217;s ApplicationController and we&#8217;re laughing. However, I thought you&#8217;d like to see what my nested controller looks like. </p> <pre><code>class ChildrenController &lt; ApplicationController before_filter :fetch_resources end</code></pre> <pre><code>def index end</code></pre> <pre><code>def show end</code></pre> <pre><code>def edit end</code></pre> <pre><code>def create @child = @children.build(params[:child]) if @child.save flash[:notice] = 'Child was successfully created.' redirect_to child_path(@child) end end</code></pre> <pre><code>def update if @child.update_attributes(params[:child]) redirect_to child_path(@child) else render :action =&gt; 'edit' end end</code></pre> <pre><code>def destroy @child.destroy redirect_to children_path end</code></pre> <p>I&#8217;ve removed the <span class="caps">XML</span> responses to save vertical space, but they work pretty straightforwardly.</p> <p>Note that <code>fetch_resources</code> is absolutely generic. It is unscaffolded, uses the resourceful conventions and extra information provided by each model&#8217;s <code>acts_as_resource</code> declations to work out what instance variables should be called and sets them appropriately.</p> <p>With a little work to set up a generically named variable as well as the conventionally named ones (say, <code>resource_chain</code>) and a wee bit of simply_helpful pixie dust (polymorphic paths), it should be possible to write a ResourceController class that does <em>all</em> the work for you but allows you to alter behaviour without having to rewrite an entire action method. But that&#8217;s definitely for the <em>next</em> release of the plugin.</p> Thu, 25 Jan 2007 09:30:00 -0600 urn:uuid:3e7b86e0-e64a-45b5-be6e-b982a156e597 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/01/25/acts_as_resource-progress#comments Teaching rails railsguts acts_as_resource http://www.bofh.org.uk/articles/2007/01/25/acts_as_resource-progress Tips for data smugglers <p>While I was working on the <code>acts_as_resource</code> plugin trying to fix things up so that the resource finding side of things works neatly, I realised that I needed some way to get at the ordered list of parameter keys that were matched by the routing system.</p> <p>One way to do it would have been to parse the path again, but that smacked a little too much of repetition, after all, the routing system knows this stuff already, but how to get at it?</p> <p>What I needed was the route object that matches the current path.</p> <p>I ended up modifying <code>ActionController::Routing::Route::parameter_shell</code>. In case you aren&#8217;t familiar with the innards of Rails&#8217; routing system, <code>parameter_shell</code> is the &#8216;skeleton&#8217; params hash that the route populates with information from the current url. So, if you have a route like:</p> <pre><code>map.connect 'some/paths/are/from/:planet', \ :controller =&gt; 'planets', :action =&gt; 'index'</code></pre> <p>then the generated route&#8217;s parameter shell would look like:</p> <pre><code>{:controller =&gt; 'planets', :action =&gt; 'index'}</code></pre> <p>I needed to stuff the route into that hash, but what key should I use? My first thought was to use <code>:matched_route</code>, but what would happen if some future rails application decided that <em>it</em> needed the <code>:matched_route</code> for something it wanted to do?</p> <p>So, then I thought of adding a &#8216;ghost&#8217; key to the hash:</p> <pre><code>matched_route = self class &lt;&lt; @parameter_shell def matched_route matched_route end end</code></pre> <p>That would have worked by hanging a method off the side of the parameter hash which, through the magic of closures would return the matching route. At least, I think so (I&#8217;m still not entirely sure when Ruby closes over things). Before I started to test it, I remembered that the first thing the <code>recognize</code> method does when it has a successful match is <code>dup</code> the parameter shell, and singleton class magic doesn&#8217;t survive <code>dup</code>.</p> <p>Then, I remembered something lovely about the way Ruby&#8217;s hashes work; keys can be arbitrary objects! All I needed to do was to use a key that was neither a string nor a symbol to smuggle the data through, and there would be no way that it could clash with some future application. So, my current implementation of <code>parameter_shell_with_matched_route</code> looks something like:</p> <pre><code>def parameter_shell_with_matched_route @parameter_shell || returning(parameter_shell_without_matched_route) do |params| params[ [:matched_route] ] = self end end</code></pre> <pre><code>alias_method_chain :parameter_shell, :matched_route</code></pre> <p>It turns out that various of the Hash support methods in Rails don&#8217;t play that well with guarded hash keys like that, so I&#8217;ve adapted <code>ActionController::AbstractRequest</code> to pull the matched route out of the parameter hash at the earliest opportunity and stash it in a new method. Here&#8217;s the code that does that:</p> <pre><code>attr_accessor :matched_route</code></pre> <pre><code>def path_parameters_with_matched_route=(parameters) if route = parameters.delete([:matched_route]) self.matched_route = route end self.path_parameters_without_matched_route = parameters end</code></pre> <pre><code>alias_method_chain :path_parameters=, :matched_route</code></pre> Thu, 25 Jan 2007 02:25:00 -0600 urn:uuid:f673cf59-be33-4642-b491-99fcdd606991 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/01/25/tips-for-data-smugglers#comments Ruby rails railsguts http://www.bofh.org.uk/articles/2007/01/25/tips-for-data-smugglers