<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>The Trellis Framework Blog : </title>
    <link>http://www.trellisframework.org/.rss</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Component Driven Web Development in Ruby</description>
    <item>
      <title>Trellis and Heroku</title>
      <description>&lt;p&gt;Currently, Trellis v0.1.1 requires Ruby 1.8.7 due to my usage of blocks as parameters (for the filters feature). This prevents Trellis applications to be deployed to Heroku using the default stack. &lt;/p&gt;

&lt;p&gt;To migrate applications to 1.8.7 see http://blog.heroku.com/archives/2010/3/5/public_beta_deployment_stacks/&lt;/p&gt;

&lt;p&gt;To create a new Heroku app for Trellis use heroku create &amp;#8211;stack bamboo-ree-1.8.7&lt;/p&gt;</description>
      <pubDate>Fri, 09 Apr 2010 11:26:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:a91a6214-b143-4b56-99d1-d81f2d5e2ccb</guid>
      <comments>http://www.trellisframework.org/2010/04/09/status#comments</comments>
      <category>deployment</category>
      <category>heroku</category>
      <link>http://www.trellisframework.org/2010/04/09/status</link>
    </item>
    <item>
      <title>Trellis Tutorial #3 - Creating a Stateless Component</title>
      <description>&lt;h2&gt;Creating a Stateless Component&lt;/h2&gt;

&lt;p&gt;A component-driven framework would be pretty pointless if you couldn&amp;#8217;t create your own components. Component creation is how developers can encapsulate a complex and/or repetitive piece of functionality and provide a clear API to access that functionality.&lt;/p&gt;

&lt;p&gt;In Trellis, components wrap both logic and presentation in a small manageable package. A Trellis component provides a template to be rendered and logic that can be used to respond to external events.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="/2009/10/06/trellis-tutorial-1-the-hilo-web-application"&gt;first&lt;/a&gt; installment of the Trellis tutorial series we got to use some of the simple components made available through the core library. The core components provide very basic functionality expected in a component-driven web framework. But things only get interesting when you get to build your own components. Whether they are general purpose, domain specific or application specific components, a well-crafted set of components can truly improve the understanding of an application, ease maintenance and improve testability. &lt;/p&gt;

&lt;p&gt;In this tutorial we&amp;#8217;ll walk through the development of a simple stateless component to display images using the Flickr API. This example is included in the Trellis distribution under examples/flickr&lt;/p&gt;

&lt;h3&gt;Project Setup&lt;/h3&gt;

&lt;p&gt;Setting up a Trellis project is quite simple. We&amp;#8217;ll start with the simple directory structure shown in Figure 1. I&amp;#8217;ve named the root directory of the application &amp;#8216;flickr&amp;#8217;. The ruby file flickr.rb will contain our application and the file spec/flickr_spec.rb will contain our RSpec specifications.&lt;/p&gt;

&lt;p&gt;&lt;img src="/files/flickr_001.png" alt="Directory Structure"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 1 - Flickr Application Directory Structure&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;Test Driven Development with Trellis with RSpec&lt;/h3&gt;

&lt;p&gt;In this tutorial we&amp;#8217;ll work in a more realistic way that in previous tutorials. We&amp;#8217;ll developed the Flickr example in a test-driven/test-first fashion. We&amp;#8217;ll start with a bare bones skeleton for a Trellis application, as shown next (flickr.rb):&lt;/p&gt;

&lt;pre class="brush: ruby;"&gt;
require 'rubygems'
require 'trellis'

include Trellis

module Flickr
  class FlickrApp &lt; Application
  end
end
&lt;/pre&gt;

&lt;h4&gt;RSpec&lt;/h4&gt;

&lt;p&gt;For our TDD efforts we&amp;#8217;ll use RSpec, &amp;#8220;the original Behavior Driven Development framework for Ruby&amp;#8221;. With RSpec you create &amp;#8220;specifications&amp;#8221; which are tests that describe the behavior of the system under certain conditions. We will try to follow the red-green-refactor mantra as close as possible:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Writing a Test that describes a particular behavior of interest in the system.&lt;/li&gt;
&lt;li&gt;Running the Test (Red): Since the behavior hasn&amp;#8217;t been implemented the test will fail.&lt;/li&gt;
&lt;li&gt;Implement: Writing enough code to pass the test&lt;/li&gt;
&lt;li&gt;Re-Running the Test (Green): With the implementation in place the test should now pass&lt;/li&gt;
&lt;li&gt;Refactor: With a basic foundation of how to fulfill the behavior and a test to prove the implementation we can now &amp;#8220;refactor without fear&amp;#8221;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the /spec directory we&amp;#8217;ll add simple RSpec spec as follows (flickr_spec.rb):&lt;/p&gt;

&lt;pre class="brush: ruby;"&gt;
require 'rubygems'
require 'spec'
require 'rack'
require 'rack/test'
require File.dirname(__FILE__) + '/../flickr.rb'

describe Flickr::FlickrApp do
  include Rack::Test::Methods

  def app
    Flickr::FlickrApp.new
  end

  it "should have a home page declared" do
    Flickr::FlickrApp.homepage == :home
  end
end
&lt;/pre&gt;

&lt;p&gt;Let&amp;#8217;s talk about the spec we&amp;#8217;ve just created. At the top, besides requiring rubygems, we need the RSpec library (spec), Rack (rack) and Rack::Test (rack/test). We will also need to make the file under test, flickr.rb available.&lt;/p&gt;

&lt;p&gt;Rack::Test enables you to test a Rack-based application without having a running server. Rack::Test mocks HTTP requests and provides a DSL to test against the response.&lt;/p&gt;

&lt;p&gt;The describe block, &amp;#8220;describes&amp;#8221; an scenario. In RSpec an scenario consists of one or more examples. Each example describes a discrete behavior of the class under test.&lt;/p&gt;

&lt;p&gt;In the scenario above we have only one example so far which states that our application should have a home page named &amp;#8220;home&amp;#8221;. With the bare bones application code and the spec in place we can now run it to get our TDD going.&lt;/p&gt;

&lt;p&gt;&lt;img src="/files/flickr_002.png" alt="Failed Spec"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 2 - Failed Spec (no home page)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As expected the test fails. We got to the &amp;#8220;red&amp;#8221; stage. To pass the test and get to &amp;#8220;green&amp;#8221; we can simply declare the home page as shown next:&lt;/p&gt;

&lt;pre class="brush: ruby;"&gt;
module Flickr
  class FlickrApp &lt; Application
    home :home
  end
end
&lt;/pre&gt;

&lt;p&gt;Running the tests again shows that we&amp;#8217;ve accomplish what we set out to do in this simple example.&lt;/p&gt;

&lt;p&gt;&lt;img src="/files/flickr_003.png" alt="Passed Example"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 3 - Passed Spec (after adding a home page)&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;Testing with Rack::Test&lt;/h3&gt;

&lt;p&gt;With an understanding of the basic mechanics of TDD we can now move onto fleshing out the rest of the application.
Our next example will make use of &lt;a href="http://gitrdoc.com/brynary/rack-test"&gt;Rack::Test&lt;/a&gt; to make sure that our application returns an HTTP status code of 200 (OK).
Previously we provided the spec with an #app method which returned an instance of the Flickr application. The #app method is required by Rack::Test and it enables the use of a simple DSL to interact with the application in a mocked HTTP server environment. Rack::Test provides a way to issue a mock HTTP request to the application, inspect the response, follow redirects and maintain cookies across requests.&lt;/p&gt;

&lt;pre class="brush: ruby;"&gt;
it "should return an OK HTTP status" do
  get "/"
  last_response.status.should be(200)
end
&lt;/pre&gt;

&lt;p&gt;This test requests the root url of the application, which should redirect to a home page and then checks that the last response has a status of 200.&lt;/p&gt;

&lt;p&gt;&lt;img src="/files/flickr_004.png" alt="Failed Example"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 4 - Failed Spec (no OK response)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To pass this next example we need to provide a bare bones implementation of the Home page. The Home page provides a simple html template as shown next:&lt;/p&gt;

&lt;pre class="brush: ruby;"&gt;
class Home &lt; Page
  template %[
    &amp;lt;html xml:lang="en" lang="en" 
          xmlns:trellis="http://trellisframework.org/schema/trellis_1_0_0.xsd" 
          xmlns="http://www.w3.org/1999/xhtml"&gt;
      &amp;lt;body&gt;
        &lt;h1&gt;Some Interesting Pictures...&lt;/h1&gt;
      &amp;lt;/body&gt;
    &amp;lt;/html&gt;
  ], :format =&gt; :html
end
&lt;/pre&gt;

&lt;p&gt;Let&amp;#8217;s run the spec again and confirm that we get a 200 response.&lt;/p&gt;

&lt;p&gt;&lt;img src="/files/flickr_005.png" alt="Passed Example"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 5 - Passed Spec (after barebones home page impl)&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;Running what we have so far&lt;/h3&gt;

&lt;p&gt;At this point we do have enough of the application in place so that we can also run it and visually inspect the progress so far.&lt;/p&gt;

&lt;p&gt;To be able to launch the application self-contained we need an instance of the application on which we can invoke the #start method. Add the two following lines at the end of the Flick module in flickr.rb:&lt;/p&gt;

&lt;pre class="brush: ruby;"&gt;
web_app = FlickrApp.new
web_app.start 3006 if __FILE__ == $PROGRAM_NAME
&lt;/pre&gt;

&lt;p&gt;To launch the application run the flickr.rb ruby script like:&lt;/p&gt;

&lt;pre class="brush: shell; gutter: false;"&gt;
ruby flickr.rb
&lt;/pre&gt;

&lt;p&gt;&lt;img src="/files/flickr_006.png" alt="Lauching the Flickr App"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 6 - Launching the Flickr Trellis App&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Open a browser and point it to http://localhost:3006 and you should see:&lt;/p&gt;

&lt;p&gt;&lt;img src="/files/flickr_007.png" alt="Barebones Flickr App"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 7 - Bare bones Flickr Trellis App&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;The Flickr Interestingness Component&lt;/h3&gt;

&lt;p&gt;The &lt;a href="http://www.flickr.com/"&gt;Flickr&lt;/a&gt; Interestingess Trellis Component will use the Flickr API to make a call to the &amp;#8220;interestiness&amp;#8221; XML-RPC web service method which returns one or more random images from Flick that have been deemed &amp;#8220;interesting&amp;#8221; (warning to the easily offended). &lt;/p&gt;

&lt;p&gt;We&amp;#8217;ll start with a simple test to get the component to render something (anything really!). Our basic test will simply expect to find an html DIV with and id attribute of &amp;#8220;flickr_viewer&amp;#8221; and with text content equals to &amp;#8220;Hello&amp;#8221;: &lt;/p&gt;

&lt;pre class="brush: ruby;"&gt;
it "should render the flickr component" do
  get '/'
  last_response.body.should include(%[&lt;div id="flickr_viewer"&gt;Hello&lt;/div&gt;])
end
&lt;/pre&gt;

&lt;p&gt;&lt;img src="/files/flickr_008.png" alt="Failed Component Test"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 8 - Failed Component Test&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To pass this test we can provide the bare bones implementation of a Trellis stateless component. Inside the Flickr module in flickr.rb we declare the FlickrInterestingness component which descends from Trellis::Component:&lt;/p&gt;

&lt;pre class="brush: ruby;"&gt;
class FlickrInterestingness &lt; Component
   tag_name "flickr_interestingness"

   render do |tag|
     %[&lt;div id="flickr_viewer"&gt;Hello&lt;/div&gt;]
   end
end
&lt;/pre&gt;

&lt;p&gt;A Trellis component has a tag_name, which by default is just the name of the component underscored and lower-cased. To provide the template or content for the component the Trellis::Component class provides the #render method which takes a block that expects a &amp;#8220;tag&amp;#8221; object as a parameter. We&amp;#8217;ll go into more detail about the &amp;#8220;tag&amp;#8221; soon.&lt;/p&gt;

&lt;p&gt;Next we&amp;#8217;ll use the component in the page template via the tag, prefixed with the namespace &amp;#8216;trellis&amp;#8217;:&lt;/p&gt;

&lt;pre class="brush: ruby;"&gt;
class Home &lt; Page
  template %[
    &amp;lt;html xml:lang="en" lang="en" 
          xmlns:trellis="http://trellisframework.org/schema/trellis_1_0_0.xsd" 
          xmlns="http://www.w3.org/1999/xhtml"&gt;
      &amp;lt;body&gt;
        &lt;h1&gt;Some Interesting Pictures...&lt;/h1&gt;
        &amp;lt;trellis:flickr_interestingness/&gt;
      &amp;lt;/body&gt;
    &amp;lt;/html&gt;
  ], :format =&gt; :html
end
&lt;/pre&gt;

&lt;p&gt;The return value of the render method is expected to be a string value that will be rendered on the page using the component. In our simple case we simply hardcoded a return value with the expected HTML snippet.&lt;/p&gt;

&lt;p&gt;&lt;img src="/files/flickr_009.png" alt="Passed Render Component Test"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 9 - Passed Render Component Test&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As you can see a Trellis stateless component is simply a way to produce content; a tag that it is available to a Trellis template.&lt;/p&gt;</description>
      <pubDate>Wed, 10 Feb 2010 14:31:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:6b8e64ec-72ce-40c3-b853-dc21807521b7</guid>
      <comments>http://www.trellisframework.org/2010/02/10/trellis-tutorial-3-creating-a-stateless-component#comments</comments>
      <category>component</category>
      <category>stateless</category>
      <enclosure url="http://www.trellisframework.org/files/flickr_001.png" type="image/png" length="35830"/>
      <link>http://www.trellisframework.org/2010/02/10/trellis-tutorial-3-creating-a-stateless-component</link>
    </item>
    <item>
      <title>Trellis Tutorial #2 - Routing in Trellis</title>
      <description>&lt;h2&gt;Routing in Trellis&lt;/h2&gt;

&lt;p&gt;Trellis provides a per page routing scheme heavily based on Sinatra&amp;#8217;s routing with a few more additions and magic of its own. In this short article I&amp;#8217;ll cover the most common usages of routing. For more examples check out the included routing example in the Trellis distribution (examples/routing) and the RSpec specs for the routing classes (test/router_spec.rb)&lt;/p&gt;

&lt;h3&gt;Absolute Routes&lt;/h3&gt;

&lt;p&gt;Routing in Trellis works at the page level. Each page in an application has a base default route which is the page class name lowercased and underscored. For example, if you have a page class called ChuckNorrisIsTheMan:&lt;/p&gt;

&lt;pre class="brush: ruby;"&gt;
class ChuckNorrisIsTheMan &lt; Trellis::Page
  template do html { body { text %[Chuck can kick you before you blink] }} end
end
&lt;/pre&gt;

&lt;p&gt;Then the page would be accessible at /chuck_norris_is_the_man. For more complex routing needs Trellis provides the &amp;#8220;route&amp;#8221; class method available on the Page class. The route method takes a routing pattern. The simplest routing pattern is just an absolute route:&lt;/p&gt;

&lt;pre class="brush: ruby;"&gt;
class WhoaPage &lt; Trellis::Page
  route '/whoa'

  template do html { body { text %[whoa!] }} end
end
&lt;/pre&gt;

&lt;p&gt;With an absolute route is easy to add route spaces like /admin and the like.&lt;/p&gt;

&lt;h3&gt;Parameterized Routes&lt;/h3&gt;

&lt;p&gt;But things only get interesting when we start passing values via our URLs. Let&amp;#8217;s say that we wanted to have a page that can be take a routing pattern representing a date. Trellis routing patterns can take named parameters so we could have a page with a complex route in a format like /day_of_the_year/2009/11/21. The page RoutedDifferentlyWithParams below shows how to create such a route:&lt;/p&gt;

&lt;pre class="brush: ruby;"&gt;
class RoutedDifferentlyWithParams &lt; Trellis::Page
  route '/day_of_the_year/:year/:month/:day'

  def parse_date
    Date.parse("#{@month}/#{@day}/#{@year}").strftime("%e %B, %Y")
  end

  def on_select
    self
  end

  template %[
    &lt;html xml:lang="en" lang="en" 
         xmlns:trellis="http://trellisframework.org/schema/trellis_1_0_0.xsd" 
         xmlns="http://www.w3.org/1999/xhtml"&gt;
     &lt;h2&gt;@{parse_date}@ is the @{Date.parse(@month + '/' + @day + '/' + @year).yday.ordinalize.to_s}@ day of the year!&lt;/h2&gt;
     &lt;br/&gt;
     &lt;trellis:action_link&gt;Refresh&lt;/trellis:action_link&gt;
    &lt;/html&gt;
  ], :format =&gt; :eruby
end
&lt;/pre&gt;

&lt;p&gt;A route pattern can take named parameters using the colon + ruby identifier syntax. Any matched parameters are available as instance variables to the page. For example in the parse_date method we are taking the 3 incoming parameters turning them into a String in the format mm/dd/year, parsing the String into a Date object and finally formatting it with strftime. In the template we then print the parsed date and what day of the year it corresponds to as shown in Figure 1.&lt;/p&gt;

&lt;p&gt;&lt;img src="/files/routing_001.png" alt="Trellis Routing"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 1 - Date Route Example&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;Optional Parameters&lt;/h3&gt;

&lt;p&gt;Trellis routes can also take optional parameters which should be pre and post-fixed with a question mark (?). For example, you could create a route such as:&lt;/p&gt;

&lt;pre class="brush: ruby;"&gt;
route '/?:foo?/?:bar?'
&lt;/pre&gt;

&lt;p&gt;The route above will match &amp;#8216;/chuck/norris&amp;#8217;, &amp;#8216;/chuck&amp;#8217; and &amp;#8216;/&amp;#8217; and both &amp;#8216;foo&amp;#8217; and &amp;#8216;bar&amp;#8217; will be available to the page as @foo and @bar respectively. In the case of the pattern &amp;#8216;/chuck/norris&amp;#8217;, @foo will be &amp;#8216;chuck&amp;#8217; and @bar will be &amp;#8216;norris&amp;#8217;. For &amp;#8216;/chuck&amp;#8217;, @foo will be &amp;#8216;chuck&amp;#8217; and @bar will be nil. While for &amp;#8216;/&amp;#8217; both @foo and @bar will be nil.&lt;/p&gt;

&lt;h3&gt;Wildcard Parameters&lt;/h3&gt;

&lt;p&gt;Trellis page routes also support wildcard parameters via using and asterisk (*). For example a simple catch-all pattern could be expressed as:&lt;/p&gt;

&lt;pre class="brush: ruby;"&gt;
route '/*'
&lt;/pre&gt;

&lt;p&gt;Any values captured by the &amp;#8216;*&amp;#8217; are available in the @splat instance variable which is an array of all captured anonymous parameters. Wildcard parameters can also be mixed with named parameters and absolute paths, for example all the routes below are valid routes:&lt;/p&gt;

&lt;pre class="brush: ruby;"&gt;
route '/awesomeness/*/foo/*/*'
route '/mixed/:foo/*'
&lt;/pre&gt;

&lt;p&gt;Also parameters do not need to be delimited only by a forward slash, for example the following pattern is also valid:&lt;/p&gt;

&lt;pre class="brush: ruby;"&gt;
route '/downloads/:file.:ext'
&lt;/pre&gt;

&lt;h3&gt;Route Sorting&lt;/h3&gt;

&lt;p&gt;In frameworks with powerful routing capabilities, the order of the route declarations is typically used to determine how they are matched against an incoming request. I felt that this was a somewhat goofy convention. In Trellis routes are sorted according to their complexity. For example, let&amp;#8217;s take a look at one of specs for the Trellis router class:&lt;/p&gt;

&lt;pre class="brush: ruby;"&gt;
it "should be able to be sorted by 'matchability'" do
  route_1 = Trellis::Router.new(:path =&gt; '/hello/:one/:two') 
  route_2 = Trellis::Router.new(:path =&gt; '/hello/jim/:last')
  route_3 = Trellis::Router.new(:path =&gt; '/hello/*')
  route_4 = Trellis::Router.new(:path =&gt; '/hello/*/:foo/*')

  routes = [ route_1, route_2, route_3, route_4 ].sort {|a,b| b.score &lt;=&gt; a.score }

  routes[0].should be(route_4)
  routes[1].should be(route_2)
  routes[2].should be(route_1)
  routes[3].should be(route_3)
end
&lt;/pre&gt;

&lt;p&gt;As you can see route patterns are compiled inside a Router object. Router objects have a score. For the routes above when sorted by score the order ends up being:&lt;/p&gt;

&lt;pre class="brush: ruby;"&gt;
'/hello/*/:foo/*'
'/hello/jim/:last'
'/hello/:one/:two'
'/hello/*'
&lt;/pre&gt;

&lt;p&gt;The score value represents the matching power of a route and it is used to try the more specific routes first. For example in any list of routes, the &amp;#8216;catch all&amp;#8217; route &amp;#8216;/*&amp;#8217; is always evaluated next to last. The default Trellis route /page[.event[_source]][/value][?query_params] is always evaluated last.&lt;/p&gt;

&lt;h3&gt;Conclusions&lt;/h3&gt;

&lt;p&gt;This short article shows the flexibility of Trellis&amp;#8217; page routing scheme. As I mentioned before it is a port of the great work done by the Sinatra framework with some additions of our own. In future installments we will exploit this flexibility to create robust applications with clean &amp;#8220;pretty&amp;#8221; routes.&lt;/p&gt;</description>
      <pubDate>Fri, 29 Jan 2010 17:13:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:79d57444-ba1c-4423-803d-01776059c2bc</guid>
      <comments>http://www.trellisframework.org/2010/01/29/trellis-tutorial-2-routing-in-trellis#comments</comments>
      <category>routing</category>
      <category>routes</category>
      <link>http://www.trellisframework.org/2010/01/29/trellis-tutorial-2-routing-in-trellis</link>
    </item>
    <item>
      <title>Trellis at RubyNation 2010</title>
      <description>&lt;p&gt;Brian Sam-Bodden (me) will be giving a presentation on the Trellis Framework at RubyNation this coming April (9-10) in Reston, VA. Check out RubyNation at &lt;a href="http://www.rubynation.org"&gt;http://www.rubynation.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.rubynation.org/"&gt;
  &lt;img src="http://www.rubynation.org/images/conference/badges/2010/rubyWebBadgeSpeaker.png"/&gt;
&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Wed, 20 Jan 2010 14:55:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:f735feb7-8177-4bbf-8cb5-6624a88948d9</guid>
      <comments>http://www.trellisframework.org/2010/01/20/trellis-at-rubynation-2010#comments</comments>
      <category>conferences</category>
      <category>presentations</category>
      <link>http://www.trellisframework.org/2010/01/20/trellis-at-rubynation-2010</link>
    </item>
    <item>
      <title>Trellis Tutorial #1 - The HiLo Web Application</title>
      <description>&lt;h2&gt;Trellis HiLo Game&lt;/h2&gt;

&lt;p&gt;The Trellis Hilo Game is a simple application where the user guesses a number between one and ten. This example was &amp;#8216;borrowed&amp;#8217; from the Apache Tapestry project and ported to Trellis.&lt;/p&gt;

&lt;p&gt;The simple diagram shows the application&amp;#8217;s page flow, which consists of three pages: Start, Guess and Game over.&lt;/p&gt;

&lt;p&gt;&lt;img src="/files/hilo_001.png" alt="Trellis Hilo Page Flow"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 1 - Hilo Application Page Flow&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Start page simply provides a link to start guessing. The guessing happens in the Guess page. The Guess page presents the user with ten links for the numbers from 1 to 10. When the user selects incorrectly the page responds with an appropriate message such as &amp;#8220;Guess X is too low&amp;#8221; or &amp;#8220;Guess X is too high&amp;#8221;. If the user selects the correct number the application navigates to the GameOver page, which reports how many guesses it took to find the correct answer.&lt;/p&gt;

&lt;h3&gt;The Application Structure&lt;/h3&gt;

&lt;p&gt;The HiLo web application structure consists of 1 Ruby file and possibly 3 XHTML templates:&lt;/p&gt;

&lt;p&gt;&lt;img src="/files/hilo_002.png" alt="Trellis Hilo Directory Structure"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 2 - Trellis Hilo Directory Structure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It is not required that you organized your application as shown but if you want to avoid having to specify your view template locations, Trellis will assume the structure above when searching for a template.&lt;/p&gt;

&lt;h3&gt;Installing Trellis&lt;/h3&gt;

&lt;pre class="brush: shell; gutter: false;" &gt;
gem install trellis
&lt;/pre&gt;

&lt;h3&gt;The Trellis Application Class&lt;/h3&gt;

&lt;p&gt;Let&amp;#8217;s start at the beginning and create a Trellis application. Let&amp;#8217;s call it HiLoGame and tuck it in a module named Hilo.  At the top we&amp;#8217;ll require the RubyGems and Trellis Gems and to simplify the code we&amp;#8217;ll include the Trellis module:&lt;/p&gt;

&lt;pre class="brush: ruby;"&gt;
require 'rubygems'
require 'trellis'

include Trellis

module HiLo
  class HiLoGame &lt; Application
    home :start
  end
end
&lt;/pre&gt;

&lt;p&gt;The class HiLoGame extends Trellis::Application which represents a Web Application composed of one or more pages. Inside the class body the &amp;#8216;home&amp;#8217; class method is used to declare the home page of the application. That is, the entry point and what the URI &amp;#8216;/&amp;#8217; will be resolved to. In the case of the HiLoGame application the entry point is indicated by the symbol :start. The Trellis convention is that there will be a Trellis Page class named Start.&lt;/p&gt;

&lt;h3&gt;The Start Page&lt;/h3&gt;

&lt;p&gt;The Start page will provide a simple welcome message and a link for the users to start guessing numbers. Let&amp;#8217;s start with the view and show the HTML markup:&lt;/p&gt;

&lt;pre class="brush: html;"&gt;
&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;
    &amp;lt;head&gt;
        &amp;lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/&gt;
        &amp;lt;title&gt;Hi/Lo Game Start Page&amp;lt;/title&gt;
    &amp;lt;/head&gt;
    &amp;lt;body&gt;
      &amp;lt;h1&gt;Hi/Lo Guess&amp;lt;/h1&gt;
      &amp;lt;p&gt;I'm thinking of a number between one and ten ... &amp;lt;/p&gt;
      &amp;lt;p&gt;
        &amp;lt;trellis:action_link&gt;Start guessing&amp;lt;/trellis:action_link&gt;
      &amp;lt;/p&gt;
    &amp;lt;/body&gt;
&amp;lt;/html&gt;
&lt;/pre&gt;

&lt;p&gt;Everything in the markup above should be familiar except for the &amp;lt;trellis:action_link&amp;gt; tag. The tag represents one of Trellis&amp;#8217; core components, the ActionLink component. ActionLink is a simple stateless component that provides a hyperlink to trigger an action. The URI produced represents the creation of an event. Events in Trellis have names. The name of the event generated by the ActionLink component is called &amp;#8220;select&amp;#8221;.
Now that we have a template, let&amp;#8217;s create the Trellis page class that will serve that template. The Start page is a simple class that extends the Trellis Page class. &lt;/p&gt;

&lt;pre class="brush: ruby;"&gt;
  class Start &lt; Page
  end
&lt;/pre&gt;

&lt;h4&gt;Launching the Application&lt;/h4&gt;

&lt;p&gt;Next, let&amp;#8217;s add a bit of code so that we can launch the application. In order to run the application we need an instance of HiLoGame for which we will invoke the start() method, as follows:&lt;/p&gt;

&lt;pre class="brush: ruby;"&gt;
  web_app = HiLoGame.new
  web_app.start if __FILE__ == $PROGRAM_NAME
&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;em&gt;The HiLoGame and all page classes are contained inside the HiLo module as well as the two lines above to instantiate and run the application.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With the skeleton page in place and its corresponding template we can now run the application like:&lt;/p&gt;

&lt;pre class="brush: shell; gutter: false;"&gt;
ruby hilo.rb
&lt;/pre&gt;

&lt;p&gt;At the console you should see output similar to (Trellis uses Mongrel by default):&lt;/p&gt;

&lt;pre class="brush: shell; gutter: false;"&gt;
091005 19:51:51 INFO: Starting Trellis Application HiLo::HiLoGame on port 3000 
091005 19:51:51 INFO: watching /Users/bsbodden/Documents/projects/trellis/examples/test/source/../html/ for template changes... 
&lt;/pre&gt;

&lt;p&gt;Launch your browser and point it to http://localhost:3000 and you should see the home page of our Hilo application as shown next:&lt;/p&gt;

&lt;p&gt;&lt;img src="/files/hilo_003.png" alt="Trellis Hilo Start Page v1.0"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 3 - Trellis Hilo Start Page&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;On the console we can see the GET request for the root &amp;#8220;/&amp;#8221; URI:&lt;/p&gt;

&lt;pre class="brush: shell; gutter: false;"&gt;
090921 15:30:22 INFO: 127.0.0.1 - - [21/Sep/2009 15:30:22] "GET / HTTP/1.1" 200 558 0.0025 
&lt;/pre&gt;

&lt;p&gt;By now, you probably have already clicked on the &amp;#8220;Start Guessing&amp;#8221; link and the application has appropriately blown chunks and showed you an error page describing the problem such as:&lt;/p&gt;

&lt;p&gt;&lt;img src="/files/hilo_004.png" alt="Trellis Error Page"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 4 - Trellis Error Page&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;Events&lt;/h4&gt;

&lt;p&gt;The error page indicates that the application could not find a method named on_select(). If you remember I mentioned that the ActionLink component generates an event called &amp;#8216;select&amp;#8217;. When a page gets an event with a name &amp;#8220;bacon&amp;#8221;, it looks for an event handler method named on_bacon().&lt;/p&gt;

&lt;p&gt;&lt;img src="/files/hilo_005.png" alt="Start Guessing Link"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 5 - Start Guessing Link&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The return value of an event handler method determines where the application will navigate to next. Inside of a page for example, returning &amp;#8216;self&amp;#8217; will make the application navigate to the same page. &lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s add a place holder on_select() event handler to the start page and for now let&amp;#8217;s just make it navigate back to the start page.&lt;/p&gt;

&lt;pre class="brush: ruby;"&gt;
    def on_select
      self
    end
&lt;/pre&gt;

&lt;p&gt;Go back to / or /start to refresh the page. If you hover over the link on the page you can see the URI generated by the ActionLink component. As you can see a page has an /events namespace in which we can &amp;#8216;drop&amp;#8217; and event. In this case &amp;#8216;select&amp;#8217;. You can see the pattern now: /page/events/event&lt;/p&gt;

&lt;table&gt;
  &lt;tr&gt;
    &lt;td&gt;Component&lt;/td&gt;
    &lt;td&gt;Event Produced&lt;/td&gt;
    &lt;td&gt;Event Handler&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;ActionLink&lt;/td&gt;
    &lt;td&gt;select&lt;/td&gt;
    &lt;td&gt;on_select()&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;Clicking on the &amp;#8220;Start Guessing&amp;#8221; link again should now take you back to the start page.&lt;/p&gt;

&lt;p&gt;By now you have probably noticed that it wasn&amp;#8217;t necessary to restart the application after each change. Trellis will detect changes to your application&amp;#8217;s code and templates and automatically reload them.
We can now navigate to the same page but what we really want to do is navigate to the not-yet-existent Guess page.&lt;/p&gt;

&lt;h4&gt;Navigating To Other Pages&lt;/h4&gt;

&lt;p&gt;Trellis pages need to declare any other pages that they might redirect to. To declare the possible page transitions we use the class method &amp;#8216;pages&amp;#8217;. Since the Start page can only navigate to the Guess page, we declare that using the :guess symbol referring to a Guess page that we&amp;#8217;ll develop next.&lt;/p&gt;

&lt;pre class="brush: ruby;"&gt;
  class Start &lt; Page
    pages :guess

    def on_select
      self
    end
  end
&lt;/pre&gt;

&lt;p&gt;Injected pages such as :guess get their own instance variables (@guess) available to the page. We can change the on_select() event handler to return an instance of the Guess page and also perform some work along the way as shown below:&lt;/p&gt;

&lt;pre class="brush: ruby;"&gt;
    def on_select
      @guess.initialize_target
    end
&lt;/pre&gt;

&lt;p&gt;Obviously we haven&amp;#8217;t yet implemented the initialize_target() method, hell we don&amp;#8217;t even have a Guess page yet!&lt;/p&gt;

&lt;h4&gt;Stand In Pages&lt;/h4&gt;

&lt;p&gt;Yet, if you refresh the start page and click the &amp;#8220;Start Guessing&amp;#8221; link you should see something like:&lt;/p&gt;

&lt;p&gt;&lt;img src="/files/hilo_006.png" alt="Trellis Stand-In Page for Guess"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 6 - Trellis Stand-In Page for Guess&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In development mode (which is the default) Trellis will generate synthetic pages or &amp;#8220;Stand-In&amp;#8221; pages for any injected pages for which it cannot find an implementation. Invoking any method on a stand in page returns the page object itself. In the case of the on_select() method, the return value is the guess page itself, since calling the initialize_target() method will just return the guess page object.&lt;/p&gt;

&lt;p&gt;Stand-In pages enable incremental development, you can think of them as virtual scaffolding that automatically fades away as you provide a page&amp;#8217;s implementation.&lt;/p&gt;</description>
      <pubDate>Tue, 06 Oct 2009 15:08:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:4816dde8-18f3-4420-8e13-3e3451f8d4e4</guid>
      <comments>http://www.trellisframework.org/2009/10/06/trellis-tutorial-1-the-hilo-web-application#comments</comments>
      <category>trellis</category>
      <category>tutorial</category>
      <category>ruby</category>
      <category>web</category>
      <enclosure url="http://www.trellisframework.org/files/hilo_002.png" type="image/png" length="44389"/>
      <link>http://www.trellisframework.org/2009/10/06/trellis-tutorial-1-the-hilo-web-application</link>
    </item>
    <item>
      <title>LoneStar RubyConf Presentation PDF</title>
      <description>&lt;p&gt;Here&amp;#8217;s the PDF for my LoneStar RubyConf session on Trellis &lt;a href="http://lonestarrubyconf.com/"&gt;http://lonestarrubyconf.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a name="PDF File" href="http://www.trellisframework.org/files/trellis.pdf"&gt;trellis.pdf&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Sat, 29 Aug 2009 11:59:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:d21ed902-482a-4f26-8977-af7ad0cd2fca</guid>
      <comments>http://www.trellisframework.org/2009/08/29/lonestar-rubyconf-presentation-pdf#comments</comments>
      <category>presentation</category>
      <category>pdf</category>
      <category>trellis</category>
      <link>http://www.trellisframework.org/2009/08/29/lonestar-rubyconf-presentation-pdf</link>
    </item>
    <item>
      <title>Trellis 0.0.1 on GitHub</title>
      <description>&lt;p&gt;The experimental code base for the Trellis framework is now on GitHUb at&lt;/p&gt;

&lt;p&gt;&lt;span&gt;&lt;a href="http://github.com/bsbodden/trellis"&gt;http://github.com/bsbodden/trellis&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span&gt;&lt;a href="git://github.com/bsbodden/trellis.git"&gt;git://github.com/bsbodden/trellis.git&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;It is rough around the edges but it embodies the general principles of what I want in a Ruby Component-based Web Framework. It is by no means production ready.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pivotal Tracker&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;span&gt;&lt;a href="http://www.pivotaltracker.com/projects/24696"&gt;http://www.pivotaltracker.com/projects/24696&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RubyForge Page&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;span&gt;&lt;a href="http://rubyforge.org/projects/trellis/"&gt;http://rubyforge.org/projects/trellis/&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Install&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;gem install trellis&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HelloWorld&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;The simple Hello World example consists of one Application and one Page. The Application defines its home page as the symbol :hello which is resolved to the Home page class. The Home page provides its markup via the template class method which takes a block of Markaby. Finally the application is launched by instantiating the Application object and using the start method (runs on port 3000 by default)&lt;/p&gt;

&lt;p&gt;&lt;pre class="brush: ruby;"&gt;
require 'rubygems'
require 'trellis'

module Hello
  class HelloWorld &lt; Trellis::Application
    home :home
  end

  class Home &lt; Trellis::Page
    template do html { body { h1 "Hello World!" }} end
  end
end

Hello::HelloWorld.new.start if __FILE__ == $PROGRAM_NAME
&lt;/pre&gt;&lt;/p&gt;</description>
      <pubDate>Sat, 29 Aug 2009 11:37:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:7dda6aab-fe3f-4240-8f4f-33f8852cc414</guid>
      <comments>http://www.trellisframework.org/2009/08/29/trellis-0-0-1-on-github#comments</comments>
      <category>trellis</category>
      <category>helloworld</category>
      <link>http://www.trellisframework.org/2009/08/29/trellis-0-0-1-on-github</link>
    </item>
  </channel>
</rss>
