StaticMatic 2 is coming

May 14th, 2008

StaticMatic is currently going through a major over-haul. There are loads of great features in the works as well as changes to the way to core works.

The major change is that StaticMatic 2 will now use ActionPack. This means we get loads of great new features:

  • Any templating language you like
  • Access to all ActionView helpers

On top of this we also now have:

  • Rake tasks for commands
  • Better error handling
  • 'Modified Date' sensitive building of static files - StaticMatic now only builds files you've modified

We're also now hanging out with cool kids on github: http://github.com/stevebartholomew/staticmatic/tree/master.

Call to Arms

Now, we need your help. StaticMatic 2 is not yet feature complete. There is still a lot of work to do with getting all the current features in as well as working up the new stuff.

What we need is for you to try out the new features on your existing StaticMatic sites. The great thing is, you can run the new version without conflicting with the current one:

  1. Download the edge version into your site's root directory:

    ~/Sites/mygreatsite $ git clone git://github.com/stevebartholomew/staticmatic.git

  2. Create a Rakefile in your site's root containing this:

    require 'rake' require 'staticmatic/lib/tasks/staticmatic'

That's it. You can use the new StaticMatic commands:

rake preview
rake build

Or you can use your Gem version:

staticmatic preview .
staticmatic build .

The main thing that needs testing is integration into ActionView - try out the helpers, see what happens. There's a fair few hoops to jump through to make ActionView happy being separated from ActionController so it can play up!

New to StaticMatic?

If you're new to StaticMatic, you can try out the new version by installing the current one and creating a new site:

sudo gem install staticmatic
staticmatic setup mygreatsite

and following the instructions above.

Be Gentle!

There's a fair way to go before we're ready for a release, but hopefully you can still have fun trying out the new features. Join us over at the Google Group for more discussion.

I'm so ridiculously excited about Google App Engine.

In the next year or so, I hope we see more and more hosting companies taking on this model.

Removing the need to worry about servers and scaling will be great for everyone. If you're a hosting company, I strongly recommend you look into how you could do this. Most developers would pay over the odds for the pain of servers & scaling to be taken away.

In my haste to get the new features out, I missed a bug that caused an assigned layout to be inherited by subsequent pages during the build process - d'oh!

However, it's all fixed now so you'll now pick up the correct gem from rubyforge and all should be fine.

gem install staticmatic

StaticMatic 0.3.0

July 26th, 2007

For anyone who isn't a member of the Google Group:

I've just released 0.3 of staticmatic as a gem so it'll be available shortly. The main reason for the release is to fix the 'base_dir' bug that appeared with the latest version of haml.

As part of this update you'll also get static files served from the sites/ directory. There were also a few helper fixes but I've been terrible with my svn log messages :0(

It'll be available via 'gem install staticmatic' soon but if you're desperate for the update, see: http://rubyforge.org/frs/?group_id=3712 to download manually.

In other news, I'll be talking about StaticMatic at the London Ruby Users Group (LRUG) in August: http://lrug.org/meetings/2007/07/23/august-2007-meeting.

If anyone's in the area, come along and show your support!

To coincide with this talk I'm pushing to get a few more features in place, namely: o Multiple Layouts o Per template variables (for things like custom page titles) o The 'official' StaticMatic website

CSV Importer for Rails

July 20th, 2007

Here's a plugin I wrote a while back: CSV Importer for Rails

Importer imports data from a CSV and creates record in the application database.

Basic importing

Organisation.import(:from => '/path/to/file.csv')

This will extract data straight from the CSV

Importing from a stream

Importer will also take a raw StringIO from a form POST:

Organisation.import(:from => params[:organisations])

CSV Columns

If no columns are specified, Importer will use the first row as column names. To set columns, you can use the columns option:

Organisation.import(:from => '/path/to/file.csv', :columns => ['name','email'])

Column Name Mapping

If you have a CSV with column names in the first row that do not correspond with your database columns, you can map them with a hash:

Organisation.import(:from => '/path/to/file.csv', :map => {'Org' => 'name', 'EMail' => 'email'})

This is particularly useful if your CSV is generated automatically from another system that you have no control over.

Associations

Take the row following for example:

"Curve21","South-East England","www.curve21.com","info@curve21.com"

'South-East England' is this organisation's region. If Organisation has_many :regions then we need a way to look up the region in our database using the name specified in this row. Importer achieves this using Proc objects:

Organisation.import(:from => '/path/to/file.csv', :map => {'region' => 'region_id'}, 
                            :associations => {'region_id' => lambda {|a| Region.find_by_name(a) } }

Currently, this is only designed to support only belongsto and hasone relationships.

Error handling

Error handling uses logger at the moment and warns when an associated record was not found

Helpers are a great way to keep your views DRY. Sometimes, however, it's difficult to make a particular helper flexible enough for reuse. You may have common parts with varying content. Rather than ending up with a bunch of slightly altered helpers, try using blocks to clean things up.

For example, I use this markup a lot:

<div class="field">
  <label for="person_name">Name</label>
  <%= text_field :person, :name %>
</div>

Now, I could create a helper to do this giving me the following:

<%= form_field :text, :person, :name %>

I would have the helper figure out that I need a 'text' field with the person's name showing. The problem comes when I need to add a new field. I don't want to have to alter my helper each time I want to use a new field.

So - how about this:

<% form_field "Name" do %>
  <%= text_field :person, :name %>
<% end %>

Much better! Here I can add any type of field I want or add additional information if needed but still managing to removing repetition of the common wrapper.

Here's the helper code:

def form_field(label, &proc)
  concat("<div class=\"field\"><label>#{label}</label>", proc.binding)
  yield
  concat("</div>", proc.binding)
end

Now, this may look slightly odd. Because we are within a code block, we cannot simply return a string of content. Instead, the output must be appended to the view output. proc.binding gives us the context outside of our code block. The concat helper is used to append our content the output buffer in the correct context. The best way I've heard it explained is to think about 'proc.binding' as the actual HTML and the first argument as the content you want to append to it.

For more inspiration, check out the Rails form helpers.

:dependent => :raise

June 22nd, 2007

Ever get woken up at night worrying about referential integrity? "What if someone deletes a Client and we end up with loads of orphaned Tickets in the database!" Just me? Ok...

It's an easy problem to solve, but why not try handling it like this:

class Person < ActiveRecord::Base
  has_many :books, :dependent => :raise
end

>> me = Person.find_by_name("steve")
>> me.destroy
ActiveRecord::HasManyDependentRecordsError: Dependent Book records for Person

Just handle the exception and you're sorted.

Download the plugin here: http://www.stephenbartholomew.co.uk/assets/2007/6/22/dependent_raise.zip

Phew! It's amazing what you learn when you say things like "I can jump over that stream" or "I'm going to add live a live preview server to this app". You kinda have to deliver if you feel it's a good idea. While the former isn't, the later definitely is, so after a week or so of learning about mongrel handlers, previewing is now in StaticMatic. To install, just run:

gem install staticmatic

Here's how it works:

Once you've set up your site directory:

staticmatic setup /path/to/directory

You simply run the preview command:

staticmatic preview /path/to/directory

It'll fire up a server on port 3000 and you'll be able to view the site on http://localhost:3000/. Any changes you make to your haml & sass will be reflected straight away.

If you have any images or other assets, simply put them in the 'site' directory of your staticmatic base directory. The server will look there for anything that isn't '.html' or '.css'.

The preview server is the main feature addition, but there has also been a major overhaul of the code. Test coverage is still not brilliant, but I'm hoping to sort this out next. As always, be aware that this is very much in development so let me know if you get any bugs or issues.

Other things I'll be working on next are sorting out the overall admin of the project as I'm clearly a rubyforge newbie. Thankfully, I have a few people keen to help me out in that regard :0)

In terms of features, I feel like we're almost there in terms of core functionality. The main thing to deal with next is multiple layouts and configuration. I've started laying the foundations of this though so it should be ready v.soon.

Also on the agenda is getting an official site up and running. My design skills are sporadic at best so any ideas would much appreciated.

Oh and I've also set up a google group here so feel free to come along and get the posts going.

Is Rails magic?

June 4th, 2007

I've been known to do a few card tricks in my time. As grown-ups we know that there is a logical answer, but we can still be impressed by something that we don't yet understand. This is what 'magic' is. Something impressive that we don't understand.

When you learn a card trick, you still get enjoyment from seeing it performed, but the 'magic' is no longer there. You have an appreciation of the effort that goes into to looking effortless.

It's the same programming. If you are new to Rails, this can seem magical:

Person.find_by_first_name("Steve")

Where does that method come from? It's not in my models. Pretty magical. But as with card tricks, you know there is a logically explanation.

Later on, you dig into the Rails source code and find this:

def method_missing(method_id, *arguments)
  if match = /^find_(all_by|by)_([_a-zA-Z]\w*)$/.match(method_id.to_s)

Ah right. So Ruby has something called method_missing. That gets called if an invoked method doesn't exist. And look - there is a regular expression that splits out the column from the method call: 'first_name'.

Yeah, there's a lot more after these two lines in ActiveRecord::Base, but the 'magic' is starts to break down when we see this.

To a greater or lesser degree, all programming languages are designed to protect us from things we don't need to deal with daily or aren't directly relevant to the problem we're solving. What makes something 'magic' is lack of knowledge and it's that that can be a problem - not the 'magic' itself. Once you understand what's underneath, it's just a convenient trick to make something easier.

I say keep the magic, but strive to understand it:

  • How does ActiveRecord figure out the correct table for my model?
  • How does Rails know which template to open for my actions?

or even Ruby:

  • How does 1 + 2 work?
  • What makes Ruby not care about data types?

Thanks to everyone who has contacted me about StaticMatic - seems it's not just me that finds it useful!

You can now find StaticMatic on RubyForge: http://rubyforge.org/projects/staticmatic/ where you can find the latest releases and access the code.

I've just released 0.1.0 which contains a small bug fix (thanks Chris!), improvements and additions to the helpers plus helper testing.

Enjoy!

For information on Haml & Sass please see haml.hamptoncatlin.com.

For the latest version:

gem install staticmatic

or visit:

http://rubyforge.org/projects/staticmatic/

What's it all about?

CMS is overrated. A lot of the time, clients want us to do what we do best - well designed pages with structured, accessible and maintainable markup & styling.

CMSs are often sufficient for this, but sometimes they can be restrictive and more cumbersome than just working with good ol' source code. At the same time we want our code to be structured, DRY and flexible.

Enter StaticMatic.

Usage

StaticMatic will set up a basic site structure for you with this command:

staticmatic setup <directory>

After this command you'll have the following files:

<directory>/
  site/
    images/
    stylesheets/
    javascripts/
  src/
    pages/
      index.haml
    layouts/
      application.haml
    stylesheets/
      application.sass

StaticMatic sets you up with a sample layout, stylesheet and page file. Once you've edited the pages and stylesheets, you can generate the static site:

staticmatic build <directory>

All of the pages are parsed and wrapped up in application.haml and put into the site directory.

Templates

StaticMatic adds a few helpers to the core Haml helpers:

= link 'Title', 'url'
= img 'my_image.jpg'

Coming soon:

I'm already extending these to include some neat conventions to speed up coding. For example, in the next version:

= link 'Contact Us'

will produce

<a href="contact_us.html">Contact Us</a>

Or with the Rewriting enabled:

<a href="contact_us">Contact Us</a>

What's Next?

  • Multiple directories of content
  • Layouts based on directory of page template
  • Additional Helpers
  • Tests, tests, tests!
  • Configuration
  • Default Rewriting for HTML pages (drop the .html)

Update: I've realised the error of my ways and formed a neater solution - read about it here

This is a call guidance. My attempts to solve some programming problems normally result in something overly complex.

We're busily working on the next application to make the world a better place. It seems that using sub-domains for routing customer accounts is the thing to do these days and our app is no different.

I've just been setting up this mechanism onto existing core code from the stand-alone application that we're pulling this from. My ApplicationController defines a before_filter that determines the account being accessed from the URL. As such, all of my controller tests need to set up the host once they have setup the relevant test response objects:

def setup
  @controller = DashboardController.new
  @request    = ActionController::TestRequest.new
  @response   = ActionController::TestResponse.new

  @request.host = "curve21.mymagicalapp.com"
  @request.session[:current_user_id] = 1
end

Every 37signals fan-boy app needs a Dashboard right?

OK - so this works. This host and session data is used in 90% of my tests. I could paste this into every test but that's just not DRY. I could make a method called 'setup_host' and stick it in my test helper, but I've already got a bunch of tests setup. Urg. I could paste the method into every test setup - and maybe I should - but I came up with nastier way...

Looking a Test::Unit::TestCase, here's how the actual tests are run:

setup
__send__(@method_name)

The test's 'setup' method is called and then the test method is called via 'send'. I need something in between that. Here's what I did:

In test_helper.rb:

class Test::Unit::TestCase

  # ...

  def __send__(method_name)
    if @request
      @request.host = "curve21.mymagicalapp.com"
      @request.session[:current_user_id] = 1
    end
    super(method_name)
  end
end

I'm overriding send for TestCase. This works. But it doesn't please me completely.

Firstly, Ruby doesn't like me overriding send:

warning: redefining `__send__' may cause serious problem

Secondly, I only really want this to happen on tests that set up @request objects. If I didn't have that 'if' statement, all my unit tests would error.

So what does everyone else think? Is there another way to do this? Should I be hung for my crimes against programming? Or could this work well with minor tweaks?

All answers get a virtual pat on the back.

REST can be a big scary subject. However, the concepts behind it are relatively straight forward.

As most web programmers know HTTP is a stateless protocol, meaning there is no connection maintained between the web browser and the web server; you ask for a page, the server gives it to you. End of communication. What REST attempts to do is standardise a way of building meaning into the actual request from the browser.

HTTP has a 4 verbs that represent interactions with the server. The original purpose for these verbs were:

GET     =>  Get something
POST    =>  Create something new
PUT     =>  Update something
DELETE  =>  Delete something

When using data, these are the basic operations that we use. What we do in a RESTful application is use these verbs in conjunction with a resource style URL scheme.

For example, let's say we have a 'Person' object on our system. In Rails, we'll have a 'Person' model with a corresponding 'people' table. The RESTful URLs for interacting with our 'people' would look like this:

GET     /people/    =>  Get a list of all people
POST    /people/    =>  Create a new person with the submitted form data
GET     /people/1   =>  Get the person with the id of '1'
PUT     /people/1   =>  Update person '1' with the submitted form data
DELETE  /people/1   =>  Delete person '1'

As you can see, the structure of our URLs is simple and clear. In Rails there are additional GET actions to show 'new' and 'edit' forms:

GET /people/new     =>  Get the 'new person' form
GET /people/1/edit  =>  Get the edit for for person '1' *

(Note: Rails 1.2 uses a semi-colon to denote these additional actions e.g. /people/1;edit. This has since been altered in Edge Rails to use the standard foward-slash notation)

REST in Rails

As with most things in Rails this is very easy to set up. A simple declaration in your routes.rb file:

map.resources :people

This will automatically route the URLs above to the corresponding actions in your PeopleController. You'll also get a load of named routes:

people_url
new_person_url
person_url(1)
edit_person_url(1)

Adding a method attribute to these will give you the 'verb' style URLs:

people_url, :method => :post
person_url(1), :method => :delete

It's worth noting at this point that most browsers do not support all 4 verbs outlined - they tend to only use POST & GET. Rails gets around this by using hidden fields containing the correct verb. Thankfully, Rails manages this for us.

Nested Resources

So what if we our 'people' have many 'cars'? Once again, it's straight forward to set up:

map.resources :people do |person|
  person.resources :cars
end

This maps routes to a corresponding CarsController and gives us these URLs:

GET   /people/1/cars  => Get the cars for person '1'
POST  /people/1/cars  => Create a new car for person '1'
etc..

In CarsController, we can add a before_filter to pick up the person's id from the url

def find_person
  @person = Person.find(params[:person_id])
end

Conclusion

I didn't want to go into to too much detail here, but I hope I've outlined the basics of REST is all about and how you can use it in Rails to structure your application's interaction with the browser.

REST is surrounded by quite a bit of controversy as many developers believe that it is simplistic to try and define an entire application using only 4 verbs. However, I've found that using RESTful URLs covers 80-90% of the applications I write so it's a great place to start. If you find you need to add a richer set of interactions then you are free to do so.

At the end of the day, thinking in REST will give you a solid, convention-rich foundation to build on.

Happy Templates with HAML

May 16th, 2007

The first time I saw HAML it weirded me out. That was a couple of months ago and now I can't live without it. Such is the power of Hampton...

HAML can look slight odd when you first see it. Rightly or wrongly, a lot of people feel that it has a python-esque feel due to it's use of indentation. However, if you put your worries aside, HAML can help you to produce clean, manageable and concise templates. Just looking at my HAML templates, give me the same sense of satisfaction as looking at a 2 line ActiveRecord class - does everyone have that or is it just me?

Anyway - What's all the fuss about?

Take a simple HTML document:

<html>
 <head>
   <title>Hello</title>
  </head>
  <body>
    <h1>Hello to you all</h1>
    <p>
      This is a test page.
    </p>
  </body>
</html>

Look familiar? Most of us accept our fate to repeat ourselves, writing two tags for each block of HTML we need. Sure, editors can help us out with typing but it's not exactly easy on the eyes.

Let's look at the equivalent in HAML:

%html
  %head
    %title Hello
  %body
    %h1 Hello to you all
    %p This is a test page

That's it. A '%' symbol creates an HTML tag. 2 spaces are used to indent the code into sub-elements.

The basic philosophy behind HAML is that everything in your template should mean something. On the latest Ruby on Rails Podcast, Hampton explained that he took a full HTML document and cut out all the repetition.

For example, most of us use a lot of divs in our markup:

<div id="wrapper">Content</div>

You could do this in HAML for the above div:

%div#wrapper Content

However, you'd still end up with tons of divs around the template - not very DRY. HAML has a shortcut for this commonly used markup:

#wrapper Content

It works for CSS classes too:

.menu Menu Content

produces:

<div class="menu">
  Menu Content
</div>

How cool is that?

It's available as a Ruby gem and there's a Rails plugin available through the website.

Once you've installed the Rails plugin, you can just name your templates .haml and they'll automatically be rendered via HAML. You can also find syntax highlighting for all the main editors here.

I hope I've managed to convert you all. If not, you've probably not actually tried it properly, so pick a template, convert and I guarantee you'll be changed forever.