Há estudos indicando que 42% das empresas paulistas fecham com até dois anos de existência.
E nós estamos sobrevivendo bem às estatísticas. Por isso, estamos em busca de mais desenvolvedores Rails para trabalhar conosco! \o/
Procuramos por geeks, com disponibilidade full-time, que realmente gostem de ‘codar’ e fazer um trabalho bem feito, limpo e sem remendos. Para esta vaga em aberto, não é necessário ter experiência com Rails. Porém, é um requisito que você já tenha trabalhado com outras linguagens orientadas a objeto e desenvolvimento para web por pelo menos um ano. Ao final do post há uma lista de habilidades que buscamos. Não esqueça de checar.

We love geeks! v2.0 (sorry girls!)***
Sobre a vaga… apesar de não atuar diretamente, o novo desenvolvedor estará envolvido com todas as áreas relacionadas aos projetos (deployment, decisões de arquitetura e infra-estrutura, questões de escalabilidade, gestão de projetos ágeis e o próprio desenvolvimento em si).
É assim que trabalhamos na Plataforma Tecnologia. Não há feudos de Gerentes Projetos vs. Arquitetos vs. Desenvolvedores vs. Designers. Cada um possui seu papel, mas a entrega de resultados depende de um time multi-disciplinar que entende a visão geral do projeto.
Bem pessoal, segue o resumo dos requisitos:
- Inglês intermediário
- Cultura ‘hacker’
- Programação orientada a objetos
- Experiência prévia com desenvolvimento de aplicativos web
- Não é necessário experiência em Ruby on Rails (mas será diferencial para os que tiverem)
- Desejável ser usuário de OS Linux ou Mac (Windows is so over…)
- Disponibilidade full-time
- Local: São Paulo (negociável)
Geeks com sede por aprendizado, uni-vos!
Enviem seus CVs para trabalhe@plataformatec.com.br.
*** Por total insensibilidade da minha parte, e totalmente sem querer, a imagem previamente publicada neste post poderia ser interpretada como ofensiva e machista. Não era essa a idéia. Estamos procurando por developers, independente do sexo.
Aproveito para agradecer as gentis meninas do ‘devchix’ que nos alertaram e nos deram feedback sobre a imagem originalmente postada. Thanks and really sorry girls! =)
Tags: contratando, geeks, hackers, plataformers, vagas
Posted in Português | View Comments
You probably know that Active Record got a facelift and is now powered by Active Relation. A new chainable-award-winning-lazy API was added and received great feedback! However, as more and more people are trying Rails 3 beta, a small incompatibility between the old and new syntax was found. This post explains this incompatibility and how it was solved.
The issue
Quoting the Lighthouse ticket, imagine the following scenario in Rails 2.3:
class Page < ActiveRecord::Base default_scope :conditions => { :deleted_at => nil } def self.deleted with_exclusive_scope :find => { :conditions => "pages.deleted_at IS NOT NULL" } do all end end end
If you rewrite it to the new 3.0 syntax, your first attempt would probably be:
class Page < ActiveRecord::Base default_scope where(:deleted_at => nil) def self.deleted with_exclusive_scope :find => where('pages.deleted_at IS NOT NULL') do all end end end
However, if you try it out on console, you will find out it does not work as expected:
Page.all #=> SELECT "pages".* FROM "pages" WHERE ("pages"."deleted_at" IS NULL) Page.deleted.all #=> SELECT "pages".* FROM "pages" WHERE ("pages"."deleted_at" IS NULL) AND ("pages"."deleted_at" IS NOT NULL)
To understand why it does not work, let’s take a look at the source code!
Investigating the issue
With Active Relation, Active Record is no longer responsible to build queries. That said, ActiveRecord::Base is not the one that implements where() and friends, in fact, it simply delegates to an ActiveRecord::Relation object. From ActiveRecord::Base source code:
delegate :select, :group, :order, :limit, :joins, :where, :preload, :eager_load, :includes, :from, :lock, :readonly, :having, :create_with, :to => :scoped
And the scoped implementation is shown below:
def scoped(options = nil) if options.present? scoped.apply_finder_options(options) else current_scoped_methods ? relation.merge(current_scoped_methods) : relation.clone end end def relation @relation ||= ActiveRecord::Relation.new(self, arel_table) finder_needs_type_condition? ? @relation.where(type_condition) : @relation end
As you can see, scoped always returns an ActiveRecord::Relation that you build your query on top of (notice that ARel::Relation is not the same as ActiveRecord::Relation).
Besides, if there is any current_scoped_methods, the scoped method is responsible to merge this current scope into the raw relation. This is where things get interesting.
When you create your model, current_scoped_methods returns by default nil. However, when you define a default_scope, the current scope now becomes the relation given to default_scope, meaning that, every time you call scoped, it returns the raw relation merged with your default scope.
The whole idea of with_exclusive_scope is to be able to make a query without taking the default scope into account, just the relation you give in as argument. That said, it basically sets the current_scope_methods back to nil, so every time you call scoped to build your queries, it will be built on top of the raw relation without the default scope.
With that in mind, if we look again at the code which we were trying to port from Rails 2.3, we can finally understand what was happening:
def self.deleted with_exclusive_scope :find => where('pages.deleted_at IS NOT NULL') do self end end
When we called where('pages.deleted_at IS NOT NULL') above, we were doing the same as: scoped.where('pages.deleted_at IS NOT NULL'). But, as scoped was called outside the with_exclusive_scope block, it means that the relation given as argument to :find was built on top of default_scope explaining the query we saw as results.
For example, the following syntax would work as expected:
def self.deleted with_exclusive_scope do where('pages.deleted_at IS NOT NULL').all end end
Since we are calling where inside the block, the scoped method no longer takes the default scope into account. However, moving the relation inside the block is not the same as specifying it to :find, because if we were doing three queries inside the block, we would have to specify the same relation three times (or refactor the whole code to always do a query on top of this new relation).
That said, it seems the previous with_exclusive_scope syntax does not suit very well with ActiveRecord’s new API. Maybe is it time for change? Can we provide a better API? Which are the use cases?
Identifying the use cases
The with_exclusive_scope method has mainly two use cases. The first one, which we just discussed above, is to allow us to make a query without taking the default scope into account inside our models:
def self.deleted with_exclusive_scope do where('pages.deleted_at IS NOT NULL').all end end
While this code looks ok, if we think about relations, we will realize that we don’t need to give a block to achieve the behavior we want. If the scoped method returns a raw relation with the default scope, couldn’t we have a method that always returns the raw relation? Allowing us to build our query without taking the default scope into account?
In fact, this method was already implemented in Active Record and it is called unscoped. That said, the code above could simply be rewritten as:
def self.deleted unscoped.where('pages.deleted_at IS NOT NULL').all end
Much simpler! So, it seems that we don’t need to support the block usage at all, confirm?
Deny! Going back to the Page example above, it seems we should never see deleted pages, that’s why we set the default_scope to :deleted_at => nil. However, if this application has an admin section, the admin may want to see all pages, including the deleted ones.
That said, what we could do is to have one controller for the normal User and another for the Admin. In the former, we would always use Page.all, and Page.unscoped.all in the latter.
However, if these controllers and views are very similar, you may not want do duplicate everything. Maybe it would be easier if we do something like this:
def resource_class if current_user.is_admin? Page.unscoped else Page end end
And, instead of always referencing the Page class directly in our actions, we could call resource_class. While this solution is also ok, there is a final alternative, that would require no changes to the current code. If you want to use the same controller for different roles, but changing the scope of what they are allowed to see, you could simply use an around_filter to change the model scope during the execution of an action. Here is an example:
class PagesController < ApplicationController around_filter :apply_scope # some code ... protected def apply_scope if current_user.admin? Page.with_exclusive_scope { yield } else yield end end end
That said, being allowed to give a block to with_exclusive_scope is actually useful and since we want to deprecate with_exclusive_scope in favor of unscoped in the future, we brought this very same syntax to unscoped as well:
def apply_scope if current_user.admin? Page.unscoped { yield } else yield end end
Tidying it up
Well, after the behavior in with_exclusive_scope was properly ported to the new API, we need to be sure we are not forgetting about anything… wait, actually we are.
with_exclusive_scope has an evil twin brother called with_scope which behaves very similarly, except that it always build the query on top of the scoped relation. It works like this:
class Page < ActiveRecord::Base default_scope where(:deleted_at => nil) end Page.with_scope :find => { :conditions => { :active => true } } do Page.all #=> Bring all active pages that were not deleted end
However, this feels way too hash-ish. Of course, we could use relations to make it a bit prettier:
Page.with_scope :find => where(:active => true) do Page.all #=> Bring all active pages that were not deleted end
This is ok, but it seems that we could improve it even more. That said, we added a new method to relations, called scoping:
Page.where(:active => true).scoping do Page.all #=> Bring all active pages that were not deleted end
Yeah! Sign me up ’cause this looks way better than the previous syntax! And, if you check the original commit, you will notice the unscoped method with a block simply delegates scoping:
def unscoped block_given? ? relation.scoping { yield } : relation end
So, with unscoped and scoping implemented, we just need to commit, git push and be happy, confirm? Deny! There is one last case to check.
create_with
If you payed attention properly, you can notice that every time we called with_exclusive_scope and with_scope, we always passed { :find => relation } as hash, instead of simply giving the relation. This happens because these methods accept two hash keys: find and create.
As you may expect, one specifies the behavior for create and the other for finding. In most of the cases, they are exactly the same and work with the new syntax:
page = Page.where(:active => true).new page.active #=> true
However, for obvious reasons, this only works if the conditions are given as a hash. Consider this case:
page = Page.where("active = true").new page.active #=> nil
That said, there may be a few scenarios where you want to specify the creation conditions on its own, explaining the :find and :create options in with_exclusive_scope and with_scope methods. So, how can I achieve it with the new syntax? Easy!
page = Page.create_with(:active => true).new page.active #=> true
If you provide both conditions as a hash and create_with, create_with always have higher priority:
page = Page.where(:active => false).create_with(:active => true).new page.active #=> true
Note this syntax already existed, we are just making it explicit now as part of the new API! That said, commit, push and be happy!
Wrapping up
All in all, with_exclusive_scope and with_scope are now part of the old ActiveRecord API giving place to the new, strong and vibrant unscoped and scoping methods!
However, they are not going to be deprecated now. They will follow the same deprecation strategy as all the current methods.
And you? What do you think about this new scoping API?
Tags: activerecord, arel, rails3, scopes
Posted in English | View Comments
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!
Tags: form, gems, open source, plugins, rails, rails3, simple_form
Posted in English | View Comments
At the end of May, I was honored to talk at Euruko, the most important Ruby event in Europe! The event was excellent, the organizers made an awesome work before, during and they are still keeping it up by releasing several videos along this week!
Without further ado, here follows my talk video:
DSL or NoDSL by José Valim from Krakow Tech Conferences.
Also, I uploaded my slides (even though they do not make a lot of sense by themselves) as a way to complete the awesome list of resources being wrapped at http://euruko2010.heroku.com/! I’m definitely looking forward to Euruko 2011 in Berlin!
Posted in English | View Comments
Nesse sábado (29/05/2010) eu fiz uma palestra sobre Rails 3 no evento Ruby e Rails no Mundo Real 2010. O evento foi muito bom, tendo cerca de 200 pessoas participando. Queria agradecer a todos que estavam lá para ver minha palestra e agradecer também aos elogios, muito obrigado.
Seguem meus slides:
E o vídeo da minha palestra, que foi feito pelo @agaelebe.
Posted in Português | View Comments
Antes de divulgar o resultado, nós gostaríamos de agradecer à todos que participaram e ajudaram a divulgar o evento. Muito obrigado a todos!
Pessoal, temos uma surpresa para anunciar… Ao invés de premiarmos a comunidade Rails com somente um ingresso, nós decidimos sortear 2 entradas para o Ruby + Rails no Mundo Real 2010. FTW!!! \o/
Sem mais mistérios, vamos aos dois ganhadores:
@jonas_alves:
@lucasmazza:
PARABÉNS!
Para receber os códigos para inscrição, enviem uma DM para @plataformatec com seus contatos (e-mail e telefone).
Atenção, pois as incrições só poderão ser realizadas até o dia 25/mai.
Nos vemos lá no Ruby + Rails no Mundo Real 2010,
Abraços!
Tags: eventos, são paulo
Posted in Português | View Comments

All
English only
Em português apenas


