Archive for December, 2010

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!

One of the great gems released in the past few months was OmniAuth. It is very easy to use, it works without tons of configurations (unless configuring XML files is your thing) and there are already plenty of resources about it on the internet.

However, it is not easy to do acceptance tests with Omniauth as it depends on external services to work. So what should we do? When I face a scenario like this, I split the acceptance test in two parts: one before the external service and one after the external service response.

Testing the first one is trivial: you only have to ensure there is an <a> tag with href equals to “/auth/facebook” (or “/auth/#{insert_your_provider_here}” if you use another one). We don’t test any of the redirects done by OmniAuth internals, because it is already tested in gem’s tests, so we go to the next step: testing the OmniAuth callback.

Testing OmniAuth callbacks is in general cumbersome but for OAuth2 providers it is a bit easier as it uses Faraday internally to connect to the provider. With Faraday, we can configure a test adapter and stub calls to return what we want.

The OmniAuth strategy provides an entry point to the Faraday connection, but we don’t have an access to the strategy directly, so we need to store it globally. For a Facebook strategy, we can achieve it as below whenever configuring Omniauth middleware:

module OmniAuth
  mattr_accessor :facebook_strategy
end
 
middleware.use OmniAuth::Strategies::Facebook, "APP_ID", "APP_SECRET" do |strategy|
  OmniAuth.facebook_strategy = strategy
end

Note you will need OmniAuth 0.2.0 (which currently is OmniAuth master) as previous versions don’t yield a block on initialization like above.

With access to the strategy, we do the acceptance test. First, we define the hashes we will return on the Faraday responses.

FACEBOOK_INFO = {
  :id =>; '12345',
  :link => 'http://facebook.com/plataformatec',
  :email => 'myemail@example.com',
  :first_name => 'Plataforma',
  :last_name => 'Tecnologia',
  :website => 'http://blog.plataformatec.com.br'
}
 
ACCESS_TOKEN = {
  :access_token => "nevergonnagiveyouup"
}

Now, we will define the stubs. OAuth2 strategies do two requests: one to retrieve the access token and another to retrieve the user information. In this example, let’s stub the Facebook requests and assign these stubs to a new connection.

stubs = Faraday::Adapter::Test::Stubs.new do |b|
  b.post('/oauth/access_token') { [200, {}, ACCESS_TOKEN.to_json] }
  b.get('/me?access_token=nevergonnagiveyouup') { [200, {}, FACEBOOK_INFO.to_json] }
end
 
OmniAuth.facebook_strategy.client.connection = Faraday::Connection.new do |builder|
  builder.adapter :test, stubs
end

For each provider the URLs may differ, so an idea is to do this on a TDD way (or you can browse through the OmniAuth source code and see the url that it requests):

  1. Assign the Faraday fake connection without stubs.
  2. Run your test
  3. See the test to raise an exception like “No stubbed request for DESIRED_URL”.
  4. Add the stubbed request with the response that you want.
  5. Repeat this process until the test pass

This is what we do on acceptance tests with OmniAuth: testing before and after the access to the external services.

Another approach is to do only one test by short-circuiting the provider authentication URLs. To do that on a Rails application, you can store the provider URL on a method like “OmniAuth.facebook_url” and stub the method to return the callback URL on your test. If you happen to be using Devise, the upcoming 1.2 version does the short-circuiting automatically for you, as you can see in Devise integration tests.

What about you? How do you stub OmniAuth requests and responses on your applications?

When I first got into Ruby and Rails development, I was impressed about how everything worked. A few lines of code and so much got done. At that time, if I was reading a book or blog post that said: “just do X and Y will automagically work”. I would gladly accept those instructions.

However, after a while, I wanted to understand how it really worked from the inside, so I started reading the source code from different plugins, including Rails itself. Accusing magic to be the reason for that 200 lines of code to “just work” didn’t feel right anymore.

Turns out, I was not the only one with this feeling. I have been into a few big conferences this year and asked people outside the Rails community what they think about it. And, for my surprise, some of them mentioned that “there is too much magic going on”.

We have been victims of myths before, as the famous “Rails can’t scale” one, and we strongly fought back. But what about the “there is too much magic going on”? Is it myth? Who is there to blame?

Yes, it is a myth and we (the Rails community) are the ones to blame for spreading it.

I have already seen people explaining how “has_many :comments” works as magic: “it magically guesses the columns from your database”. Well, a more appropriate description for that would be “Convention over Configuration”. Rails uses a set of conventions so it can properly build your associations without you having to specify all tables and columns.

Heck, I also did my part in the past. There was a time that Inherited Resources’ README was filled by words like “magic” and  “automagically”. Just recently, I replaced all this occurencies with more detailed explanations of how it really works.

The question is: isn’t it about time for us to start fighting against the “magic” myth?

When I improved Inherited Resources’ README, the benefits were clear in my head. People using Inherited Resources would write better code and be more productive because they understood it better. And, as consequence, they would be able to troubleshoot issues easily or even contribute back. This is clearly a win-win situation.

At the beginning of this year (or more specifically February, 2010) I started to put a lot of effort in writing and understanding Rails 3 architecture. Or as some people would (wrongly) say: I started to unveil the magic. After some time, it was clear that I could write better and faster code and that a lot of people could benefit from this knowledge as well.

Now, 10 months later, I am happy to say that the beta version of my book Crafting Rails Applications is out to spread what I have learned about Rails and its applications. Rails is a framework that allows us to write web applications and an advanced Rails book should consequently be about crafting them.


Crafting Rails Applications Cover

Crafting Rails Applications guides you through seven different tutorials, each of them using test-driven development to build a new Rails extension or application that solves common problems through the new Rails 3 APIs. You will understand how the Rails rendering stack works and customize it to read templates from the database while you learn how to mimic Active Record behavior, like validations, in any other object. You will find out how to write faster, leaner controllers, and you’ll learn how to mix Sinatra applications into your Rails apps, so you can choose the most appropriate tool for the job. In addition, you will improve your productivity by customizing generators and responders.

From the book cover:

Rails 3 is a huge step forward. You can now easily extend the framework, change its behavior, and replace whole components to bend it to your will, all without messy hacks. This pioneering book is the first resource that deep dives into the new Rails 3 APIs and shows you how use them to write better web applications and make your day-to-day work with Rails more productive.

My goal is that Crafting Rails Applications increases the Rails community thirst for knowledge, that “magic” is no longer enough to describe any part of Rails or its ecosystem.

The benefits are clear: leaner code, faster applications and a well-grounded Rails community. Check what people are saying or get a copy on Pragmatic Programmers web site.

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