domingo, 22 de novembro de 2009

Tela de Cadastro com Many-to-Many - correção

Pessoal,

O Maurício Linhares (http://codeshooter.wordpress.com) deu uma dica para melhorar o código do post anterior, na partial _form.rhtml onde temos o nome do campo checkbox, devemos trocar disciplina_ids[] por aluno[disciplina_ids][] e no controller alunos_controller.rb não é necessário colocar o código @aluno.disciplinas = Disciplina.find(params[:disciplina_ids]) if params[:disciplina_ids] nos métodos create e update.

Valeu Maurício pela dica!

sexta-feira, 20 de novembro de 2009

Tela de Cadastro com Many-to-Many

* Esse post foi baseado no tutorial de Jeffrey Hicks e no Railscast número 47.

A idéia deste post é mostrar na prática como fazer um tela de cadastro havendo uma relação many-to-many. Para criar esse tutorial estou usando o Netbeans 6.7.1 e o banco de dados MySQL.

Primeiro passo é criar um projeto Rails chamado escola.

Esse exemplo mostra uma parte do que seria um sistema acadêmico, onde eu tenho uma tabela de alunos, disciplinas e uma relação alunos por disciplina. Para trabalhar com o padrão do Rails seguiremos a convenção de nome para as tabelas e os campos.



  • Repare que o nomes das tabelas estão no plural.
  • Os campos chaves são chamados de id.
  • A tabela de relacionamento é na ordem alfabética.
  • O campo de relacionamento é o nome da entidade no singular seguido de _id.
O segundo passo é gerar os scaffolds para aluno e disciplina, abaixo mostro a tela de gerar o scaffold do Netbeans 6.7.1 para o model aluno, a mesma operação deve ser feita para disciplina (lembre-se que o nome do model deve ser no singular).


Altere os models aluno.rb e disciplina adicionando o método has_and_belongs_to_many conforme imagem abaixo.

Essa alteração diz que disciplina tem e pertence a muitos alunos e aluno tem e pertence a muitas disciplinas. O método has_and_belongs_to_many é que faz o relacionamento n:n.

Como precisaremos de uma tabela de relacionamento, vamos criar uma migração de nome create_alunos_disciplinas para essa tabela.


Edite o código dessa nova migration conforme imagem abaixo:


Essa tabela não terá a chave primário id. Rode as migrations.

Para permitir que o usuário informe um aluno com várias disciplinas, vamos utilizar checkbox múltiplos. O nosso formulário será gerado dinamicamente a partir das disciplinas cadastradas no banco de dados. Nossa view vai depender do controller alunos_controller para carregar as disciplinas, altere o método new e edit do controller alunos_controller.rb conforme imagem abaixo.



Agora iremos customizar as views edit e new de alunos. Vamos fazer isso em um único local, ou seja, na partial _form.rhtml - para isso crie dentro de views/alunos o arquivo _form.rhtml e coloque o código abaixo.


Nessa partial colocamos um for para carregar os checkbox com os valores e nomes das disciplinas disponibilizadas pelo objeto @disciplinas que foi passado nos métodos new e edit do controller. Repare que o botão f.submit tá com nome button, esse nome é passado como parâmetro na chamada da partial nas views new e edit e o :disable_with serve para desabilitar o botão com a mensagem "Aguarde..." enquanto a requisição estiver ocorrendo. Abaixo o código das views alteradas, veja que na chamada da partial, passamos o parâmetro :button com o texto que vai aparecer nos botões.


Vamos alterar agora a view index de alunos para poder mostrar as disciplinas que o mesmo está associado.



Os métodos update e create de alunos_controller.rb recebem requisições das views edit e new. Para armazenar o relacionamento precisamos converter disciplinas_ids para objetos Disciplina com Disciplina.find(@params[:disciplina_ids]) if @params[:disciplina_ids]. O if previne erros de objetos nulos quando o aluno não estiver associado a alguma disciplina.



Agora é só testar!!!! Veja algumas telas abaixo.


quinta-feira, 12 de novembro de 2009

Formulário Simples de Pesquisa

A idéia desse post é permitir filtrar o grid de Locadoras que está na página index.

Sabemos que a página inicial é a página index.html.erb do controller Locadoras, abra o arquivo e adicione o trecho de código destacado.


O helper form_tag inicia uma tag form que aponta a ação para uma url configurada com locadoras_path e método get. De acordo com métodos padrões REST, locadoras_path será substituida por /locadoras, ou seja, com o verbo get e o path /locadoras, a ação a ser executada será a index - trocando em miúdos, carregará a própria página.

O helper text_field_tag cria um campo texto padrão, onde o primeiro parâmetro é o nome do campo e o segundo é o value - trocando em miúdos, um campo com nome :search e o valor será o próprio valor digitado quando o formulário for submetido.

O helper submit_tag cria um botão submit padrão, onde o primeiro parâmetro é o texto que aparecerá no botão, o segundo parâmetro é um hash, que nesse caso, estamos dizendo que o botão não tem campo nome, para que não seja passado pela url.

Como estamos chamando o método index, vamos alterá-lo no controller de locadoras.


Reparem que agora o método índex retorna @locadoras, que ao invés de ter ser resultado do método all (Locadoras.all), é resultado do método search, e de onde vem esse método search? Vem do model locadora, conforme abaixo:



Criamos o método search que recebe um parâmetro, verificamos se p existe, em caso afirmativo, chamamos o método find, onde o mesmo retornará todos os registros que atendam à condição passada, caso contrário, retorna todos os registros.

Este post foi baseado pelo vídeo abaixo:

http://media.railscasts.com/videos/037_simple_search_form.mov