Skip to content

Instantly share code, notes, and snippets.

@pauloschiavon
Last active August 29, 2015 14:22
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pauloschiavon/97c684e68ac148db4489 to your computer and use it in GitHub Desktop.
Save pauloschiavon/97c684e68ac148db4489 to your computer and use it in GitHub Desktop.
Alternativa para criação de modelos/tabelas de domínio

Motivação

Sempre torci o nariz para criação de modelos de domínios (status.rb, genero.rb, tipo.rb, ...), principalmente quando o usuário não terá acesso para adicionar ou editar estes dados. Uma alternativa para isto é criar um modulo onde os domínios serão hashs:

# app/utilities/data_base.rb
module DataBase
  def self.gender
    { "Male"    => 1, 
      "Female"  => 2
    }
  end
end
 
 
# app/models/user.rb
class User < ActiveRecord::Base
  validates :gender, inclusion: { in: DataBase.gender.values }
end
 
 
# views/users/_form.html.rb - use simple_form
<%= user_form.input :gender, collection: DataBase.gender %>

Acessando os valores

Basta informar qual é a descrição do valor desejado:

# app/models/user.rb
class User < ActiveRecord::Base
  validates :gender, inclusion: { in: DataBase.gender.values }
  
  scope :male, -> { where(gender: DataBase.gender["Male"]) }
end

Passar a descrição desta maneira, me incomoda um pouco pois o código pouco legível. Costumo contornar isto, desta forma:

# app/utilities/data_base.rb
module DataBase
  def self.gender(key = nil)
    data = { "Male"    => 1, 
             "Female"  => 2
           }
    
    key.nil? ? data : data[key.to_s]
  end
end
 
 
# app/models/user.rb
class User < ActiveRecord::Base
  validates :gender, inclusion: { in: DataBase.gender.values }
  
  scope :male, -> { where(gender: DataBase.gender :male) }
end

Internacionalização

Aqui esta a principal vantagem de não criar modelos para os domínios

# app/utilities/data_base.rb
module DataBase
  def self.gender(key = nil)
    data = { I18n.t('base.gender.male')    => 1, 
             I18n.t('base.gender.female')  => 2
           }
    
    key.nil? ? data : data[ I18n.t("base.gender.#{key.to_s}") ]
  end
end
 
# config/locales/pt-BR/pt-BR/base.pt-BR.yml
br:
  base:
    gender:
      male: "Homem"
      female: "Mulher"

O código para acessar o valor do domínio voltou a ficar ruim. Melhorando ele:

# app/utilities/data_base.rb
module DataBase
  def self.gender(key = nil)
    data = { I18n.t('base.gender.male')    => 1, 
             I18n.t('base.gender.female')  => 2
           }
    
    key.nil? ? data : data[ DataBase.i18n(:gender, key) ]
  end
	
	def self.i18n(domain, key)
		I18n.t("base.#{domain.to_s}.#{key.to_s}")
	end
end

Flexibilidade

Outro ponto interessante desta abordagem é a flexibilidade em exibir os domínios. Exemplo: Em uma tabela polimorfica para endereço deve ser exibido para o campo address_type as opcões Residencial e Comercial quando for User e Matriz e Filial para associação com Company.

# app/utilities/data_base.rb
module DataBase
  def self.address_type(type, key = nil)
    if type == "User"
      data = { I18n.t('base.address.home')    => 1, 
               I18n.t('base.address.work')  => 2
             }
    else
       data = { I18n.t('base.address.headquarter')  => 1, 
                I18n.t('base.address.subsidiary')   => 2
              }
    end
    
    key.nil? ? data : data[ DataBase.i18n(:address, key) ]
  end
	
  # ... omitted self.i18n
end

Desvantagens

  • Todo acesso a domínio irá criar um hash
  • Caso mais de uma aplicação acesse a base de dados, existirá código replicado
  • Quando executar querys em um console, terá a necessidade de colocar 'hardcode' e não poderá fazer joins

Vantagens

  • Aplicação mais simples
  • Flexibilidade para os domínios
  • Internacionalização
  • Validações não acessam base de dados.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment