Rails 3.2 is out with great features on spotlight: faster development reloading, faster router and explain queries. However, every Rails release ships with minor features that do not get that much attention but still would be a great fit to your application. This blog post is about my five favorites “hidden” features of Rails 3.2.
1) Smarter content_tag_for
This feature written by Prem Sichanugrist provides a very simple but welcome clean up to your views. Both content_tag_for and div_for now accepts an array of records and automatically loop over each record. Therefore, instead of writing this:
@posts.each do |post| content_tag_for(:li, post) do ... end end |
You can simply write:
content_tag_for(:li, @posts) do |post| ... end |
2) Smarter migration generators
It is funny how some parts of Rails as old as the migration generators continue receiving improvements day after day. Rails 3.1 already added a feature that automatically generate indexes for associations, by simply invoking:
rails g scaffold Comment post:references title:string body:text
With the above, Rails will detect that post is a reference and it will automatically 1) add a post_id integer column, 2) add an association to your model and 3) add an index to that column.
Right after 3.1 came out, I have pushed another small feature to the migration generator that simply makes the type attribute default to string. Therefore, you no longer need to write:
rails g scaffold Person name:string email:string
You could simply write:
rails g scaffold Person name email
Oddly enough, the idea for this feature came when I was preparing a presentation and the scaffold command could not fit in a slide (the so-called Presentation Driven Development). Anyhow, this small addition would not be enough to make to the best five “hidden” features of Rails 3.2. That’s when Dmitrii Samoilov comes in.
Dmitrii sent a pull request that allows you to specify which columns should have an (unique) index. So one could write:
rails g scaffold Person name:index email:uniq
And the generator will automatically generate an index for name and an unique index for e-mail. There are other features there as well, so don’t forget to checkout the CHANGELOG.
3) Flexible exception handling
When Rails 3.0 came out, one of the features that people suddenly missed was the ability to better handle exceptions. The issue was: since Rails 3 became a lot more Rack “fluent”, we had to move some features to the middleware stack and this forced us to move the whole exceptions handling as well. Rails 3.2 attempts to bring some customization back to the game by allowing you to set your own exceptions rack application that is invoked when a failure happens. For instance, you could set the exceptions application to your own router in your config/application.rb:
config.exceptions_app = self.routes |
Now, every time there is an exception, your router is going to be invoked. Therefore, to render custom 404 pages, you could simply add to your router:
match "/404", :to => "errors#not_found" |
And implement the logic in the controller as you wish! However, there are a few things to keep in mind if you go down this road:
- You need to use
matchin your routes and notget/post/put/deletebecause such exceptions can happen in any HTTP request; - You won’t be able to see your custom exceptions in development unless you set
config.consider_all_requests_localto false in yourconfig/environments/development.rb. The reason is, if the request is considered local, Rails will always favor to show the debug exceptions page; - You can always access the original exception in the controller at
env["action_dispatch.exception"]; - It is not possible to set cookies, the session nor the flash after an exception happens. They all were already serialized back to the client;
- Finally, the default exceptions application used by Rails that simply renders a page in
public/STATUS.htmlis available here: action_dispatch/middleware/public_exceptions.rb
Remember that whatever you do in the errors controller, it should not be anything “fancy”. Keep it simple because something already went wrong with your application!
4) Custom partial paths
In order to render a partial for a given model, Rails 3.0 retrieved the partial name by calling: model.class.model_name.partial_path. Grant Hutchins & Peter Jaros noticed that this was not very flexible because the class was responsible to define the partial path and therefore they decided to move this responsibility to the instance. In order to better understand how you can use this feature, let’s consider the following practical example.
Imagine your application have an activity feed and each activity in the feed has a certain type. Usually, each type is rendered differently. For example, if you consider a to-do-list application, activities could be both “marking a list as favorite” or “marking a task as done”. Usually, applications solve this by looping for each item and rendering its respective partial, something like this:
@activities.each do |activity| render :partial => "activities/#{activity.kind}", :locals => { :activity => activity } end |
Now, you can solve this problem by defining to_partial_path in the model (the method to_partial_path is part of the ActiveModel API and can be implemented in any object. The example above implements it in the model for convenience, but it could be a presenter, another ORM, etc):
class Activity < ActiveRecord::Base def to_partial_path() "activities/#{kind}" end end |
And then invoking:
render :partial => @activities, :as => :activity |
This will now work on Rails 3.2 because even though all activities are of the same class, each instance is actually responsible for telling Rails which partial should be rendered.
The difference here is not only in brevity, but also in performance. Although the first snippet works fine, it is slow. In the scenario where only one kind of activity happened, the first snippet will go through the render stack 30 times and lookup the same template in your filesystem 30 times. If you read Crafting Rails Applications you know that this lookup is cached, but even though it would certainly be faster if we didn’t have to do this 30 times, but once.
That’s where render :collection or render :partial with an array comes in. In such cases Rails will retrieve all templates up front skipping duplicates, and this new feature allows us to take advantage of it even if the partial lookup is dynamic. So, in the scenario where all the activities are of the same kind, the template lookup will happen just once and no longer 30 times. In other words, best case scenario becomes O(1), worst case scenario is still O(n).
5) Filtered chain logging is back
Another very small change that will make development more pleasant is that Rails will now log “Filter chain halted as CALLBACK_NAME rendered or redirected” every time a before/around/after filter in your controller halts the request. This was the case in Rails 2.3 but somehow got lost when Rails 3 came out. It is one of those small things you don’t know how much you missed until you see it again!
And what is your favorite Rails 3.2 “hidden” feature? Don’t forget to take a good look at the CHANGELOGs and check out many others improvements!
Tags: crafting rails applications, exception handling, rails 3.2
Posted in English | 14 Comments »
We, Rails developers, have always worried about improving the performance of our test suites. Today I would like to share three quick tips we employ in our projects that can drastically speed up your test suite.
1. Reduce Devise.stretches
Add the following to your spec/test helper:
Devise.stretches = 1 |
Explanation: Devise uses bcrypt-ruby by default to encrypt your password. Bcrypt is one of the best choices for such job because, different from other hash libraries like MD5, SHA1, SHA2, it was designed to be slow. So if someone steals your database it will take a long time for them to crack each password in it.
That said, it is expected that Devise will also be slow during tests as many tests are generating and comparing passwords. For this reason, a very easy way to improve your test suite performance is to reduce the value in Devise.stretches, which represents the cost taken while generating a password with bcrypt. This will make your passwords less secure, but that is ok as long as it applies only to the test environment.
Latest Devise versions already set stretches to one on test environments in your initializer, but if you have an older application, this will yield a nice improvement!
2. Increase your log level
Add the following to your spec/test helper:
Rails.logger.level = 4 |
Explanation: Rails by default logs everything that is happening in your test environment to “log/test.log”. By increasing the logger level, you will be able to reduce the IO during your tests. The only downside of this approach is that, if a test is failing, you won’t have anything logged. In such cases, just comment the configuration option above and run your tests again.
3. Use shared connection with transactional fixtures
If you are using Capybara for javascript tests and Active Record, add the lines below to your spec/test helper and be sure you are running with transactional fixtures equals to true:
class ActiveRecord::Base mattr_accessor :shared_connection @@shared_connection = nil def self.connection @@shared_connection || retrieve_connection end end # Forces all threads to share the same connection. This works on # Capybara because it starts the web server in a thread. ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection |
Explanation: A long time ago, when Rails was still in 1.x branch, a new configuration option called use_transactional_fixtures was added to Rails. This feature is very simple: before each test Active Record will issue a begin transaction statement and issue a rollback after the test is executed. This is awesome because Active Record will ensure that no data will be left in our database by simply using transactions, which is really, really fast.
However, this approach may not work in all cases. Active Record connection pool works by creating a new connection to the database for each thread. And, by default, database connections do not share transactions state. This means that, if you create data inside a transaction in a thread (which has its own database connection), another thread cannot see the data created at all! This is usually not an issue, unless if you are using Capybara with Javascript tests.
When using Capybara with javascript tests, Capybara starts your Rails application inside a thread so the underlying browser (Selenium, Webkit, Celerity, etc) can access it. Since the test suite and the server are running in different threads, if our test suite is running inside a transaction, all the data created inside the test suite will no longer be available in the server. Alternatively, since the server is outside the transaction, data created by the server won’t be cleaned up. For this reason, many people turn off use_transactional_fixtures and use Database Cleaner to clean up their database after each test. However, this affects your test suite performance badly.
The patch above, however, provides a very simple solution to both problems. It forces Active Record to share the same connection between all threads. This is not a problem in your test suite because when the test thread is running, there is no request in the server thread. When the server thread is running, the test thread is waiting for a response from the server. So it is unlikely that both will use the connection at the same time. Therefore, with the patch above, you no longer need to use Database Cleaner (unless you are using another database like Mongo) and, more importantly, you must turn use_transactional_fixtures back to true, which will create a transaction wrapping both your test and server data, providing a great boost in your test suite performance.
Finally, if any part of your code is using threads to access the database and you need to test it, you can just set ActiveRecord::Base.shared_connection = nil during that specific test and everything should work great!
Conclusion
That’s it! I hope you have enjoyed those tips and, if they helped you boost your test suite performance, please let us know in the comments the time your test suite took to run before and after those changes! Also, please share any tips you may have as well!
Tags: capybara, devise, performance, tests
Posted in English | 15 Comments »
This article is about our Hacking Evenings, a weekly session in which we gather our team and do something to improve our knowledge. We talked about it on Ruby Conf Brazil and Ruby Conf Uruguay. You can see the slides here:
We’ve always worried about how to disseminate knowledge inside PlataformaTec. As a company with 13 employees (8 developers, 1 designer, 2 business analysts and 1 project manager), we all know that someone always has something new to share and that everyone else can learn from it.
As regular speakers in Agile and Ruby events, we usually rehearse our talks with our colleagues in order to get some feedback and improve them. But those rehearsals happened at best once a month.
Some months ago I read Chad Fowler’s Passionate Programmer book. In this book, Chad said about Brown Bag sessions, which is a lecture or talk given at lunch time (the name “Brown Bag” comes from the food packet that people usually brought, usually brown bags). Reading this chapter was the motivation I needed to gather our team and discuss the requirements to make our own meetings happen.
The first requirement is inherent to a consultancy company which sometimes has people working from its clients’ offices, making it harder to find a day and hour when everyone can participate. After some discussion, we decided to do that on tuesday evenings. When we decided to do that most of our team could participate but, as time goes by, the ones that couldn’t changed their schedules to fit our hacking evening there.
The second requirement was (IMHO) easier to solve: the resources. We have a big flat TV in our office since september, but before that we had only 24 inches monitors which were also fine and that you probably already have in your office. We also needed motivated people to spend some time preparing something to share. As a company that always looks for mastery, this was not hard and since we started someone always had something to share (but in case nobody has, we can watch a screencast or a talk at confreaks, which requires almost zero preparation).
The third requirement is to have something to eat. Because it is after the working hours, people are usually starving, and we can’t have fun in our hacking evenings without grabbing something to eat. In first sessions, we ordered some Pizza, which was great but expensive. So, we decided to prepare something on our own. Before starting we usually go to a near supermarket and buy the ingredients. We already prepared ham and cheese sandwiches, hot-dogs, cheeseburgers and tapioca (a brazilian wrap made of manioc).
OK, we’ve satisfied our requirements. But how to keep people motivated and participating on every session? Here are some tips:
- Make it a habit: if we do it every week at the same day and time, it is easier for everyone to commit themselves to participating. Ok, not everybody will go every week, but once we introduced this habit into our colleagues minds, they will avoid scheduling other activities in the same time and participate
- Accept any idea: the main idea is to spread knowledge. Can it be a typical talk? yes. Can it be a design or agile workshop? Yes. Can it be an open-source hacking session with someone helping the others to do bug-fixes and developing new features? Yes.
- Invite friends to talk and watch: If you have a friend that knows a lot about some subject and can improve the knowledge of your company, why not call him to participate ?
- Have fun: this is, by far, the most important tip: without having fun, people will not participate. Try to make it fun to make people spend a nice time. We’re talking about after-hours so, if it is not fun, people will not participate.
How do you disseminate your knowledge internally? Do you usually do Brown Bag Sessions? What activities do you usually do ? Would you recommend an activity for us?
Posted in English | 2 Comments »
Startup Weekend is a global network of passionate leaders and entrepreneurs on a mission to inspire, educate, and empower individuals, teams and communities. And when they say global, they really mean it! There are Startup Weekends in Germany, France, Poland, Malasya, China, Uruguay, USA and many other countries, incluing Brazil.
It is the time and place where developers, designers, product managers and startup enthusiasts gather to build products and launch startups. And now, it is São Paulo’s turn!
The ‘paulista’ edition will be hosted at ESPM in the next weekend (November 18th, 19th and 20th) and we will be there too. Don’t miss this opportunity. Bring your ideas and coding skills. Let’s share experiences and meet other entrepreneurs.
Watch the video below or take a look into http://saopaulo.startupweekend.org/ for more information.
Nesse Sábado (19/11), a PlataformaTec estará presente na etapa São Paulo do Agile Tour 2011.
O Agile Tour, considerado o maior evento sobre agilidade do mundo, tem como objetivo disseminar a visão, a cultura e as práticas adotadas pela comunidade ágil no desenvolvimento de software através da troca de experiências entre os participante. É uma excelente oportunidade de aprender mais sobre as nuanças do ágil no dia-a-dia dos profissionais.
Ano passado, em sua terceira edição, o Agile Tour reuniu cerca de 7.500 participantes em 44 cidades espalhadas por 15 países. No Brasil, o evento foi organizado em 5 cidades e atraiu mais de 600 pessoas no total. Esse ano, só no Brasil serão 12 cidades participantes e, com certeza, teremos um recorde no número de inscritos.
Ao longo do dia teremos nove palestras sobre diferentes temas – dentre os quais: “PO, tão simples como dizem?”, onde estarei representando a PlataformaTec em um bate-papo com o público sobre os skills do Product Owner que nem sempre estão presentes nos projetos ágeis.
Caso você se interesse pelo assunto, não perca o Agile Tour 2011. Além de ser uma maneira diferente de se aprender mais sobre ágil, é um ótimo canal para conhecer pessoas e ampliar sua rede de contatos.
Ah, o evento é gratuito! Por isso, não perca tempo e se inscreva já!!
Tags: Agile, product owner, project, scrum
Posted in Português | Comments Off
Para quem acompanha a comunidade Ruby brasileira, não é nenhuma novidade que nos dias 3 e 4 de Novembro teremos mais uma edição do RubyConf BR.
Assim como no ano passado, o evento acontece no Centro de Convenções Frei Caneca, perto da Av. Paulista e de fácil acesso.
Toda a equipe da PlataformaTec estará lá. Além disso, José Valim irá nos contar sobre a experiência de criar uma nova linguagem (Elixir) e como isso o fez aprender mais sobre Ruby. Será no dia 4, às 17h10.
Não deixe de nos procurar para bater um papo bacana. Aproveite e fique também para o Happy Hour que sempre acontece após o evento. É a oportunidade para conversar e conhecer todo mundo que trabalha com Ruby no Brasil. Vai perder essa? Inscreva-se!
Tags: eventos, rubyconf, rubyconfbr
Posted in Português | 1 Comment »

All
English only
Em português apenas

