Posts by Carlos Antônio

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.

We have been working on SimpleForm for some time since the last release and have got a lot of contributions from community. Now it is time for a new release with more HTML 5 compatibility plus some new cool features. So, without further ado, lets take a ride on the new stuff.

HTML 5

One of the most useful features coming in HTML 5, in my opinion, is the placeholder option. This option allows us to configure a text to be shown inside the input when it is empty. This is really nice to help the user while filling out forms. SimpleForm now gives us the possibility to pass in a placeholder option in the same way we are used to do with use hints:

<%= simple_form_for @user do |f| %>
  <%= f.input :username, :label => 'Your username please' %>
  <%= f.input :password, :hint => 'No special characters.' %>
  <%= f.input :email, :placeholder => 'user@domain.com' %>
  <%= f.button :submit %>
<% end %>

As you can see here, the placeholder is given as String, but it can also be fetched from I18n, as labels/hints does.

Another addition is the automatic lookup of min/max values from numericality validations, for number inputs. For instance:

class User
  validates_numericality_of :age, :greater_than_or_equal_to => 18,
    :less_than_or_equal_to => 99, :only_integer => true
end
<%= simple_form_for @user do |f| %>
  <%= f.input :age %>
<% end %>

Would generate an input with type number, and the min/max attributes configured with 18 and 99, respectively.

Besides that SimpleForm also adds:

  • the :required html attribute for required inputs (it is retrieved automatically from your presence validations);
  • the :search and :tel input types, with :tel mapping automatically for attributes matching /phone/.

Collections

From now on, radio and check box collections will wrap the input element inside the label, making it pretty straightforward to associate both elements. Besides that, SimpleForm now comes with two new configurations:

  • collection_wrapper_tag wraps the entire collection in the configured tag;
  • item_wrapper_tag wraps each item in the collection using the configured tag.

An example:

<%= simple_form_for @user do |f| %>
  <%= f.association :roles, :as => :check_boxes, 
    :collection_wrapper_tag => :ul, :item_wrapper_tag => :li %>
<% end %>

This should be kind of self explanatory =).

New input options

It’s now possible to give the :disabled option straight to the input, which will also add the disabled css class to both input and wrapper elements:

<%= simple_form_for @user do |f| %>
  <%= f.input :email, :disabled => true %>
<% end %>

And also the :components option, which will only render the given components in the given order:

<%= simple_form_for @user do |f| %>
  # Generates the label after the input, and ignores errors/hints/placeholders
  <%= f.input :email, :components => [:input, :label] %>
<% end %>

New configuration options

If you are not using any label / hint / placeholder with I18n, you can now completely disable the translation lookup of these components by setting the config.translate to false in your SimpleForm initializer. This should improve performance a bit in these cases.

Another nice improvement is the ability to add custom input mappings to SimpleForm. If you ever needed to map a specific attribute to a default input, now you can:

  config.input_mappings = { /_count$/ => :integer }

This configuration expects a hash containing a regexp to match as key, and the input type that will be used when the field name matches the regexp as value. In this example we match all attributes ending with _count, such as comments_count, to be rendered as integer input by SimpleForm.

New docs and mailing list

SimpleForm now has its own google group where you can ask questions, search for already answered questions and also help others. Besides that, you can also navigate and search the entire RDoc.

Wrapping up

As you can see, there are plenty of new and cool stuff in this release. We encourage you to take a look at the CHANGELOG and also review the README to see what else is available and some more examples.

And please, check out SimpleForm contributors, we want to thank everyone who is helping us to improve SimpleForm.

What about you? Do you want any cool feature in SimpleForm? Help us improve it by forking and sending us a pull request, we will be really glad to apply it. We hope to see your name in the contributors page soon!

Finally, in your opinion, what is the coolest feature SimpleForm has? And what idea you have you might want to be added to SimpleForm? Feel free to comment :D

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!

Two months ago we were celebrating Devise’s birthday. We were not talking about its age, Devise had just 4 months of life, but we were happy to reach the 1.0 release.

Today we are celebrating again! We are very proud and glad to have Devise in its first Railscast! Ryan Bates has done a great job explaining how to get Devise up and running in a Rails 3 application, showing how to install Devise and choose the basic modules you want to use in your application.

We also made a promise to you: get Devise up and running for Rails 3. We keep walking this road, each Rails beta version released we are releasing a new compatible Devise version. For the time being, we have Devise 1.1.rc0, a release candidate version, compatible with Rails 3 beta 2.

We are looking forward to see the second part of Devise’s Railscast, about how to configure Devise to fit the needs of your application.

Give Devise a try. You can post your questions to the mailing list and, if you find any issue, please use the Github Issue Tracker. Don’t forget to post information about your environment (like Devise, Warden and Rails versions) including the stack trace if you are facing an error, to help us help you =). Enjoy!

Update: Railscasts just released the second part of Devise screencast, Customizing Devise, going through Devise configuration options. Check it out!

Ultimamente temos trabalhado em alguns projetos que necessitaram de vários CRUDs na administração como páginas mostrando listas de atributos. E com passar do tempo, estávamos ficando entediados de tanto copiar e colar código como este para cada atributo em nossas páginas:

<p>
  <strong class="label">Name</strong><br />
  <%= @person.name %>
</p>

Nós já tinhamos criado um helper para fazer o trabalho para nós, mas copiar este helper de um projeto para outro não é DRY. Então decidimos criar uma nova gem, chamada ShowFor.

ShowFor é uma DSL para auxiliá-lo a mostrar uma lista de atributos, usando I18n, perfeito para páginas de visualização em interfaces CRUDs. Ele permite que você substitua duplicação de código/html em suas views usando uma sintaxe mais atraente. Vejamos o que podemos fazer!

Atributos

Vamos imaginar que temos um model Person, que possui os atributos first_name, last_name, age, photo, e confirmed. As linhas abaixo criam uma lista de valores para um registro específico:

<% show_for @person do |p| %>
  <%= p.attribute :first_name %>
  <%= p.attribute :last_name %>
  <%= p.attribute :confirmed? %>
  <%= p.attribute :created_at, :format => :short %>
  <%= p.attribute :age, :if_blank => "No age" %>
 
  <% p.attribute :photo do %>
    <%= image_tag(@person.photo_url) %>
  <% end %>
<% end %>

E este é o código HTML que você tem como resultado:

<div class="show_for person" id="person_1">
  <p class="wrapper person_first_name"><strong class="label">First name</strong><br />Carlos</p>
  <p class="wrapper person_last_name"><strong class="label">Last name</strong><br />Antonio</p>
  <p class="wrapper person_confirmed"><strong class="label">Confirmed?</strong><br />Yes</p>
  <p class="wrapper person_created_at"><strong class="label">Created at</strong><br />08 Mar 11:30</p>
  <p class="wrapper person_age"><strong class="label">Age</strong><br />24</p>
  <p class="wrapper person_photo"><strong class="label">Photo</strong><br />
    <img alt="Rails" src="/images/rails.png?1268047643" />
  </p>
</div>

Como se pode ver, você terá uma marcação HTML padrão, com classes e ids para ajudá-lo no design com CSS. E caso tenha notado, estamos usando opções extras em alguns atributos, vamos dar uma olhada em algumas delas:

  • :format permite que você defina um formato a ser usando com I18n, somente para atributos date/time, como você usaria com o helper l.
  • :if_blank define o que será mostrado caso o atributo esteja em branco. Pode ter um valor padrão via I18n.
  • do...end: usando blocos você mesmo pode manusear o conteúdo para o atributo específico, como fizemos no exemplo para o atributo photo.

Atributos booleanos, como nosso :confirmed, também possuem um valor padrão para true e false, e podem ser configurados através de I18n. Se você deseja mostrar “Sim” e “Não” no lugar de “Yes” e “No” respectivamente, só precisa mudar seu arquivo I18n. Você também pode passar a opção :escape para não escapar o conteúdo (true por padrão).

Associações

ShowFor também funciona com associações. Por exemplo, podemos adicionar que nosso Person agora pertence a um model City com um atributo nome, e que também possui e pertence a muitas Tags. Para gerenciar o primeiro, podemos fazer:

<%= p.association :city %>

ShowFor irá adivinhar o atributo correto para mostrar procurando todas as possibilidades configuradas em ShowFor.association_methods e neste caso escolhendo :name. Mas é claro, você pode modificar isso se precisar:

<%= p.association :city, :using => :full_name %>
<%= p.attribute :full_name, :in => :city %>

Ambas as possibilidades acima terão a mesma saída, apenas escolha a que você mais gostar.

Manusear coleções é tão fácil quanto associações belongs_to. Você simplesmente passa a associação para ShowFor e ele irá saber se é uma coleção ou não, gerando uma lista de elementos usando tags ul e li.

<%= p.association :tags %>

Entretando, se você quiser renderizar a coleção inline, pode usar as opções :to_sentence e :join:

<%= p.association :tags, :to_sentence => true %>
<%= p.association :tags, :join => ',' %>

Também é possível passar um bloco para a coleção. O ShowFor criará a tag wrapper (ul por padrão nesse caso) e retornará cada elemento da coleção para você gerenciá-lo:

<% a.association :tags do |tag| %>
  <li><%= link_to tag.name, tag %></li>
<% end %>

Labels

Você deve ter percebido que o ShowFor possui um label padrão usando a tag strong. Ele também expõe a você o método label como um helper, para que possa usá-lo quando desejar:

  <%= p.label :first_name %>
  <%= p.label :age, :id => 'person_age' %>
 
  <strong class="label">First name</strong>
  <strong class="label" id="person_age">Age</strong>

Instalação

O ShowFor, em sua versão 0.2.0, já é compatível com o Rails 3. Você pode seguir as instruções no README para instalá-lo.

Se você está usando o Rails 2.3.x, pode dar uma olhada no branch 0.1, e seguir as instruções no README deste branch para utilizá-lo.

E após a instalação, não se esqueça de executar o generator e dar uma olhada no initializer gerado, que permite que você configure várias partes do ShowFor.

script/generate show_for_install

Fechando

ShowFor ajuda você a mostrar os atributos de seus objetos facilmente com uma marcação html padrão, e pode ser totalmente configurado para atender sua necessidade. Ele tem nos ajudado em todos os projetos, e esperamos que ele possa ajudá-lo também. Se você tiver alguma dúvida, por favor dê uma olhada no README, existem muitos exemplos e documentação lá.

E você? Possui algum helper que usa todos os dias e que poderia ser transformado em um plugin/gem? Não hesite em fazer isto, ficaremos contentes em ver seu trabalho!

Divirta-se!