Datas em campos text_field

Conforme a discussão na lista rails-br, ainda não encontrei uma boa forma de resolver o problema de entrada de datas em formato brasileiro em um text_field. O problema ocorre porque o formato esperado é ano/mês/dia (ou mês/dia/ano, dependendo do banco de dados), enquanto que o formato brasileiro é dia/mês/ano. Para os interessados, resolvi paliativamente o problema com o monkeypatching abaixo (coloque o código em um arquivo no diretório config/initializers) . Vou testar melhor essa solução e atualizo aqui eventuais mudanças. Se alguém souber de uma solução melhor, me avise!

class ActionView::Helpers::FormBuilder

  def text_field_with_conversion(*args)
    # args[0] is the method
    if object
      column = object.class.columns_hash[args[0].to_s]
      args[0] = "convert_#{args[0]}".to_sym if column &&
                                               column.type == :datetime
    else
      # TODO: treat symbols, ex.: text_field(:model, :attribute)
    end
    text_field_without_conversion(*args)
  end
  alias_method_chain :text_field, :conversion
end

module ActiveRecord
  class Base
    def method_missing_with_conversion(method_id, *args)
      if method_id.to_s.starts_with? "convert_"
        method_name = method_id.to_s[8..-1]
        eval %{
            def convert_#{method_name}=(value)
              @original_#{method_name} = value
              self.#{method_name} = UtilDate.to_date(value)
            end
            def convert_#{method_name}                            
              #{method_name}.blank? ? @original_#{method_name} : 
                                      #{method_name}
            end
          }
      else
        method_missing_without_conversion(method_id, *args)
      end
    end
    alias_method_chain :method_missing, :conversion
  end
end

Palestra sobre Ruby on Rails

Decidi mudar um pouco o foco do meu blog. No antigo eu escrevia esporadicamente sobre pequenos hacks no Ruby on Rails. Como atualmente estou, além de desenvolvendo sistemas, trabalhando em consultorias e ministrando cursos e palestras, achei que seria interessante compartilhar também um pouco dessa experiência em meu blog.

Portanto, amanhã, dia 22 de outubro, 19h, vou ministrar uma palestra introdutória ao Ruby on Rails na Targettrust, assim como falar um pouco da minha experiência em desenvolver aplicações Web. Estão todos convidados!

Mais informações neste link .

Tell Validations to Look in the Database

If you already worked on a project with many tables and hundreds of fields, where most requirements are based on simple CRUD operations, you probably looked for a plugin to reduce all the repetitive work. There are many plugins for these cases that help to DRY the controller and model. Good examples are resources_controller and make_resourceful plugins.

Unfortunately, my experience told me that when I change too much the way I develop in Rails, even in applications with lots of fields, the adoption of a plugin with such a broad effect can be dangerous and not worth on the long run. So I became a fan of tiny useful hacks with very specific purposes that don’t change the big picture. It is easy to modify or delete them.

Recently, dealing with a large set of fields in my models, I was looking for a plugin to help me to do validations from database metadata. But, hey, that is easy! I don’t need a plugin for this!

module ActiveRecord
  class Base
    def self.not_null_attributes
      columns.map {|c| c.name if c.null == false}.compact - ['id']
    end

    def self.integer_attributes
      columns.map {|c| c.name if c.type == :integer}.compact - ['id']
    end

    def self.decimal_attributes
      columns.map {|c| c.name if c.type == :decimal}.compact - ['id']
    end
  end
end

I just put the above code in a file under config/initializers and it was ready to go. How to use it?

validates_presence_of integer_attributes

Suppose I don’t want the counter attribute to be validate:

validates_presence_of integer_attributes - ['counter']

Here are the validations in my class. I liked it!

class SomeComplexEquipment < ActiveRecord::Base
  # code
  validates_presence_of not_null_attributes
  validates_numericality_of decimal_attributes,
                                 :allow_nil => true
  validates_numericality_of integer_attributes,
                                 :allow_nil => true,
                                 :integer => true,
  # more code
end

If you find it useful, notice that you can instead create a method that receives the field type as a parameter. Something like attributes_of_type(type) (Doesn’t Rails already have it? :)