Wow, a major release? Yes, a major release and we have plenty reasons for that. Since me and José Valim were working on it for a couple months, we have quite a list :). So follow up:
1. Remarkable Core
Remarkable is now a framework for rspec matchers. Since Rails matchers are not simple, as Remarkable grew, we saw our matchers full of logic to show messages (description and failure messages) and that some methods could be automatically generated, reducing repetitive work.
Compare the allow_mass_assignment_of matcher in Remarkable 2.x and in Remarkable 3.0. Which one do you prefer? :)
So we built a DSL and called it Remarkable, which with Remarkable ActiveRecord and Remarkable Rails, provides you nice matchers/macros to speed up your tests. To install them, just do:
You can also install just remarkable or just remarkable_activerecord. But remarkable_rails brings you the whole packet.
2. I18n
On Rails Summit Latin America, Obie Fernandez talked about the Hash Rocket way and one of the items were that they actually print out the specs and give it to the client. Both me and José work with Rails projects and we couldn’t deliver the same to technical clients, because the output was in english. Well, we scratched our own itch!
This is how an English output would be like:
User
- should require name and email to be set
- should ensure length of name is within 3..40 characters
- should require unique values for email
- should ensure numericality of age allowing only integer values and allowing blank values
In Remarkable, we can have the same results in Portuguese:
Usuário
- deve exigir presença de nome e email
- deve garantir tamanho de nome seja entre 3..40 caracteres
- deve garantir valores únicos para email
- deve aceitar apenas números em idade permitindo somente valores inteiros e permitindo valores nulos
As you have noticed everything gets translated including the class and attributes names. This happens by setting up Remarkable and Rails yml files.
3. Macros
In Remarkable earlier versions, we coded the matcher (validate_presence_of) but most of the time we had to do some tweaks in other to a matcher becomes a macro (should_validate_presence_of). In Remarkable 3.0 it happens transparently.
In other words, if you are using Remarkable 3.0 to build your matchers you have cleaner matchers, I18n support and transparent macros creation.
4. Pending and disabled macros
In Remarkable 2.2, we added the ability to mark macros as disabled:
xshould_validate_uniqueness_of :name
And it would print on your specs output:
As some people pointed out, Remarkable was still lacking support for pending macros. Pending examples in Rspec would be:
pending("create managers resource")
end
pending("create managers resource")
end
And now in Remarkable, you have the pending group:
pending "create managers resource" do
should_have_one :manager
should_validate_associated :manager
end
In both cases a message “PENDING: create managers resources” is appended to matcher description.
5. More options to matchers
In Remarkable 2.2, we started to support ALL Active Record validations with ALL options. And now we extended support for association matchers!
From only :dependent and :through as supported options, now it accepts:
Besides matchers became much smarter. Whenever :join_table or :through is given as option, it also checks if the given table exists. Whenever :foreign_key or :counter_cache is given, it also checks if the given column exists.
6. Controllers matchers extended
To provide I18n, we ported redirect_to and render_template matchers from rspec-rails. We also added some extra options to respond_with and render template, so you can now do:
render_template 'edit', :layout => 'users'
respond_with 422, :content_type => Mime::XML,
:body => /Unprocessable Entitity/
And the route matcher is willing to make your life twice easier. Since it tests params recognitation and routes generation at once, you can cut your routing_specs at least in a half! So the following lines:
route_for(:controller => "companies",
:action => "show",
:id => "1").should == "/companies/1"
params_from(:get, "/companies/1").should == {:controller => "companies",
:action => "show",
:id => "1" }
Will become:
route(:get, "/companies/1", :controller => "companies",
:action => "show",
:id => "1")
7. Macro stubs
There is a presentation from José Valim that explains this feature with more details, but it basically makes your controllers specs from this:
@task ||= mock_model(Task, stubs)
end
Task.should_receive(:new).with({'these' => 'params'}).
and_return(mock_task(:save => true))
post :create, :task => {:these => 'params'}
assigns[:task].should equal(mock_task)
end
Task.stub!(:new).and_return(mock_task(:save => true))
post :create, :task => {}
response.should redirect_to(task_url(mock_task))
end
end
end
Become this:
mock_models :task
expects :new, :on => Task, :with => {:these => 'params' }, :returns => mock_task
expects :save, :on => mock_task, :returns => true
should_assign_to :task, :with => mock_task
should_redirect_to {task_url(mock_task) }
end
end
It aims to improve readability and be more DRY, since you declare your expectations/stubs just once. You can see the whole controller specs in rspec and remarkable way compared here.
It works by eval’ing the expectation/stubs chain and performing the action before each macro is executed. On should_assign_to it evals using expectations (:should_receive), on should_redirect_to it uses stubs (:stub!).
We also want to thank David Chelimsky that gave the nice hint to allow :post => :create inside the describe method and suggested to use mocha syntax. :)
8. Documentation, documentation and documentation
Yes, three times, because each project is very well documented. Browse them:
Remarkable:
http://remarkable.rubyforge.org/core/
Remarkable ActiveRecord:
http://remarkable.rubyforge.org/activerecord/
http://remarkable.rubyforge.org/activerecord/classes/Remarkable/ActiveRecord/Matchers.html (just matchers)
Remarkable Rails:
http://remarkable.rubyforge.org/rails/
http://remarkable.rubyforge.org/rails/classes/Remarkable/ActionController/Matchers.html (just matchers)
9. Volunteers?
Last but definitely not least: we need you!

We created a solid basis for matchers/macros creation. And we want to take it further by hosting even more matchers. So anyone who wants to work on Remarkable Datamapper, Remarkable Sequel, Remarkable Sinatra, please step in! We are waiting for you. :)
And all the others can equally help us by joining the group and posting bugs, matchers, enhancements in bug tracking system.
Good times! It has been just one week since I announced Diego Carrion and José Valim as members of the Remarkable core team and we already put some effort into making a new shiny release! We are going to cover what’s new on this Remarkable version, step by step.
1. All ActiveRecord validations are supported with all options
In other words, you can write your spec validation macros the same way as you do in ActiveRecord, without consulting the documentation, without worrying if any validation is supported or not, without checking which options are allowed or not. Check it out:
end
Or if you prefer:
should_validate_uniqueness_of :email
should_validate_presence_of :email, :password
should_validate_confirmation_of :email, :password
should_validate_acceptance_of :terms
should_validate_inclusion_of :gender, %w(m f), :message => 'whoa! what are you then?'
should_validate_length_of :password, :within => 6..20
should_validate_numericality_of :age, :greater_than_or_equal_to => 18, :allow_nil => false
should_allow_mass_assignment_of :password, :email
should_not_allow_mass_assignment_of :salt, :hashed_password
end
We updated the wiki and it’s already reflecting the new macros. But you might ask, what happened with the older ones? The older ones are going to be deprecated and you will see a message while running the tests.
What you might have noticed above is that should_protect_attributes now became should_not_allow_mass_assignment_of. This one was based on Shoulda last changes, so who are porting tests from Shoulda gets everything compatible.
2. Pending macros
We are not just bringing macros to Rspec, we are bringng Rspec to macros! So let’s suppose you are doing some code refactoring and you know some tests will fail while you clean the house, what do you do then?
In Rspec, you can do:
xit {should validate_numericality_of(:age) }
Well, now you can do just the same with macros:
xshould_validate_numericality_of :age
And it’s even better because it shows you a nice message:
Yeah!
3. Full I18n support
You know how validations macros (as validate_presence_of) work? Let’s talk about it a little bit.
When you say that we should validate presence of e-mail, we set the e-mail to nil and save the object. Then we search in all error messages in e-mail, if it has a “can’t be blank” message, your validation is working properly and then the test passes, otherwise, the test fails. The problem is, if you change the error message in your application and do not change on the macro, we will never be able to find the message “can’t be blank” and then the tests will always pass.
This is valid for almost rspec matchers, not only on Remarkable. But what’s new is, if you change the message using the I18n YAML files, we will find the message properly and you don’t have to pass :message in your macros. This is new and we are currently the only one doing this.
But remember, if ever you set the message directly in your models like this:
validates_inclusion_of :gender, %w(m f), :message => 'whoa! what are you then?'
Don’t forget to do the same in your macros:
should_validate_inclusion_of :gender, %w(m f), :message => 'whoa! what are you then?'
Deal?
Conclusion
Remarkable is available on GitHub and to install it, just do on your console:
gem sources -a http://gems.github.com/
sudo gem install "carlosbrando-remarkable"
And then on your RAILS_ROOT/config/environment.rb:
config.gem "carlosbrando-remarkable", :lib => "remarkable", :source => "http://gems.github.com/"
Any doubts? Any bug?
We want to hear you! So you can use the Remarkable google group, our bug tracking system, Github comments, whatever suits you better!
See you there!
For a long time I was evangelizing Shoulda at Surgeworks and used it in my personal projects. The fact is, I didn’t have much success in convincing my co-workers to adopt Shoulda. On the other hand, they managed to convince me to learn and use RSpec.
RSpec is a very interesting Testing Framework. But I start to like it more after I started to use the Cucumber.
The great thing about Shoulda is that it’s simplifies tests for trivial things.
I got to like RSpec more and more, so I decided to adopt it as my official testing framework from now on. But I can no longer live without the resources that Shoulda offers me. So I decided to scratch my itch.
Remarkable
Initially, the main objective of Remarkable is to port all Shoulda macros to RSpec, but of course the plan is more ambitious than that. I have other ideas that will hopefully be especially useful for Rspec users.
At this point you may ask: “But aren’t there already plug-ins that do the same thing, such as skinny and rspec-on-rails-matchers. Why build something else?”
First, this isn’t simply “another” plugin with RSpec matchers. It also does a lot of things differently that I feel are better than other approaches.
Here are some of the things that make Remarkable special:
- It is not a plug-in; it’s a gem.
- All currently Shoulda macros are ported to RSpec.
- It has two different test syntaxes: one for those who like the RSpec style and another for those who are migrating their projects from Shoulda to RSpec.
- Tests.
- More tests.
- And a few more tests.
Unlike other similar projects, Remarkable is the only one that tests itself, and this is a big difference, believe me! How can we trust in a project that has no tests? How can you develop an open-source project with no tests? How do you ensure that the last commit didn’t break anything?
Install
Install Remarkable is very easy. It is stored in GitHub, so if you have never installed a gem via GitHub run the following:
Then install the gem:
In RAILS_ROOT/config/environment.rb:
config.gem "carlosbrando-remarkable", :lib => "remarkable", :source => "http://gems.github.com"
Using
All Remarkable macros can be accessed in two different ways. For those who prefer the Shoulda style, let’s look at some model tests:
fixtures :all
should_belong_to :user should_belong_to :owner should_belong_to :user, :owner
should_have_many :tags, :through => :taggings should_have_many :through_tags, :through => :taggings should_have_many :tags, :through_tags, :through => :taggings
should_require_unique_attributes :title should_require_attributes :body, :message => /wtf/ should_require_attributes :title should_only_allow_numeric_values_for :user_idend
Like Shoulda, right? That’s the idea! This syntax is for those who wish to migrate their Shoulda tests to RSpec. You basically just have to change context to describe and wrap your should statements with it {}.
But if you don’t like this syntax, you can also create the same tests as follows:
fixtures :all
Now with an RSpec style!
Macros
Here are all the available macros:
For Shoulda style, click here.
For RSpec style, click here.
Finalizing
This project has already reached the first goal, which was to port all Shoulda macros to RSpec. This has been done with great care and attention to detail, and I have tried to write lots of tests. But there is no substitute for using it in real life and finding areas that could use improvement.
Please use Remarkable and help me to make it even better!

Acabou de sair a última tradução do livro “Ruby on Rails 2.1 – O que há de novo?“, agora em espanhol.
Com mais esta tradução o livro está disponível em 8 línguas: português, inglês, japonês, chinês simplificado e tradicional, italiano, coreano e espanhol.
Esta tradução foi feita pelo meu amigo Gastón Ramos e Lucas Florio. O download da versão em espanhol pode ser feito clicando aqui. Também foi publicada um versão em html.
Tengo el agrado de de comunicarles que junto con Lucas Florio hemos finalizado la traducción completa al español del libro “Rails 2.1 ¿Qué hay de nuevo?” de Carlos Brando, la pueden descargar desde aquí y también está disponible la versión en html, este es el proyecto en github. Desde ya cualquier sugerencia o corrección es bienvenida.
In English
I am very happy to notice the launch of a Spanish version of the book “Ruby on Rails – What’s new?“.
The book was translated by Gastón Ramos and Lucas Florio.
To download click here. It also created a HTML version.
Now this book is already available in 8 languages: Portuguese, English, Japanese, Simplified and Traditional Chinese, Italian, Korean, and Spanish.

Graças ao formato open-source do livro “Ruby on Rails 2.1 – O que há de novo?” e ao fato de ele ser codificado ao invés de escrito em um editor de texto, muita gente aceitou o desafio de traduzir o livro para suas línguas.
Acabei de receber um e-mail de Libin Pan me avisando que a tradução para chinês terminou.
Libin Pan apenas coordenou o processo de tradução, porque assim como nós, eles também também tem uma comunidade muito forte que ajudou na tradução.
Parabéns a todos os nossos amigos chineses pelo excelente trabalho!
English
The “Ruby on Rails 2.1 – What’s new?” is a open-source book, so many people accepted the challenge to translate the book for their languages.
I just received an email from Libin Pan telling me that the translation into Chinese has finished.
Check the official announcement clicking here.
Congratulations to all our Chinese friends!

Photo by bananagranola
Português
Acabou de sair uma versão alpha da tradução do livro “Ruby on Rails – O que há de novo?” em japonês.
O livro foi traduzido por Hirobumi Hama, que fez o trabalho praticamente sozinho. Como não entendo nada de japonês, não sei dizer se tem muita coisa para ser corrigida até uma versão final, mas com este lançamento, acredito que a comunidade japonesa deve colaborar e em breve teremos uma versão final lançada.
Quero agradecer ao Hama, por este excelente trabalho e espero que ele também colha bons frutos com este trabalho!
Para fazer o download da versão em japonês, clique aqui.
English
An alpha version of the “Ruby on Rails – What’s new?” in Japanese has just been released.
The book was translated by Hirobumi Hama, who did the work almost alone. I don’t understand Japanese, so I don’t know if have a lot to be fixed to a final version, but with this release, I believe that the Japanese community will work and a final version will be released soon.
Congratulations to Hama for his excellent work and I hope he will reap good results from his hard work!
To download the Japanese version click here.
![]()
Inspirado pelo último screencast do Fábio Akita (totalmente recomendado), resolvi incluir uma leve brincadeira no meu gem Autotest Notification.
Não vou estragar a surpresa… mas para quem quiser conferir, basta instalar a nova versão do gem. Rode no terminal:
sudo gem install carlosbrando-autotest-notification -s http://gems.github.com
No Windows não precisa do sudo no começo…
Ok, e depois de instalado entre com o seguinte comando no terminal para ligar o gem:
an-install --doom
# são dois traços na frente do doom
Se quiser voltar para a versão normal, rode o mesmo comando, sem o –doom. Você também pode usar a opção -s para ouvir o gem falando com você.
Espero que os saudosistas se divirtam…
English
Inspired by the presentation of Ryan Davis in Goruco 2008 (recommended), I decided include a little joke in my Autotest Notification Gem.
I will not spoil the surprise… but for those who want to check, just install the new version of Gem. Turn on the terminal:
sudo gem install carlosbrando-autotest-notification -s http://gems.github.com
Okay, installed. Now run this command in the terminal:
an-install --doom
# are two dashes in front of doom
If you want to return to the normal version, run the same command without the –doom. You can also use the option -s to hear the gem talking to you.
I hope you have fun…
In English
Bruno Miranda revised the English version of the book, fixing some typos. So I’m publishing a second edition of the book with all adjustments.
This doesn’t mean that the first version contained errors, but the translation was done very quickly. Then imagine this version as a version made with more time.
To download the updated version, click here.
Em português
O Bruno Miranda fez uma revisão monstro na versão em inglês do livro, corrigindo alguns erros de gramática e ajustando os textos. Por isto estou publicando uma segunda edição do livro em inglês com todos os ajustes realizados.
Isto não significa que a primeira versão continha erros, mas realmente a tradução foi feita muita rápido, já que a idéia era lançar o livro primeiro que todo mundo, e é fato que isto impediu uma revisão mais detalhada. Então imaginem esta versão como uma versão feita com mais tempo.
Para fazer o download da versão atualizada, clique aqui.
Less than one week after the release of Rails 2.1, was launched in Brazil the first book describing all the new features of this release.
After the launch of the book in Portuguese, the Brazilian community united to translate the book into English.
Done! A gift from all Brazilian Railers to the international community.
To download click here.
Credits
The book was originally written by Carlos Brando and revised by Marcos Tapajos.
If you liked the book, you can recommend them:
Recommend Carlos Brando
Recommend Marcos Tapajos
Thank these guys for the English version:
- Recommend
- Introduction and chapter 1
- Recommend
- Chapters 3-8 and 10-13
- Recommend
- Chapter 9
- Recommend
- Chapter 14
Neither came out the Rails 2.1 and was already found a serious error. Access the irb and try to run this:
Date.new(2008, 5, 31).end_of_quarter
ERROR!
Why? The implementation of the method end_of_quarter was made of the wrong way, it moves until the last month of the quarter and then picks last day. The problem is that it only moves the month, but as the date is starting on May 31, it’s trying to create a new instance of the Date to June 31, which does not exist. The class Time not raise an exception, but returns the wrong date: July 31.
In Edge Rails this has already been corrected, but who are using Rails 2.1 will have this problem.
Very careful, because this error only occurs if you use the method end_of_quarter in day 31 of May, July, and August. So, very careful.
For those who do not like to live dangerously by using the edge rails, I created a plugin with the code that fixes the bug. I will try to keep out this plugin updated whenever any corrections is released.
To install:
Do you like it? Recommend me on Working With Rails.