giant robots smashing into other giant robots

Written by thoughtbot

dancroak

Step right up, win a $1,295 prize

Here at thoughtbot, we love a good contest.

It’s been too long since the last one, so here we go again. Now since we all kind of know each other, I’m sure we’ll all feel comfortable within the confines of the honor system.

Follow @thoughtbot

That’s it. All followers of the @thoughtbot Twitter account will be eligible to win a prize next week. We’ll pick a random winner for the following prizes.

  • On Monday, winner gets a Widgetfinger account.
  • On Tuesday, winner gets a Tadpole Hoptoad account.
    (4 projects, 4 users, Lighthouse integration)
  • On Wednesday, winner gets a Toad Hoptoad account.
    (16 projects, 16 users, SSL, Lighthouse integration)
  • On Thursday, winner gets a Bullfrog Hoptoad account.
    (32 projects, 32 users, SSL, Lighthouse integration)

Open source markets

Since Vegas has yet to release odds, we’ve created the Open Source prediction market to answer burning questions we have, such as:

Who will win a Ruby Heroes Award at RailsConf 2009?

I’ve got my money on James Golick, but Jason thinks he’s a long shot.

We’re also constantly faced with a decision about which open source project to use for certain tasks:

To make the markets measurable, we’re using github watchers as a proxy for “preferred open source project” and setting a date of RailsConf so people think relatively long-term.

When you’re atop the leaderboard at high noon EST on Friday, you win the big prize:

One FREE ticket to a thoughtbot training class,
a $1,295 value.

So trade early trade often at the Open Source prediction market, and tell your friends.

cpytel

Widgetfinger: Versioning and Google Apps Support (or, how I learned to stop worrying and love Google Apps)

We’ve rolled out a few updates to Widgetfinger, our simple content management system for simple websites, and we wanted to tell you about them.

Content Versioning

The biggest change is that you can now review and compare past revisions to your content.

The special treat here is that we’ve actually been tracking every change since Widgetfinger launched last year. When building Widgetfinger, we realized after we started work on the Revisions functionality that it shouldn’t be a feature for v1. Since most of the code was in place, well tested, and functioning, we decided to leave it in place so that when the revisions functionality came back up to the top of the priority list, we’d roll it out with access to all prior revisions.

Support for Google Apps

The other new feature we’ve rolled out is built-in support for Google Apps when using Widgetfinger DNS.

Widgetfinger is meant to take over responsibility for the hosting of your simple “brochure” type website, and that includes Web Pages, DNS, and Email. We’ve had some requests to use Google Apps instead of the built in email hosting, and we’re now happy to oblige. Enabling this for your site is as easy a signing up for Google Apps and checking a checkbox in Widgetfinger, and providing the ‘finger with your Google Apps verification code.

Doing so will cause the proper DNS entries to be created to fully support Google Apps for email, calendar, and the other Google Apps services. For more information on how to set this up, see the Widgetfinger help section on it.

Let us know if you have any thoughts about this or any other Widgetfinger features, we love to hear from you. If you’ve never tried Widgetfinger before, we encourage you to give it a shot, and let us know what you think.

cpytel

Custom Tags in Liquid

We recently rolled out a new feature in Widgetfinger that allows you to quickly build navigational menus

{% navigation %}
  {% link About %}
  {% link Services %}
  {% link Contact %}
{% endnavigation %}

The above tags will create the following navigation HTML.

<ul id="navigation">
  <li class="about"><a href="/about">About</a></li>
  <li class="services"><a href="/services">Services</a></li>
  <li class="contact"><a href="/contact">Contact</a></li>
</ul>

As we’ve mentioned before, Widgetfinger uses Liquid, which provides safe templates that don’t affect the security of the server they are rendered on.

Liquid allows you to write custom tags, and that’s exactly what the new navigation tag in Widgetfinger is.

Writing tags in Liquid is fairly straightforward, once you get the hang of it. Lets talk a look at what goes into the navigation tag.

Liquid provides for two different types of Tags, a non-block tag, and a block tag. Since our navigation tag has a starting and ending tag, with other tags inside of it, that’s a block tag, so that’s what we’ll be implementing.

When the Liquid template is parsed, an instance of our Navigation block tag is initialized

class NavigationBlock < Liquid::Block
  include LiquidExtensions::Helpers
  attr_accessor :links
      
  def initialize(name, params, tokens)
    @links = []
    super
  end

In the initialize method, the name is the name of the tag, and params is the “extra stuff” given to the tag. The navigation tag doesn’t have anything extra given to it, but the {% contactform :to email@example.com %} tag in Widgetfinger does (the :to email@example.com would be given in the params as a string). Finally, the tokens are all of the other tags that appear within this block tag, including the closing endnavigation tag.

In the initialize method above for the navigation tag, we simply initialize the links i-var and call super. The Liquid::Block initialize method calls parse, which parses each of the tokens, causing each of the tags within the block to be parsed. This means that any valid liquid tag can appear inside your block. If parse comes across any tag that it doesn’t recognize, it calls an unknown_tag method on your Block, allowing you to handle it as you see fit. Here is the unknown_tag method for the Navigation block.

def unknown_tag(name, params, tokens)
  if name == "link"
    handle_link_tag(params)
  else
    super
  end
end

What we’re doing here is pretty straightforward. The only custom tag that we want to provide within the Navigation tag is the link tag. So, when check to see whether the tag is the link tag, otherwise, we call the unknown_tag method in the base class. If know handler is ever found for a tag, that’ll cause a Liquid::SyntaxError exception to occur. The handle_link_tag method gets a little more interesting, as it provides the meat of the additional parameters you can pass a link tag.

def handle_link_tag(params)
  args = split_params(params)
  element_id = args[0].downcase
  if args.length > 1
    match = (args[1].first == "/" ? args[1][1..-1] : element_id)
    @links << { :name => args[0], :match => match, :url => args[1], :id => element_id, :extra_class => args[2] }
  else
    @links << { :name => args[0], :match => element_id, :url => "/#{element_id}", :id => element_id }
  end
end

def split_params(params)
  params.split(",").map(&:strip)
end

In the code above, we’re taking all of the parameters passed to link tag. If there is only one, then we’re going to use several sensible defaults to build the navigation element. If there is more then one, then tag defaults are being overridden. For more information on the addition parameters of the link tag, view the Widgetfinger documentation on it.

Finally, once everything is parsed, and the template is going to be outputted, the render method on the Block is called. Here is what the render method looks like for the Navigation tag.

def render(context)
  render_erb(context, 
             'editor/navigation.rhtml',
             :links => @links,
             :registers => context.registers)
end

The render method receives a Context. This is provided by Liquid and the Context and its registers are essentially a hash where you can store things that’ll be passed around for the parsing of the template. That’s an over simplification, but it should suffice for our purposes here.

The render_erb method is provided by LiquidExtensions::Helpers, which you may have noticed that we included above. This is something we devised in order to open it up so Widgetfinger tags would be able to render Erb, and have access to the normal Rails view helpers. Here’s how it works.

def render_erb(context, file_name, locals = {})
  context.registers[:controller].send(:render_to_string, :partial => file_name, :locals => locals)
end

After floundering around for a while trying to get Erb Rendering to work by doing it manually, using Erb directly, and then having to deal with making the Rails view helpers available in that Erb, we realized that we could just add the Widgetfinger controller responsible for causing the Liquid templates to be parsed to the Liquid context registers. From that controller, we can simple call :render_to_string on it. This allows us to make regular Rails partial that are responsible for the output of the tags, that have access to all of the normal view helpers we’re used to.

In the case of the Navigation tag partial, we’ve composed a hash of links to draw, and the partial outputs it as we expect.

<ul id="navigation">
  <% links.each do |link| -%>
    <li class="<%= link[:id] %><%= match_class registers, link %><%= extra_class link %>">
      <%= link_to link[:name], link[:url] %>
    </li>
  <% end -%>
</ul>

Finally, in order for Liquid to know about our new navigation tag, we have to register it like this.

Liquid::Template.register_tag 'navigation', NavigationBlock

Lets talk about Testing

In Widgetfinger, the tags are placed in lib/liquid_extensions.rb, and we provide unit tests for this code in test/unit/liquid_extensions_test.rb.

I won’t cover the full extent of the tests here, but to provide an example of a basic test case that ensures that the proper erb file is rendered.

context "a NavigationBlock tag" do
  setup do
    @tag = LiquidExtensions::Classes::NavigationBlock.new 'navigation', '', ['{% endnavigation %}']
  end
      
  should "render in erb the navigation element when sent render" do
    context = stub(:registers => stub)
    @tag.expects(:render_erb).with(context,
                                  'editor/navigation.rhtml',
	                             :links => [],
	                             :registers => context.registers).returns ''
    @tag.render context
  end
end

In the test code above, we instantiate an instance of the navigation block tag, with the proper tag name, no parameters, and the ending tag token.

The test then provides a stub context with a stub registers. We then create an expectation that when the render Erb method will be called with the expected arguments: the proper partial, an empty links array (because there are no links in the tag, as evidenced by the lack of links in the tokens, and the mock registers.

We then call the render method on the tag, which causes the whole thing to go into action.

Now that you know how to properly instantiate the tag, and stub out some important pieces of it, providing additional unit tests for the other portions of the tag, particularly those relating to handling the link tags inside of it should be clear.

cpytel

Keeping the Pressure On

Rather than spending our surplus on gold rings, hookers, and fur coats, we’ve been keeping the pressure on. Over the last 3 months we’ve released 5 new products, services, or open source projects. I figured we’d take a moment to remind you of them. Consider this a clip show of GRSIOGR.

In May

  • We launched a new t-shirt store, Tee-Bot. The store currently features 3 Ruby on Rails inspired shirts, and we plan on releasing more soon. To check it out, visit the store.
  • We released widgetfinger, a simple content management system for simple websites. Widgetfinger isn’t just a CMS, its a complete hosted service for design firms, so they no longer have to deal with the annoyance of maintaining their own server or separate hosting accounts. Find out more and get started at the widgetfinger website.

In June

  • We released factory_girl, a fixture replacement library that follows the Factory pattern. The response to factory_girl has been extremely positive, and we’ve had great success in converting our existing apps over, either replacing custom factory code, or completely replacing fixtures. For more information, go to our factory_girl page.

In July

  • We announced our new service, Rails Training. We’ll be kicking it off with a session at Lone Star Ruby Conference, and then quickly following it up with our Advanced Ruby on Rails session in Boston on October 14th. For more information, and to register, go the our Ruby on Rails training page
  • We launched Hoptoad, the hosted exception catcher. A replacement for exception_notification, Hoptoad sends all your exceptions to a centralized service, detects duplicates, and only notifies you about new, unique errors. We followed that up with updates that included an API and Open ID authentication. To start riding the toad yourself, visit the Hoptoad website.

All this while presenting at RailsConf, making updates to shoulda, paperclip, squirrel, and jester, doing excellent work for our clients, keeping a 40 hour work week, and just generally getting the job done.

We’ve got a great team, and I appreciate everyone’s work with everything we’ve accomplished.

cpytel

Screencast: Creating a website in Widgetfinger

Its been just under 2 months since we first launched Widgetfinger, and during that time we’ve had several hundred signups, some great feedback from users and customers, and we’ve continued to refine the product – focusing on how best to deliver on its core premise – being a simple content management for simple websites.

Over the weekend, I took the time to create a quick screencast showing the basics of getting a website created in Widgetfinger.

Watch the screencast in HD on Vimeo.

This is our first screencast, so, if you have any thoughts about what you might like to see covered in future ones, the quality of this one, etc. please let me know.

We’ll be releasing some interesting new features over the next few months. Stay tuned.