Today I want to show you a project I’ve started over a year ago, during Mendicant University core skills course. For those who don’t know, Mendicant University is a group of skilled software developers that offer courses, mentoring, and help out the community, started by Gregory Brown, and that nowadays counts with some other awesome folks as part of the staff. I highly recommend taking a look at and enrolling.
Back to I18n, during Mendicant University we were supposed to create a project in Ruby, not specifically with Rails, and I decided to scratch my own itch by trying to solve a problem we usually have in Brazil: receiving date/time/numeric input from user interface. I know and have already used the delocalized gem, and it works quite nice, but sometimes I felt a bit uncomfortable about how it handled some parts of localization/parsing. This is mainly due to the need to monkey patch both ActiveRecord to handle input, and ActionView to handle output. Besides that, and most important, I had to come up with some project and I thought that’d be a good challenge
.
The main goal of this project is to provide a proxy object to use with your ORM (currently ActiveRecord only) that will be responsible for localizing and parsing the date/time/numeric attributes when getting or setting their values, respectively. Lets see some quick examples:
# Include the proxy in your model class Product < ActiveRecord::Base include I18n::Alchemy end # Grab your object from the database @product = Product.first # Instantiate the localized proxy @localized = @product.localized |
Now that we have a localized proxy for the @product object, we can get/set numeric attributes with localized values, such as:
@localized.price = "1.99" @product.price # => 1.99 @localized.price # => "1.99" I18n.with_locale :pt do @localized.price = "1,88" @product.price # => 1.88 @localized.price # => "1,88" end |
And also date/time attributes, for instance:
@localized.released_at = "12/31/2011" @product.released_at # => Date.new(2011, 12, 31) @localized.released_at # => "12/31/2011" I18n.with_locale :pt do @localized.released_at = "31/12/2011" @product.released_at # => Date.new(2011, 12, 31) @localized.released_at # => "31/12/2011" end |
I18n Alchemy can also receive a hash of attributes, the same way you use with your models when calling new. That means you can use it like this:
# You could be using params[:product] for instance. I18n.with_locale :pt do @localized = @product.localized(:price => "1,88") @product.price # => 1.88 @localized.price # => "1,88" end |
The parsing/localization formats are basically the same ones you already use in your Rails application. You can check the basic locale configuration for I18n Alchemy in its README on github.
Wrapping up
I18n Alchemy is a small and new project which solves most of the problems we commonly face when dealing with localization and parsing of date/time/numeric values. It is tested with Rails 3.0, 3.1 and 3.2 and works with all the basic methods, such as attributes=, assign_attributes, update_attributes and nested attributes as well.
It was a really fun time creating it during Mendicant University, and it took a long time until I decided to release it as a gem. There is still a bunch of things to do, but I wanted to ask you to give it a try and let me know about any feedback you have.
As a side note, if you are interested in knowing more about the design decisions that led this project, you may want to take a look at Gregory Brown’s post on Ruby Best Practices, entitled “Issue #23: SOLID Design Principles”, more specifically in the Open/closed principle topic.
I’m releasing the first 0.0.1 version today, and I hope you find it useful. Have any comments? Let us know!
Tags: date, i18n, localization, number, parsing, rails, ruby, time
Posted in English | Comments Off
Elixir is a new language we are building that targets the Erlang VM. Based on our strong Ruby background, we were asked several times and finally decided to write a blog post about why Rubists should play with Elixir. Granted that some of Elixir’s syntax and features comes from Ruby, however Elixir is definitely closer to Erlang than anything else. Single assignment variables, immutability, easy communication between processes, lists, tuples, binaries and OTP behaviors are all available in Elixir. Therefore, you will be able to learn a lot by using Elixir, here are the things I have enjoyed the most learning:
Pattern matching
Pattern matching is one of the features I enjoy the most in functional programming. They provide an easy to extract information from a data structure. For instance, in Elixir, you would write:
[first, second] = [1,2] first % => 1 second % => 2
You could definitely write something similar using Ruby assignment operator, but the gain in pattern matching comes from the fact you can use them in method signatures and, if a method signature does not match one specific pattern, the next method is tried. For instance, here is a method that iterates through a list of strings and print them:
module Printer
% This pattern matches a list with at least one element.
% The first element of the list is assigned to h, the remaining
% is assigned to tail.
def print([head|tail])
IO.puts head
print(tail) % Recursively calls print with the tail
end
% Eventually the list will be empty and the method above
% won't match, causing this one to match instead.
def print([])
% Do nothing, we are done printing items
end
end
Printer.print ["foo", "bar", "baz"]
Another cool example is a recursive method that checks if a list is a prefix of another list:
module Prefix % Iterate both lists. Check if the first element is equal then call itself again. % If the first element (i) is not equal, it won't match this method. def is?([i|prefix], [i|list]) is?(prefix, list); end % If the prefix is empty, is because everything matched, so return true. def is?([], _list) true; end % Else, return false def is?(_prefix, _list); false; end end Prefix.is?([1,2,3], [1,2,3,4,5]) % => true Prefix.is?([0,1,2], [1,2,3,4,5]) % => false
Finally, pattern matching allows us to easily have key-value args, one of the features planned to Ruby 2.0. This examples comes straight from Elixir code (notice that symbols in Elixir start with a single quote instead of colon):
module Record
def retrieve(name, 'from: file)
% Implementation ...
end
end
The fact that neither Elixir nor Erlang provides conditional loops like while forces you to think differently and use pattern matching in different occasions. Thinking differently about a problem that you are frequently solving in Ruby and coming up with a completely different solution is in general a very insightful and enjoying process.
Also, notice that both Elixir and Erlang do tail call optimization, so the methods above will perform nicely while you could get huge stack traces if you implemented such methods in Ruby in a similar fashion.
Single assignment variables and immutability
What I haven’t showed in the example above is that variables in Erlang are single assignment, therefore, the following will raise an error:
[first, second] = [1,2] first = 10
The above raises a bad match error because, since a value was already assigned to first, the second expressions first = 10 is actually comparing 1 to 10, which obviously fails. The fact variables are assigned just once is what allows us to implement our prefix method above, ensuring the value assigned to i matches in both lists.
Also, both in Elixir and Erlang, objects/data structures cannot be modified in place. They are immutable. Every modification generates a new object/data structure. Immutability removes the shared state internal to the language (you still have shared state if you have to do external operations) and play a key role on Erlang’s and Elixir’s concurrency.
Personally, I have found immutability to be a blessing and a curse at the same time. Mutability is not commonly an issue when working with Rails applications, but while working on Rails itself and other gems, we need to be frequently thinking about mutability. Sometimes you pass an object (like a hash or an array) to a method that modifies it in place and then you have to spend some time tracking how that new element ended up in your object.
When working in Elixir, since everything is immutable, I don’t need to worry about such cases and yes, it feels good! It feels like going from C to Java and then I suddenly don’t need to worry about memory management. However, such benefit comes with an obvious downside that some code just becomes more verbose.
To show this downside, consider a possible create action for PostsController similar to Rails, but where we have rewritten it to consider both immutability and single assignment variables:
def create
post0 = Post.new(params[:post])
post1 = post0.set(:published, false)
post2 = post1.save
if post2.persisted?
redirect_to post2
else
render :new
end
end
In such cases, the ORM could likely provided better APIs, but that is a pattern that would repeat over and over again. For instance, modifying the response cookies would require an explicit change in the response object:
response1 = response.cookies.set "tracker_code", "123456"
In any case, just working with a language that provides immutability and single assignment variables is worth the experience. You will learn a lot by trying it out that I could ever mention in a blog post. As pattern matching, it frequently forces you to handle problems through a different perspective which is extremely challenging and rewarding.
UPDATE: As some pointed out in the comments, Elixir can remove single assignment and still play properly with Erlang’s foundations. For this reason, Elixir now allows you to assign to the same variable more than once and has more flexible rules related to the variable scope (similar to Ruby) when compared to Erlang.
Communication between processes
Pattern matching, single assignment variables and immutability provides a good foundation for communication between processes. If you are interested to learn more about this one and see all these things working together, watch the screencast from previous week!
A different Object Model
Elixir has a different Object Model from Ruby. The Object Model is prototype-based like Javascript, in the sense there are no classes, but it is also different from Javascript and Self in the sense an object can still dictate how its children is going to look like, not necessarily being an exact copy from the parent. There is plenty more information about it Elixir’s README, including some other cool features like real private methods (maybe it will also be included in Ruby 2.0?) and local method calls.
You can always learn a lot by using other Object Models and this tip is not restricted only to Elixir. For instance, if you are not familiar with Javascript’s Object Model or other prototype based languages, I recommend you to learn it now!
Just learn
As I mentioned in the screencast and in the README, contributing to Elixir is quite easy because both the Standard Library and tests are written in Elixir itself. Now, imagine that you had to implement something like Ruby’s Set in Elixir. You would not learn about Ruby’s Set more, but also think about the best structure to use, which algorithm would be the best to update the Set and what would be a good API to access those objects.
Besides, there are other basic tools that are required in any language, like packaging system, documentation parser and test libraries that are currently missing in Elixir and you could be the one to implement it!
Wrapping up
I hope I have convinced you to try out Elixir. You can learn much more about the language itself by checking out its README.
Finally, if you need some inspiration to do crazy things, I recommend the Forking Ruby talk by Dave Thomas. As he said, we love Ruby and we are not moving away from it anytime soon, but forking it or trying out new things is a great way to improve the language and its ecosystem, and I hope Elixir helps you think more about that.
Tags: elixir, erlang, ruby
Posted in English | 14 Comments »
Outpost is me, scratching my own itch. For a while now, freelancing or working
for others, I work with pretty much all the stack in web development: from front-end
development with HTML and CSS up to the system administration.
And sometimes, I screw up. Sometimes, stuff go wrong. Maybe that Sphinx
isn’t getting indexed or even running after an unsuccessful deploy. Maybe that
background job isn’t being run, and I forget to verify it.
I know there are excellent tools that already solve this problem. But I wanted an
easy way I would be able to code my own monitoring rules, using one of the
languages I like the most. And also, the fantastic Aaron Patterson (or
tenderlove), one of the most prominent faces of the Ruby community once told in
a Q&A at RMU: it should be fun!
And thus the Outpost idea was born. Outpost is a framework so I can easily
implement Ruby code that query the current state of any service I want. I can
also write code that can go into the database and do a SELECT on a table (a
jobs table, for example) to check if everything’s fine.
What is Outpost?
Outpost is basically a DSL where you can describe rules to monitor your
service, application, server, whatever. Below is a very simple example:
require 'outpost' require 'outpost/scouts' class MyWebPageOutpost < Outpost::DSL using Outpost::Scouts::Http => "web page" do options :host => 'localhost', :port => 3000 report :up, :response_code => 200 report :down, :response_body => {:match => /Ops/} end end |
In this example, we are monitoring (using what I’ve called ‘Scouts’) HTTP
communication to localhost:3000. It will report that the system is
up if the response code is 200 (HTTP OK) and report that it is down if the
response body contains the word “Ops”, by matching a Regular Expression to it.
There is still a lot of work to be done, but I feel it is ready for a very first
release. There are only two Scouts today: HTTP and Ping, but it’s so
easy to write new ones that I will be releasing a few more in the next
days.
Also, there are only three expectation matchers: response time, response body
and response code. I believe they are able to cover most of the cases, but it is also
very easy to write new expectations.
Below is another example of an Outpost, based on the integration tests:
require 'outpost' require 'outpost/scouts' class ExamplePingAndHttp < Outpost::DSL using Outpost::Scouts::Http => 'master http server' do options :host => 'localhost', :port => 9595, :path => '/' report :up, :response_body => {:match => /Up/} end using Outpost::Scouts::Ping => 'load balancer' do options :host => 'localhost' report :up, :response_time => {:less_than => 500} end end |
For more details, please check the project’s README, on GitHub.
The future
My plans for Outpost are: SSH support, so you can connect to servers that do
not expose their services to the outer world, a very simple web dashboard to show
the results, better error reporting (for now you can only know which Scout
failed, but not why), a script that automatically generates Outposts for Rails
apps, and the list goes on!
Crazy idea: wouldn’t it be nice to have a script that reads Outposts and
tells if a machine is ready to be in production? TDD for machines? Woot!
Thanks
This project was my personal project for RMU (Ruby Mendicant University) and
so I would like to thank all the people involved for the amazing experience and
reviews on the project. Also thanks to my friends for listening me nagging
about this project for a while. Finally, thanks to Tomás D’Stefano, who
did some work on my previous attempt to write Outpost, your work won’t be
thrown away.
Closing
Please share your thoughts about this project. I would love to know your opinion!
Tags: devops, monitoring tools, outpost, ruby
Posted in English | 1 Comment »
Since moving to Mac, I always find it surprising that the default Mac OS X Ruby and IRB doesn’t allow inputs with accented characters. So, you cannot do
name = "George Guimarães" |
This is annoying for brazilians and anyone who uses non-ASCII characters. The problem is that the default Ruby in Mac OS X isn’t linked against readline. A simple solution is to compile readline on your system, and then compile your own ruby binaries. A better one is to use tools that automate this process.
This post by Christopher Sexton uses homebrew to compile readline-0.6 but compiles ruby by hand. Since we love RVM, we’ll use it too.
If you use Homebrew (and you *should*), just do
brew install readline brew link readline |
Beware: linking readline into your system may break other tools that depends on readline source to compile. It was harmless on my system.
Ok, so now we want to build a new ruby and irb binaries. I wanted to use ruby 1.8.7-p248, so:
rvm install 1.8.7-p248 -C --enable-shared,--with-readline-dir=/usr/local |
This tells the configure script to enable shared library linking (it is the default), and to search for readline in /usr/local (homebrew has just linked readline there). You may have to use --force if you already have this ruby version compiled. Newer versions of RVM do not need --force.
Now you can use accented and unicode characters on keyboard input in IRB using ruby 1.8.7.
And you? Do you have any tricks with IRB that you may want to share? Do you use Wirble, Utility Belt or others?
Tags: irb, ruby, rvm, unicode
Posted in English | 5 Comments »
One of the beauties in the Open Source world is the possibility of reading other people source code and learn new things. However, lately I found out that not only the library code, but the test suite of several open source projects are full lessons for us.
In this post, I want to tell you which are the three test suites that I admire the most and why.
Integration award: Railties
Rails 3 has several improvements and not all of them may be visible to the application developer. One of the hidden unicorns is Railties test suite. As Yehuda stated in a blog post during the refactoring of version 2.3 to 3.0:
“Although the Rails initializer tests covered a fair amount of area, successfully getting the tests to pass did not guarantee that Rails booted.”
This happened because, in order to have fast tests, Rails 2.3 suite stubbed and mocked a significant part of the booting process. The new test suite is able to create a new application using the application generator, change configuration options, add plugins and engines, boot it and even make HTTP requests using Rack::Test.
For instance, take a look at this test which ensures that app/metals inside plugins are successfully added to the application middleware stack:
def test_plugin_metals_added_to_middleware_stack @plugin.write 'app/metal/foo_metal.rb', <<-RUBY class FooMetal def self.call(env) [200, { "Content-Type" => "text/html"}, ["FooMetal"]] end end RUBY boot_rails require 'rack/test' extend Rack::Test::Methods get "/not/slash" assert_equal 200, last_response.status assert_equal "FooMetal", last_response.body end |
The most important lesson here is: whenever mocking or stubbing in our tests, we still need to add tests without the mocks and stubs to ensure all API contracts are respected.
Readability award: Capybara
Capybara is a tool to aid writing acceptance tests for web applications. Capybara can use several drivers to interact with a web application, as Selenium, Celerity or even Rack::Test. Each driver needs a different setup and has different features. For instance, both Selenium and Celerity can handle javascript, but not Rack::Test.
As you may imagine, all these different drivers can make a test suite become a real spaghetti. However, Jonas Nicklas was able to transform a potential problem into a very elegant and readable test suite with Rspec help. Here is, for instance, the tests for selenium:
describe Capybara::Driver::Selenium do before do @driver = Capybara::Driver::Selenium.new(TestApp) end it_should_behave_like "driver" it_should_behave_like "driver with javascript support" end |
Each behavior group above (“driver” and “driver with javascript support”) is inside Capybara library allowing everyone to develop its own extensions using a shared suite. For instance, if a driver has javascript support, it means the following tests should pass:
shared_examples_for "driver with javascript support" do before { @driver.visit('/with_js') } describe '#find' do it "should find dynamically changed nodes" do @driver.find('//p').first.text.should == 'I changed it' end end describe '#drag_to' do it "should drag and drop an object" do draggable = @driver.find('//div[@id="drag"]').first droppable = @driver.find('//div[@id="drop"]').first draggable.drag_to(droppable) @driver.find('//div[contains(., "Dropped!")]').should_not be_nil end end describe "#evaluate_script" do it "should return the value of the executed script" do @driver.evaluate_script('1+1').should == 2 end end end |
Capybara test suite is one of the best examples of using tests as documentation. By skimming the test suite you can easily know which features are supported by each driver! Sweet, isn’t it?
Friendliness award: I18n
When you are a big Open Source project, your test suite needs to be easy to run in order to new developers can create patches without hassle. The I18n library for Ruby definitely meets the big Open Source project requirement since it’s widely used and provides several extensions.
However, some of these extensions depends on ActiveRecord, some in ruby2ruby, others in ruby-cldr… and soon it will even support a few Key-Value stores, as Tokyo and Redis. Due to all these dependencies, you would probably imagine that running I18n test suite would require several trials and a lot of configuration before it finally works, right?
WRONG! If you don’t have ActiveRecord, I18n will say: “hey, you don’t have ActiveRecord” but still run the part of test suite that does not depend on it. So if a developer wants to fix or add something trivial, he doesn’t need to worry with installing all sorts of dependencies.
Besides, as mentioned a couple months ago, the I18n library allows you to create several combinations of backends. In other words, the I18n test suite needs to ensure that all these different combinations work as expected.
This problem is quite similar to the one in Capybara which needs to test different drivers. However, I18n uses Test::Unit thus it cannot use shared examples groups as in Rspec. So how were I18n developers able to solve this issue? Using Ruby modules!
Here are the tests for the upcoming KeyValue backend:
require 'test_helper' require 'api' class I18nKeyValueApiTest < Test::Unit::TestCase include Tests::Api::Basics include Tests::Api::Defaults include Tests::Api::Interpolation include Tests::Api::Link include Tests::Api::Lookup include Tests::Api::Pluralization # include Tests::Api::Procs include Tests::Api::Localization::Date include Tests::Api::Localization::DateTime include Tests::Api::Localization::Time # include Tests::Api::Localization::Procs STORE = Rufus::Tokyo::Cabinet.new('*') def setup I18n.backend = I18n::Backend::KeyValue.new(STORE) super end test "make sure we use the KeyValue backend" do assert_equal I18n::Backend::KeyValue, I18n.backend.class end end |
Each included module above adds a series of tests to the backend. Since key-value backends cannot store procs, we don’t include any test related to procs.
Wrapping up
These three are my favorite test suites and also part of my favorite open source projects!
We’ve adopted Capybara as the official testing tool at PlataformaTec for some time already and I18n is one of the subjects of my upcoming book about Rails 3. In one specific chapter, we will build a tool that stores I18n translations into TokyoCabinet, which allows us to create and update translations through a web interface, similarly to ActiveRecord. The only difference is that TokyoCabinet is waaaay faster.
Finally, the fact you can mimic several of Rspec features using simple Ruby (like Capybara using shared example groups and I18n simply using modules) will be part of my talk in Euruko 2010 entitled DSL or NoDSL: The power is in the middle. The talk will show cases where DSLs mimics much of the behavior provided by Ruby and discuss what we are winning and/or losing in such cases.
Keep following us and, until the next blog post is out, we would love to hear in the comments which are your favorite test suites!
Tags: capybara, euruko, i18n, open source, rails 3, railties, ruby, tests
Posted in English | 5 Comments »
This weekend during Rails Bugmash I stumbled across some nice posts about Rails 3 generators which motivated me to share them and add some comments!
First, David Trasbo wrote a nice guide about how to make your first Rails 3 generator, it covers up all the basic steps including setting it up in a gem. He also puts the deserved attention into Thor::Actions, which contains most helpers you need in a generator, like copy_file, template, create_file, empty_directory and so on.
On another post, Ben Scofield talks about apply method, which is also in Thor::Actions, and how to use it to dry your application templates.
Wait… so Thor::Actions is used both in generators and in Rails application templates? Exactly, Rails’ new generators unifies both application templates and generators API into one. While Thor::Actions holds basic methods, all Rails specific methods like environment, rakefile, generator are in Rails::Generators::Actions. If you already wrote an application template, you will feel more at home when writing a Rails 3 generator.
Paul Barry talks how easy it’s to customize your scaffold to use Rspec, Haml and Factory Girl instead of Test::Unit, Erb and Fixtures. This all works because scaffold is just a meta generator which provides hooks for template engine, test framework, ORM and so forth. A good way to see the hooks system working is by running script/generate scaffold --help before and after Paul changes, so you can see exactly how generators options update depending on the configuration values you set. While I wrote Rspec generators used in the example, he implemented himself Haml and Factory Girl generators and they can all be used as example if you plan to build your own.
Finally, Zigzag Chen wrote about templates customization and how you can change your scaffold controller to use json instead of the xml format. New generators have source paths, so you can customize them simply by copying files to RAILS_ROOT/lib/templates.
Rails Bugmash was excellent to gather feedback and we also got some tickets on Lighthouse, mainly about how generators help can be improved for people starting with Rails. Many thanks to Rails Bridge and besides the posts linked above, there is a generator guide, which may help you get started and maybe write your own post as well.
Tags: gems, generators, plugins, rails, ruby, thor
Posted in English | 8 Comments »

All
English only
Em português apenas