/* CODIFICANDO */

Relatos de um programador em contínua aprendizagem.

Posts Tagueados ‘activerecord

Nova versão do plugin Booleanize: Agora recebendo Hashes!

sem comentários

Agora o plugin Booleanize também pode receber Hashes, além de Arrays e Symbols como parâmetros para o método booleanize.

class User  < ActiveRecord::Base
  booleanize :deleted => ["Yes, I'm gone", "No, I'm still here!"], :active => ["Yes!", "No"]
end

É possível também misturar os atributos

class User < ActiveRecord::Base
  booleanize :active, [:deleted, "Yes, I'm gone", "No, I'm still here!"], :smart => ["Smart!", "No, very dumb"]
end

O único cuidado é que o Hash deve ser o último parâmetro da lista, caso contrário você terá que colocá-lo entre chaves { … }

Agradeço ao Shairon Toledo que deu a idéia na lista do Rails-BR.

Escrito por cassiomarques

Dezembro 2, 2008 em 4:17 pm

Publicado em rails, ruby

Etiquetado com ,

Booleanize: Plugin para facilitar o trabalho com atributos booleanos com Active Record

com 5 comentários

Escrevi um pequeno plugin chamado Booleanize, que facilita um pouco nossa vida para trabalhar com atributos booleanos nos nossos models Active Record. Ou melhor, facilitou a minha vida, por isso escrevi o plugin. Espero que facilite a vida de mais alguém também!

Em alguns projetos eu preciso usar atributos do tipo boolean em diversos models e isso acaba duplicando código em várias lugares. O Booleanize resolve um pouco desse problema, criando 4 novos métodos, sendo dois de instância e dois named scopes.

Métodos de instância

Suponha que você possui um atributo booleano chamado active dentro de um model User. Se você passar o nome deste atributo na forma de um symbol para o método booleanize, dois novos métodos de instância serão criados:

  • active? – Informa se o valor do atributo é true ou false. Caso o atributo seja nil, será retornado false.
  • active_humanize – Retorna uma string representando true ou uma string representando false.
class User < ActiveRecord::Base
  booleanize :active
end

u = User.new(:active => true)
u.active? #=> true
u.active_humanize #=> "True"
u.active = false
u.active_humanize #=> "False"
u.active? #=> false

Você também pode especificar quais strings o Booleanize deve usar para os valores true ou false, passando um array de três elementos com o formato [:attr_name, "string para true", "string para false"].

class User < ActiveRecord::Base
  booleanize [:active, "Yes", "No"]
end

u = User.new(:active => true)
u.active_humanize #=> "Yes"

Named scopes

O Booleanize criará dois novos named_scope para cada atributo recebido. Usando novamente o exemplo dado acima, teremos:

  • active – Retornará todos os objetos para os quais o atributo booleano active for true. É equivalente a escrever:
      named_scope :active, :conditions => {:active => true}
      
  • not_active – Retornará todos os objetos para os quais o atributo booleano active for false. É equivalente a escrever:
      named_scope :not_active, :conditions => {:active => false}
      

Múltiplos atributos de uma única vez

Você pode passar vários parâmetros para o método booleanize de uma única vez, tanto na forma de um symbol como na forma de um array de três elementos

class User < ActiveRecord::Base
  booleanize :active, [:smart, "Yes!", "No, dumb"], :friend
end

Resumo

É simples: Ao invés de ter que escrever

class User < ActiveRecord::Base
  named_scope :active, :conditions => {:active => true}
  named_scope :not_active, :conditions => {:active => false}

  def active_humanize
    active ? "Yes" : "No"
  end

  def active?
    active ? true : false  #=> because we'll always want it to return true or false, and never nil.
  end
end

você pode escrever apenas

class User < ActiveRecord::Base
  booleanize [:active, "Yes", "No"]
end

Instalação

Basta usar o GIT e clonar o plugin dentro da pasta vendor/plugins da sua aplicação Rails. A partir de sua aplicação, faça

git clone git://github.com/cassiomarques/booleanize.git vendor/plugins/booleanize

e pronto.

Testes

O Booleanize possui muitos testes unitários, escritos com o RSpec, para garantir seu correto funcionamento. Caso queira executar estes testes, dê uma olhada no README do projeto no GitHub.

Escrito por cassiomarques

Dezembro 1, 2008 em 3:23 pm

Publicado em rails, ruby

Etiquetado com , ,

Seu model não pode ter um atributo chamado “type”, seu burro!

sem comentários

Essa me pegou hoje… Como raramente utilizo single table inheritance, esqueci que type é uma palavra reservada no Active Record. Criei um novo model e tasquei um atributo type na migration… o que aconteceu quando fui criar uma factory com o Factory Girl para testar a coisa toda?

client_factory.rb:12:in `type': wrong number of arguments (1 for 0) (ArgumentError)

Ainda bem que uso testes :-)

Tarefa para casa: Escrever 1000x no VI: “Não posso criar um atributo chamado ‘type’ em um model Active Record”

Foi só trocar o nome do atributo para outra coisa qualquer (no meu caso troquei para ‘category’) e pronto.

Escrito por cassiomarques

Novembro 11, 2008 em 7:30 pm

Publicado em activerecord, rails

Etiquetado com ,

Usando a opção :through no has_many

com 5 comentários

Que os métodos para associações entre models do ActiveRecord quebra um galhão todo mundo sabe. O interessante é que quando não conhecemos e/ou estamos habituados a utilizar os recursos do ActiveRecord, existe uma forte tendência a não utilizar estes métodos para associação ou ainda escrever métodos de pesquisa com sentenças SQL puras, usando o famigerado find_by_sql. O fato é que sempre que possível deve-se usar os recursos disponíveis pelo AR, pois isso gera um código mais limpo, legível e, para os puristas de plantão, mais OO.

O AR tem muitos recursos para facilitar a associação entre os models e tornar automáticas (ou quase) buscas que de outra forma exigiriam a criação de sentença SQL complexas cheias de joins. Um destes recursos é a opção has_many, através da qual podemos dizer coisas como “um carro tem muitas peças”.

class Peca < ActiveRecord::Base
  belongs_to :carro
end

class Carro < ActiveRecord::Base
  has_many :pecas
end

E podemos usar isso assim

@carro = Carro.find(1)
@pecas = @carro.pecas # &lt;= retorna uma lista de objetos da classe Peca

Essa busca é feita através das chaves primárias/estrangeiras presentes nas tabelas. Na verdade voc6e não precisa ter essas contraints realmente criadas no banco, desde que obedeça certos critérios de nomenclatura para as colunas das suas tabelas. No exemplo acima, o Rails vai assumir que uma coluna chamada carro_id na tabela pecas indica a coluna id da tabela carros e assim relaciona os dois models.

Um exemplo mais complexo seria o caso onde temos um esquema do tipo:

  • Uma empresa tem vários clientes
  • Cada cliente possui várias faturas

Neste cenário, podemos querer pesquisar todas as faturas de uma determinada empresa. O problema é que não existe na tabela faturas uma coluna chamada empresa_id. Como o Rails vai então relacionar as coisas?
A tabela clientes possui essa coluna empresa_id!
Podemos então utilizar a opção :through da associação has_many, e fazer com que o ActiveRecord utilize um join para associar as tabelas “empresas” e “faturas” através da tabela “clientes”. Assim:

class Empresa < ActiveRecord::Base
  has_many :clientes
  has_many :faturas, :through => :clientes
end

class Cliente < ActiveRecord::Base
  belongs_to :empresa
  has_many :faturas
end

class Fatura < ActiveRecord::Base
  belongs_to :cliente
end

E podemos fazer coisas como

@empresa = Empresa.find(1)
@faturas = @empresa.faturas

O Rails vai pesquisar o banco usando um SQL mais ou menos assim (que você não precisou escrever!):

SELECT "faturas".* FROM "faturas" INNER JOIN clientes ON faturas.cliente_id = clientes.id WHERE (("clientes".empresa_id = 1))

Escrito por cassiomarques

Julho 24, 2008 em 6:10 pm

Publicado em activerecord, rails

Etiquetado com ,