Ajax Scaffold: Extendendo o Plugin
Posted on December 01, 2006
De volta com mais um tutorial de Scott Rutheford sobre o plugin Ajax Scaffold. Desta vez ele nos mostra como extender ou substituir a funcionalidade padrão do plugin. Ele vai por duas áreas: em primeiro lugar como filtrar o conjunto de dados que tabela mostra e em segundo os métodos que vamos sobrescrever para realmente ganhar controle.
Filtro Simples do Conjunto de Dados
Para conseguir filtrar os dados que a tabela mostra, precisamos simplesmente sobrescrever um único método (para cada model) no seu controller:
Espera-se que esse método retorne o mesmo array que o método find() do Rails aceita como valor do parâmetro :conditions.
Vamos pegar um simples model user como exemplo. A tabela no banco de dados tem as seguintes colunas: id, name, password, employer_id, onde o employer_id representa um relacionamento has_one com o contratante do usuário (representado em outra tabela). Agora digamos que queremos ver usuários do contratante atual em nossa tabela, então tudo que precisamos fazer é definir o seguinte método em nosso controller:
[ ‘employer_id = ?’, params[:current_employer] ]
end
Claro que isso assume que a requisição atual define :currrent_employer como o ID do contratante.
Podemos usar qualquer declaração condicional que quisermos. Se funcionaria no método find() do Rails, funcionará aqui.
Filtros Mais Complexos
Num nível mais baixo, a coleção usada pela tabela é fornecida por uma combinação de três métodos:
- count_{nome_da_tabela}_collection(model, options)
- page_and_sort_{table_name}_collection(model, options, paginator)
- page_and_sort_{table_name}_collection_with_method(model, options, paginator)
Esses métodos representam uma versão um pouco extendida dos métodos encontrados no paginador do Rails. Os dois primeiros são chamados para qualquer página normal ou ordenação (ou seja, não usando o ScaffoldColumn definido com o parâmetro :sort) e o último é chamado somente por ScaffoldColumns definidos com, espere por isso, o parâmetro :sort.
Por exemplo, digamos que temos um conjunto de objetos Report que são mostrados usando as seguintes definições de colunas:
AjaxScaffold::ScaffoldColumn.new(Report, {
:name => “title”,
:eval => “row.current_definition.title”,
:sort => ‘current_definition.title’}),
AjaxScaffold::ScaffoldColumn.new(Report, {
:name => “viewed”,
:eval => “row.views”,
:sort => ‘views’ }),
]
Também definimos um método que retorna os relatórios para um projeto em particular ou para um projeto em uma categoria em particular (ambos seriam difíceis de fazer com apenas :conditions):
project = get_project
reports = project.reports
if request.post?
selected_category = params[:category]
reports = project.reports_for_category(selected_category) if selected_category
end
reports
end
Então poderíamos definir os três métodos acima da seguinte forma (em ReportsController.rb):
get_reports.size
end
def page_and_sort_reports_collection_with_method(model, options, paginator)
collection = get_reports
order_parts = options[:order].split(’ ’)
sort_collection_by_method(collection, order_parts0, order_parts1).slice(paginator.current.offset,options[:per_page])
end
def page_and_sorts_reports_collection(model, options, paginator)
page_and_sort_reports_collection_with_method(model, options, paginator)
end
Isso faria cada ordenação (sort) / página usar o método “with_method” uma vez que todas as colunas usam o mesmo parâmetro :sort. Nossa contagem viria de nosso método get_reports e tudo deveria funcionar como esperado.
Outros Pontos de Extensão
Aqui estão alguns outros métodos que podemos sobrescrever para mudar o comportamento do scaffold. Provavelmente é uma boa idéia olhar realmente no código-fonte do plugin para ver como cada um é usado. Embora alguns sejam auto-explicativos.
Em todos eles, {prefix} é definido como {nome_da_tabela}_. Ou seja, o nome da tablea com um sublinhado adicionado. {suffix} é definido como _{nome_do_model_em_caixa_baixa}. Esse é o nome da classe do model usando apenas letras em caixa baixa com um sublinhado adicionado antes. Isso é apenas necessário em cenários de múltiplas tabelas (eu escrevi dessa forma aqui para igualar com o código real). A razão para fazer isso é para dar métodos estilo CRUD quando estamos usando apenas uma única tabela.
Coluna Padrão de Ordenação
Por padrão as linhas são ordenadas usando a chave primária, ID. Para mudar isso podemos sobrescrever: default_sort / default_{prefix}sort
“users.name”
end
Direção Padrão de Ordenação
Para mudar isso de “asc” podemos sobrescrever: default_sort_direction / default_{prefix}sort_direction. O único outro valor de retorno possível é “desc”.
“desc”
end
Criação
Se quiser mudar o comportamento padrão quando o model é criado podemos sobrescrever o seguinte método que chamado é internamente:
@user = User.new(params[:user])
@successful = @user.save
end
Atualização/Update
Se quiser mudar o comportamento padrão quando o model é atualizado podemos sobrescrever o seguinte método que é chamado internamente:
@user = User.find(params[:id])
@successful = @user.update_attributes(params[:user])
end
Tabela
Para adicionar comportamento customizado para a renderização da tabela podemos usar esse método. Isso é realmente para adicionar funcionalidade. Ainda precisamos chamar os métodos como mostrados ou as coisas podem ir um pouco erradas:
self.#{prefix}table_setup
OTHER CODE GOES IN HERE
render#{suffix}_template(:action => ‘table’)
end
Adicionado em 3.2.2
Novo
Chamado antes do formulário para um novo model aparecer:
@user = User.new
@successful = true
end
Editar
Chamado para encontrar o objeto a editar:
user = User.find(params[:id])
@successful = !user.nil?end
Destruir
Chamado para encontrar o objeto a destruir:
@successful = User.find(params[:id]).destroy
end
blog comments powered by Disqus
Archives
- February 12(2)
- December 11(1)
- November 11(4)
- October 11(6)
- September 11(5)
- August 11(1)
- July 11(5)
- May 11(4)
- April 11(11)
- March 11(4)
- February 11(3)
- January 11(4)
- December 10(9)
- November 10(2)
- October 10(10)
- September 10(4)
- August 10(6)
- July 10(14)
- June 10(16)
- May 10(8)
- April 10(14)
- March 10(9)
- February 10(6)
- January 10(14)
- December 09(10)
- November 09(10)
- October 09(7)
- September 09(19)
- August 09(4)
- July 09(12)
- June 09(7)
- May 09(12)
- April 09(11)
- March 09(9)
- February 09(9)
- January 09(12)
- December 08(14)
- November 08(20)
- October 08(15)
- September 08(18)
- August 08(25)
- July 08(13)
- June 08(21)
- May 08(29)
- April 08(27)
- March 08(12)
- February 08(32)
- January 08(31)
- December 07(27)
- November 07(30)
- October 07(25)
- September 07(28)
- August 07(16)
- July 07(15)
- June 07(16)
- May 07(7)
- April 07(13)
- March 07(8)
- February 07(9)
- January 07(24)
- December 06(17)
- November 06(17)
- October 06(15)
- September 06(38)




