Posts tagged "rails"

When writing Crafting Rails Applications, I knew exactly which parts from Rails I wanted to talk about. However, I didn’t want the book to simply describe how everything works, I actually wanted everyone to build something useful from each part of Rails.

One of the hardest areas to come up with an useful tool as example was the template handlers. Template handlers are responsible for template compilation and the canonical examples are: ERb and Haml. Obviously, creating something like ERb or Haml from scratch would require a lot of code beyond the Rails integration so it wasn’t an option. On the other hand, tools that simply render rdoc or markdown templates would be too simple and there are already plenty of gems doing the same out there.

So I started playing with some options. The first one was something like Why’s Markaby but that would still require a good amount of code (albeit much less than ERb). Next, I have played with something called YERb (YAML + ERb) which was an interesting hack but too slow to be of any use. I was almost planning to remove the chapter about template handlers when it finally came to me the idea of markerb: markdown + erb (in the book, we did a wordplay and called merb). While the idea was simple and easy to implement, it had a great use case: multipart templates.

With Markerb, you can create one template for ActionMailer and it will be delivered both as text and HTML. So there is no need to maintain two templates. You write it in markdown, which is delivered as text, but also rendered to be delivered as HTML. Recently, I have crafted Markerb in its own gem so everyone can use it.

How to use?

The usage is quite simple. Assuming you have a notifier as below:

class Notifier < ActionMailer::Base
  def contact(recipient)
    @recipient = recipient
    mail(:to => @recipient, :from => "john.doe@example.com") do |format|
      format.text
      format.html
    end
  end
end

If you create a template at app/views/notifier/contact.markerb:

Multipart templates **rock**, right <%= @recipient %>?!

It will generate two parts, one in text and another in HTML when delivered. And that is it! Before we finish, here are a few things you might need to know:

  • The “contact.markerb” template should not have a format in its name. Adding a format would make it unavailable to be rendered in different formats;
  • The order of the parts matter. It is important for e-mail clients that you call format.text before you call format.html;
  • Notice you can normally use ERb inside the template.

If you are interested in how Markerb, template handlers and other part of Rails work, check out Crafting Rails Applications. We also hope to add a generator to Devise that will optionally copy all views as Markerb templates to your application.

And you? Do you have any use cases for Markerb? Do you have any other interesting template handlers you would like to share?

A while ago we were working on an application that had an entire version specially created for mobiles, such as the iPhone. This specific application was entirely tested with Capybara, Steak and Selenium Webdriver. Although the test suite wasn’t the fastest one in the world, the web application was very well tested, and to guarantee that we would also be testing the mobile version, we would have to simulate an iPhone user agent accessing the application.

But wait, you might be thinking that we are not able to change browser headers while dealing with Selenium. Capybara has a nice API to define new drivers and Selenium allows us to define different profiles with custom configurations for each driver. Lets see how we can put all this together to handle that:

Capybara.register_driver :iphone do |app|
  require 'selenium/webdriver'
  profile = Selenium::WebDriver::Firefox::Profile.new
  profile['general.useragent.override'] = "iPhone"
 
  Capybara::Driver::Selenium.new(app, :profile => profile)
end

Yup, it’s that simple =). We are creating a new driver for Capybara called :iphone, that will use Selenium with Firefox, but with a different profile, overriding the user agent string. This way you can pretend to your application that you are accessing through a “real” iPhone, by giving the “iPhone” string as user agent. You could also configure an :android driver, for instance, by simply changing the user agent string.

So now, how do we make use of that new driver in our specs? Here comes a simple example:

scenario 'access phone information using a modal box', :driver => :iphone do
  visit root_path
 
  page.should have_no_css "#fancybox-wrap"
  page.should have_no_content "0800 123456"
 
  within("header") { click_link "Telefones úteis" }
 
  within("#fancybox-wrap") do
    page.should have_content "0800 123456"
  end
end

We are just passing the :driver => :iphone option to our scenario. Remember that the latest Capybara versions use RSpec metadata options and will apply the :driver option automatically, changing the current driver to our registered :iphone in this case. For more info please refer to Capybara’s README.

You are now able to configure different user agents based on your application requirements, and test it in a full stack way. How about you, do you have any quick hint on how to test different user agents using another driver? Let us know in the comments :)

Updates (04/04/2014)

We were told that if you’re using Selenium Webdriver version 2.41.0, the code above will raise an exception. In order to fix that problem, you just need to replace Capybara::Driver::Selenium.new by Capybara::Selenium::Driver.new. Thanks Michael Joseph for suggesting that update.

Erik DeBill has put two interesting benchmarks on his blog. The first one compares the performance of different Ruby implementations in Rails development mode while the second compares their performance in Rails boot time. If you haven’t read them yet, please do it now.

Benchmarking code is an important practice, but it can be misleading if you fail to understand the root causes that lead to the different results.

Performance in development mode

In the first blog post, it is guessed that the root case for having slow requests in development is because Rails eager loads all models and controllers for each request:

Now, what I’d really like is a way to avoid recompiling everything every time. If I could have Rails recompile just the model or controller I’m working on and skip all the others, that’d be grand. I’ve taken a couple stabs at it, but I haven’t succeeded yet.

This is wrong! Rails, in development, only loads the model and the controller you are using in that specific request. This is very easy to verify if you create a new application, scaffold two resources and add a puts self.name in their class definition. If you access one controller, it will only load the model explicitly referenced in that controller. Even the model associations try to be lazy in that aspect, always loading the minimum it can.

So you may ask, why Rails is getting so slow after adding more scaffolds?

It happens because Rails 3.0 includes all helpers by default in your ApplicationController. So at the beginning of each request, Rails needs to load all helpers. Loading a helper in development mode is slow because ActiveSupport::Dependencies needs to track which dependencies were added when a file is loaded. This tracking basically happens by checking which constants were added invoking Object.constants before and after the file was loaded. Tracking these constants take more than 50% of the time in the request, mainly because invoking Object.constants is slow.

In other words, the main reason for an implementation to perform better in the benchmarks showed in the blog post is if it can calculate Object.constants faster. Those results do not mean at all that an implementation is more suitable than other for Rails development. In order to have real results, we would need a real application that is not made of 1000 scaffold (or, in this case, 1000 helpers).

In any case, if the root cause is in loading all helpers, how can we make it better? There are a few things:

1) Obviously, the problem can be fixed by having less helper files. Since Rails scaffold automatically generates helper files, it is common that applications have a bunch of empty helpers. Get rid of them. If you prefer you can even turn off the automatic generation of helpers in scaffold by adding the following to your application configuration:

config.generators.helper = false

2) If you simply don’t want to include all helpers, there is a method called clear_helpers that you could invoke in your ApplicationController. This method won’t fix the problem because it is invoked too late, after all the helpers were already loaded. So you get the feature, but not the performance improvement.

3) Rails master (upcoming Rails 3.1) has a configuration option that allows you to effectively turn these helpers off getting both the feature and the performance improvement:

config.action_controller.include_all_helpers = false

Boot performance

The second blog post shows how Rails boot time performs in different implementations. Since it was not made explicit in which environment those benchmarks were executed, I will assume it happened on development.

At the end of the second blog post, it tries to associate the performance of booting Rails in development with the amount of code inside the app. However, when you boot an application in development, no model, controller or helper is loaded at all unless you explicitly access them in an initializer or in your routes file. Once again, you can check that by adding some puts to your classes.

So, you may ask one more time, what makes booting up so slow?

Rails 3 has a new router that can match paths very fast, but in order to do so, it needs to compile each route into a regular expression and that takes some time (although it could probably be made faster). And it is exactly the routes compilation that is slow on boot time. We can easily reproduce it by adding the following to our router:

Foo::Application.routes.draw do
  1000.times do |index|
    resources :"posts#{index}"
  end
end

This took 55 seconds on my machine using REE which is quite close to the value that he showed on his benchmark.

Again, benchmarking code is important, but more important is to correctly interpret the results. In his example, it is likely that most of Rails booting time is spent on compiling the routes and the benchmark just shows how good different Ruby implementations are in handling all these regular expressions.

Wrapping up

Much more interesting benchmarks for Rails boot time would actually be performed in production environment, which actually has to load all the code inside the app folder and compile the routes file. Regardless, developers starting new applications should always be skeptical about choosing a Ruby implementation based on other application’s benchmarks.

When starting out a new application, any Ruby implementation should suit you just fine unless you have a stronger constraint (like Java integration). Once your application starts to grow and you want to evaluate how well it performs in different implementations, you should do your own benchmarks and see how it goes. In any case, don’t jump into conclusions. If you need to investigate deeper, each implementation has its own sets of benchmarking and profiling tools that may help you really understand what is actually slow and how to improve it.

I also want to thank ruby-prof authors and maintainers, for such an amazing tool, and Yehuda Katz, who helped me profile a demo Rails application in order to write this detailed response.

And you? Have you done benchmarks in your applications and found any interesting data you would like to share?

This year is coming to an end and it was amazing for us at Plataforma Tecnologia. We are proud to share with you, faithful reader, our accomplishments in 2010, which weren’t few.

Open Source

The year has begun on fire. In February, José Valim made his way into the Rails Core team and has been doing a great work since then, including many contributions to the Rails 3 release.

We are also really proud with Devise. It got very mature, achieving the 1.0 version this February. Since then, Devise is becoming one of the best solutions for authentication in Rails and also one of the most watched repositories on GitHub.

In August, Devise 1.1 was released with Rails 3 support and a bunch of cool features. Recently, a lot of work is being done towards the 1.2 version, which includes full support to the awesome OmniAuth gem.

We also released SimpleForm this year. SimpleForm is our take on building forms in a simplified way lead by Carlos Antônio who recently did a great work on HTML 5 support.

Other gems were released, such as ShowFor, which is a DSL to simplify how you show your objects in views and also Responders, a collection of Rails 3 responders.

Book

Eariler this month, José Valim’s book entitled Crafting Rails Applications has been released by the highly acclaimed publisher Pragmatic Bookstore! The book covers internal aspects of Rails 3 and how you can bend it to your will. The reviews and buzz has been great so far, even though still in beta. Grab your copy now!

Events

This year was also very productive in terms of events. We’ve been to a lot of events, heck, George was even able to go to RailsConf, in Baltimore! Also, José Valim has spoken in various events, including Euruko 2010 (includes video), RubyConf Brazil 2010 (talk in portuguese) and OxenteRails 2010.

Carlos, Hugo and George did their share as well, speaking at various events, from smaller and user-group events to bigger ones such as OxenteRails, RS on Rails and QCon SP.

Company

The company itself is getting more mature and increasing. At January 2010, PlataformaTec was composed of 6 people, and up until December 2010, 5 other people joined the company (including myself)! We also have started playing with iOS development, something we believe to have a great future, expect future blog posts on the subject.

Great 2011!

Have a great New Year! We wish you all the best for year to come. We have high expectations for 2011, so stay tuned!

Most of the applications we create these days usually have an admin interface where an user with necessary privileges is able to manage the application content, respecting some business rules. Thus it is required that part of this content is easily manageable, which means the user needs to be able to add some formatting to the content. For us, it usually means that the user has to input HTML tags. And it also means that the user can do things that might break our application.

Luckily, Rails can help us since it has some helpers to sanitize and strip unwanted tags or attributes from the markup.

Strip links

If you just want to remove all links from the text you want to show, you can use the following method:

<%= strip_links 'Send e-mail to <a href="mailto:me@example.com">Me</a>.' %>
 
Send e-mail to Me.

Strip tags

This might be a bit famous: it removes all html tags from the given markup, using html-tokenizer:

<%= strip_tags '<p class="foo">Send e-mail to <a href="mailto:me@example.com">Me</a>.</p>' %>
 
Send e-mail to Me.

Sanitize

The sanitize helper encodes all html tags and strips all attributes that are not allowed, specially script tags.

<%= sanitize '<p id="bar" class="foo">foo bar <script>alert("I am a hacker!")</script> baz</p>' %>
 
<p class="foo">foo bar  baz</p>

For instance here the script tag was removed, and also de id attribute from the paragraph tag.

Simple format

Together with sanitize we have the simple_format helper. Besides sanitizing the given content, it automatically converts one new line into a br tag, and two or more new lines into a p tag. Lets see how it works:

<%= simple_format "I am a text \n and I want to be formatted \n\n by <strong>simple_format</strong>", :class => 'foo' %>
 
<p class="foo">I am a text 
<br /> and I want to be formatted </p> 
<p class="foo"> by <strong>simple_format</strong></p>

So I want to change this stuff, and now, what happens?

Rails gives you the ability to configure most of what is allowed and what is not when sanitizing content. Lets see the available options:

  • sanitized_uri_attributes
  • sanitized_bad_tags
  • sanitized_allowed_tags
  • sanitized_allowed_attributes
  • sanitized_allowed_css_properties
  • sanitized_allowed_css_keywords
  • sanitized_shorthand_css_properties
  • sanitized_allowed_protocols

I believe these configs are pretty straightforward, but in case you have any doubt, check the docs in the source code. You can change any of these configs in your application file:

class Application < Rails::Application
  config.action_view.sanitized_allowed_tags = %w(table tr th td thead tbody tfoot)
  config.action_view.sanitized_allowed_protocols = %w(tel)
end

Wrapping up!

These simple helpers can make our life really easier when dealing with content coming from an admin interface, allowing specific tags and attributes to be shown, and doing the most they can to remove unwanted tags.

You can see more about them in the docs:
http://api.rubyonrails.org/classes/ActionView/Helpers/SanitizeHelper.html
http://api.rubyonrails.org/classes/ActionView/Helpers/TextHelper.html

What about you, do you use some Rails helper that might be in the dark? We would love to bring it to the light side, share with us!

Sometime ago we were working on a project together with a designer, and that specific application was full of forms, each one having a different layout, but most of them sharing the same features: inline errors, hints, specific label markup for required fields, etc. To start prototyping the application faster, we used the markup the designer created with similar forms, duplicating the code. But we don’t like code duplication, we weren’t feeling comfortable with it. So we decided to move on and create a tool to help us, that should be flexible enough to let us define the markup that fits better for each application, or even no extra markup at all. Here is SimpleForm!

SimpleForm inputs

From the README:

Forms made easy (for Rails)!

SimpleForm aims to be as flexible as possible while helping you with powerful components to create your forms. The basic goal of simple form is to not touch your way of defining the layout, letting you find the better design for your eyes. Good part of the DSL was inherited from Formtastic, which we are thankful for and should make you feel right at home.

As the README says, SimpleForm is a tool to help you build forms easily in Rails. Let’s see some examples:

<%= simple_form_for @user do |f| %>
  <%= f.input :username, :label => 'Your username please' %>
  <%= f.input :password, :hint => 'No special characters.' %>
  <%= f.input :remember_me, :as => :boolean %>
  <%= f.button :submit %>
<% end -%>

There are plenty of things going on here: we create a form using simple_form_for helper, then we use the :input method to create input elements based on column type. For instance, :username will create a default text input, while :password attribute will render an input type password. For the :username attribute, we are specifying a label manually. For :password, the label will be taken from I18n, and we are adding a hint message to the field. For :remember_me, we are explicitly saying to render it as a checkbox, using the :as => :boolean option (that is the default for boolean attributes). Also, there is a button helper that simply delegates to Rails helpers, in this case submit.

The output for a new @user would be:

<form action="/users" class="simple_form user" id="new_user" method="post">
  <div class="input string required">
    <label class="string required" for="user_username"><abbr title="required">*</abbr> Your username please</label>
    <input class="string required" id="user_username" maxlength="255" name="user[username]" size="50" type="text" />
  </div> 
  <div class="input password required">
    <label class="password required" for="user_password"><abbr title="required">*</abbr> Password</label>
    <input class="password required" id="user_password" name="user[password]" size="30" type="password" />
    <span class="hint">No special characters.</span>
  </div> 
  <div class="input boolean optional">
    <label class="boolean optional" for="user_remember_me"> Remember me</label>
    <input name="user[remember_me]" type="hidden" value="0" />
    <input class="boolean optional" id="user_remember_me" name="user[remember_me]" type="checkbox" value="1" />
  </div> 
  <input id="user_submit" name="commit" type="submit" value="Create User" /> 
</form>

You may have noticed there is some additional css classes added to the markup, like string and required. They are added automatically by SimpleForm to help us style and plug some javascript in. There are specific css classes for each available input type. Also, pay some attention to the label: inside it there is an abbr tag with an asterisk (*) showing that the field is required. SimpleForm uses the new validations reflection API from Rails 3 to check if the attribute has the presence validator, and mark the field as required if so. And we are able to say that a field is required or disable the required mark, by passing the option :required => true|false.

Furthermore, there is the hint tag for the :password attribute that SimpleForm creates based on the :hint option we have defined. Also notice that the gem has automatically added a div wrapper to each input, with the same css classes. SimpleForm allows us to configure this wrapper as well, using for instance p instead of div. We are going to see more about configuration later.

SimpleForm is already prepared to generate some of the new HTML 5 input tags, such as email, url and number inputs:

<%= simple_form_for @user do |f| %>
  <%= f.input :website, :as => :url %>
  <%= f.input :email %>
  <%= f.input :age, :hint => "This defaults to 'number' input based on field type" %>
  <%= f.button :submit %>
<% end -%>

Based on the attribute name, SimpleForm will generate url or email input types, and we can always set a specific type with the :as option. Numeric attributes will always be rendered as input type number.

Working with associations

SimpleForm adds a custom and straightforward method to render select tags for associations, called association. For now, consider our User belongs to a Company, and has and belongs to many Roles. Let’s go straight to the example:

<%= simple_form_for @user do |f| %>
  <%= f.input :name %>
  <%= f.association :company %>
  <%= f.association :roles %>
  <%= f.button :submit %>
<% end -%>

It will detect the association type and render a select tag for choosing the company, listing all companies in the database, and another select for roles, with multiple option enabled.

SimpleForm also has some add-ons, letting us render associations as a collection of radios or check boxes. Using the same example:

  f.association :company, :as => :radio
  f.association :roles, :as => :check_boxes

Now we are rendering a collection of radios for choosing the Company, and another collection of check boxes for choosing Roles.

Configuration

SimpleForm lets us do some customizations by running its install generator:

rails generate simple_form:install

# Output
  create  config/initializers/simple_form.rb
  create  config/locales/simple_form.en.yml
  create  lib/templates/erb/scaffold/_form.html.erb

As we can see, running this generator will copy an initializer file, responsible for configuring SimpleForm; a locale file, to let us change some I18n messages; and a form template inside our lib dir. This template will be used instead of the default Rails scaffold form template, so it will create our form already using SimpleForm. Easy, right?

Let’s take a look at some configuration options:

  • components: defines the components used by the form builder. We can remove any of them, change the order, or add new ones. Defaults to [ :label, :input, :hint, :error ].
  • hint_tag: tag used for hints, defaults to span.
  • error_tag: tag used for errors, defaults to span.
  • wrapper_tag: tag used as wrapper to all inputs, defaults to div
  • label_text: determines how the label text should be generated altogether with the required text. It must be a lambda/proc that receives both label and required texts. Defaults to "required label".

There are a lot more options available in the initializer file, such as default input size and priority countries for generating country selects. Also, the locale file lets us determine the required text and mark, or even the entire required html tag.

Internationalization

SimpleForm is ready for I18n, supporting labels and hints. In addition, it lets us set different content for each action, new and edit. Here is an example locale file:

  en:
    simple_form:
      labels:
        user:
          username: 'User name'
          password: 'Password'
          edit:
            username: 'Change user name'
            password: 'Change password'
      hints:
        user:
          username: 'User name to sign in.'
          password: 'No special characters, please.'

Simple, right? If it does not find any specific translation using I18n for the label, it will fallback to human_attribute_name.

Here we go!

SimpleForm has much more to offer. We would like to invite you to take a better look at the examples and possibilities. Remember, SimpleForm aims to be flexible and powerful to help you easily build forms, without saying how you should create your markup.

Also, feel free to explore the source code and extend SimpleForm even further. Since it’s based on components, creating a new component which moves the current hints to inside the input (using javascript or the new placehoder attribute in HTML 5), should be easy!

It’s worth saying SimpleForm is Rails 3 compatible in the master branch. If you are using Rails 2.3.x, there is a v1.0 branch and version that you might want to take a look.

SimpleForm has been helping us a lot so far, we hope you enjoy it. Moreover, we would like to enjoy other tools that help your productivity day by day, please leave a comment and let us know, we would appreciate a lot!