Blog
what did i learn today

I have created a Rails3 application, started with Haml/Sass and finding it awesome. I am also trying to do unobtrusive javascript. Before, in Rails 2.3, I would have expected a remote-form to have an :update attribute, where you could specify a selector where the response of the remote method would be rendered. Now it needs to be done differently: my controller function will render a ".js" view, which will do the necessary actions itself. This makes it more library agnostic, and i prefer jquery. So for instance i have a controller action "search", and i have a corresponding "search.js.erb" as follows: [ruby] $('.grid').replaceWith('<%= escape_javascript(render :partial => 'list') %>') [/ruby] This works. It will replace the html of the element with a class grid with the html from my rendered partial. I started out trying to achieve that in HAML, and failed at first. So first i created the above ERB code which worked. Now my task seemed simpler: translate this seemingly simple line to HAML. My first naive approach was to do the following: [ruby] = "$('.grid').replaceWith('#{escape_javascript(render :partial => 'list')}')" [/ruby] But this just places the html as a readable string inside my page. Even i do something simple like [ruby] = "$('.grid').replaceWith('<h3>Text</h3>') [/ruby] i see the actual characters [ruby] <h3>Text</h3> [/ruby] and not the markup. But i need to contain the javascript inside the double-quotes or haml will not recognise it, and can not interpolate my ruby there. After looking through the HAML reference, actually the solution was incredible simple. Once more. [ruby] != "$('.grid').replaceWith('#{escape_javascript(render :partial => 'list')}')" [/ruby] The != unescapes HTML (as opposed to the standard =). This is exactly what we need of course.

With Rails3 i can create a project fully cut to my needs. I will write it down here, just so i remember it well and hopefully it will help some of you too. In my projects, i want to use haml, rspec2, factory-girl, jquery, ... We need a few steps to complete this.

Create the project

For starters, create the folder, without Test::Unit (-T) and without prototype (-J). [ruby] rails new test-project -T -J [/ruby] You could also specify the database, using option -d, [--database=DATABASE], with the following options: `

mysql oracle postgresql sqlite3 (default) frontbase ibm_db`

Specify needed gems

We also have to specify the gems we need. To do that, we need to edit the Gemfile which is located in the root of your project. My file looks as follows: [ruby] source 'http://rubygems.org' gem 'rails', '3.0.0.rc' # Bundle edge Rails instead: # gem 'rails', :git => 'git://github.com/rails/rails.git' #gem 'pg' gem 'sqlite3-ruby', :require => 'sqlite3' # Use unicorn as the web server # gem 'unicorn' # Deploy with Capistrano # gem 'capistrano' # To use debugger # gem 'ruby-debug' gem 'rails3-generators' gem "bson_ext" gem "haml" gem "haml-rails" gem "jquery-rails" gem "rcov" # we need this here, see http://blog.davidchelimsky.net/2010/07/11/rspec-rails-2-generators-and-rake-tasks/ group :development, :test do gem "rspec-rails", ">= 2.0.0.beta.18" end # test-environment gems group :test, :spec, :cucumber do gem "factory_girl_rails" gem "rspec", ">= 2.0.0.beta.18" gem "remarkable", ">=4.0.0.alpha2" gem "remarkable_activemodel", ">=4.0.0.alpha2" gem "remarkable_activerecord", ">=4.0.0.alpha2" gem "capybara" gem "cucumber" gem "database_cleaner" gem "cucumber-rails" end [/ruby] Run bundle install to install all needed gems.

Use wanted generators

Then now edit the file application.rb, located in the config folder, and add the following lines: [ruby] # Configure generators values config.generators do |g| g.test_framework :rspec, :fixture => true g.fixture_replacement :factory_girl, :dir=>"spec/factories" end [/ruby] This will make sure that the generators use our own defaults. So now when you type [ruby] rails generate model TestModel name:string rails generate controller TestModel [/ruby] and it will create haml views, rspec tests, and factories. Awesome :)

Prepare to use jquery!

To start using jQuery in Rails3, you have to first get the rails.js specifically for jQuery (stored in the jquery-ujs project). Save it in your public\javascripts directory. Download jquery, and make sure to include both in your application layout or view. In HAML it would look something like. [ruby] = javascript_include_tag 'jquery.min.js' = javascript_include_tag 'rails' [/ruby] BUT: there is a quicker route! We also installed the gem jqeury-rails, which has the following generator if we want to install jquery in one go! [ruby] rails g jquery:install #--ui to enable jQuery UI [/ruby] Rails requires an authenticity token to do form posts back to the server. This helps protect your site against CSRF attacks. In order to handle this requirement the driver looks for two meta tags that must be defined in your page's head. Luckily rails makes it easier for us, again, and we just need to include csrf_meta_tag somewhere inside your page's head (rails3 does this default in your application.html.erb). Be sure to include it in your haml code too. An example application.html.haml would look like this: [ruby] !!! Strict %html{ "xml:lang" => "en", :lang => "en", :xmlns => "http://www.w3.org/1999/xhtml" } %head %title== Test-project #{@page_title} %meta{'http-equiv' => "Content-Type", :content => "text/html; charset=utf-8"} %link{ :href => "/favicon.ico", :rel => "shortcut icon" } = stylesheet_link_tag :all = javascript_include_tag 'jquery-1.4.2.min.js', 'rails.js', 'application.js', :cache => 'all_1' = csrf_meta_tag = yield :local_javascript = yield :head %body #banner =image_tag 'your-logo.png' .the-title %h1 %p Your application #navigation #container #sidebar #contents =yield #footer == © 2010 your company [/ruby]

Done! :)