Qualquer um que comece a desenvolver com Active Record (AR), minha primeira recomendação é, para tudo e leia: A Guide to Active Record Associations ou O Guia de Associações do Active Record. O guia é bem completo, e descreve muito bem os tipos de associações que estão disponíveis no AR.
Association Proxy, #wtf !
As associações:
- belongs_to
- has_one
- has_many
- has_and_belongs_to_many
Quando usadas, adicionam alguns métodos (veja Detailed Association Reference). Por exemplo, ao declarar uma associação belongs_to, o model “ganhará” os seguintes métodos:
- association(force_reload = false)
- association=(associate)
- build_association(attributes = {})
- create_association(attributes = {})
Onde association, será substituído pelo nome da associação. Exemplo retirado do guides:
class Order < ActiveRecord::Base belongs_to :customer end
Cada instância de Order, conterá os métodos:
- customer
- customer=
- build_customer
- create_customer
O association proxy, é o objeto que faz a ligação do objeto que contém a associação, conhecido como owner, e o objeto associado, conhecido como target.
Legal e daí !?!
Graças ao association proxy, ao declarar uma associação, podemos extendê-la e adicionar comportamentos “customizados”. No guia, é citado como Association Extensions. O código de exemplo abaixo, está no github em random-samples.
Para exemplificar, vamos criar um modulo que adiciona o comportamento de uma galeria a qualquer coleção.
module GalleryColletion def current=(curr = nil) @current, @index = nil if curr.nil? @current = collection.first @index = 0 else collection.each_with_index do |item, index| if item.id.to_i == curr.to_i @current = item @index = index end end end @current end def current @current end def position @index + 1 end def previous? return false if @index.nil? !!(@index - 1 >= 0) end def previous collection[@index - 1] if previous? end def next? return false if @index.nil? !!(@index + 1 < collection.size) end def next collection[@index + 1] if next? end private def collection proxy_owner.send(proxy_reflection.name) end end
Note que o modulo está na pasta lib, logo, a pasta tem que ser adicionada no path via config/environment.rb.
Para extender a associação, declare:
class Article < ActiveRecord::Base has_and_belongs_to_many :images, :extend => GalleryColletion end
Article model, Image model aqui.
Agora para navegar entre as imagens, você pode usar:
a = Article.first a.images.current = 1 #1 e o Image.id que deseja selecionar a.images.current a.images.position a.images.next? a.images.next a.images.previous? a.images.previous
Caso esteja com coragem, baixe o projeto e veja rodando.
Dúvidas, sugestões, algum “case” de sucesso, comente!










