Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Bom dia,
Desenvolvo em PHP há algum tempo e estou começando a estudar ruby.
Depois de muito ler, ainda não consegui fazer um simples join da tabela turmas e alunos.
Minha aplicação é simples, vou passar a estrutura das tabelas.
Turma Aluno
id_turma(PK) id_aluno (PK)
serie_turma id_turma (FK)
nome_aluno
Preciso exibir o id do aluno, o nome do aluno e a serie da turma dele.
Como posso fazer um join para trazer a serie da turma e exibi-la na grid?
model aluno
class Aluno < ActiveRecord::Base
belongs_to :turma
validates :matricula_aluno, uniqueness: true
end
controller aluno
def show
end
partial da view
<div class="control-group">
<%= f.label :codigo_turma_aluno, :class => 'control-label' %>
<div class="controls">
<%= f.number_field :codigo_turma_aluno, :class => 'text_field' %>
</div>
</div>
index view
<%- model_class = Aluno -%>
<div class="page-header">
<h1><%=t '.title', :default => model_class.model_name.human.pluralize.titleize %></h1>
</div>
<%= link_to t('.new', :default => t("helpers.links.new")),
new_aluno_path,
:class => 'btn btn-primary' %>
<p> </p>
<table class="table table-striped">
<thead>
<tr>
<th><%= model_class.human_attribute_name(:matricula_aluno) %></th>
<th><%= model_class.human_attribute_name(:nome_aluno) %></th>
<th><%= model_class.human_attribute_name(:codigo_turma_aluno) %></th>
<th><%=t '.actions', :default => t("helpers.actions") %></th>
</tr>
</thead>
<tbody>
<% @alunos.each do |aluno| %>
<tr class='<%= aluno.matricula_aluno %>'>
<td><%= link_to aluno.matricula_aluno, aluno_path(aluno) %></td>
<td><%= aluno.nome_aluno %></td>
<td><%= aluno.codigo_turma_aluno %></td>
<td>
<%= link_to t('.edit', :default => t("helpers.links.edit")),
edit_aluno_path(aluno), :class => 'btn btn-mini' %>
<%= link_to t('.destroy', :default => t("helpers.links.destroy")),
aluno_path(aluno),
:method => :delete,
remote: true,
:data => { :confirm => t('.confirm', :default => t("helpers.links.confirm", :default => 'Are you sure?')) },
:class => 'btn btn-mini btn-danger' %>
</td>
</tr>
<% end %>
</tbody>
</table>Você chama a tabela "Usuarios.joins(:nome_da_relação)", essa relação é a mesma que você define no models
No model aluno eu deixei assim:
elongs_to :turma, foreign_key: "id_turma"
na view index.html eu deixei assim, mas está dando erro
<%- model_class = Aluno -%>
<%- model_class2 = Turma -%>
<div class="page-header">
<h1><%=t '.title', :default => model_class.model_name.human.pluralize.titleize %></h1>
</div>
<%= link_to t('.new', :default => t("helpers.links.new")),
new_aluno_path,
:class => 'btn btn-primary' %>
<p> </p>
<table class="table table-striped">
<thead>
<tr>
<th><%= model_class.human_attribute_name(:matricula_aluno) %></th>
<th><%= model_class.human_attribute_name(:nome_aluno) %></th>
<th><%= model_class.human_attribute_name(:idade_aluno) %></th>
<th><%= model_class.human_attribute_name(:data_matricula_aluno).to_s %></th>
<th><%= model_class2.joins(:id_turma) %></th>
<th><%=t '.actions', :default => t("helpers.actions") %></th>
</tr>
</thead>
<tbody>
<% @alunos.each do |aluno| %>
<tr class='<%= aluno.matricula_aluno %>'>
<td><%= link_to aluno.matricula_aluno, aluno_path(aluno) %></td>
<td><%= aluno.nome_aluno %></td>
<td><%= aluno.idade_aluno %></td>
<td><%= aluno.data_matricula_aluno %></td>
<td><%= turma.serie_turma %></td>
<td>
<%= link_to t('.edit', :default => t("helpers.links.edit")),
edit_aluno_path(aluno), :class => 'btn btn-mini' %>
<%= link_to t('.destroy', :default => t("helpers.links.destroy")),
aluno_path(aluno),
:method => :delete,
remote: true,
:data => { :confirm => t('.confirm', :default => t("helpers.links.confirm", :default => 'Are you sure?')) },
:class => 'btn btn-mini btn-danger' %>
</td>
</tr>
<% end %>
</tbody>
</table>
Defini um novo model, o model2 lá em cima.
E troquei as variaveis e a chamada do modulo na grid. Estou com o pensamento errado?
Grato
Turma.all(:joins => :aluno)
Esse código é a mesma coisa que essa query:
SELECT "turmas".* FROM "turmas"
INNER JOIN "alunos" ON "turmas".id = "alunos".turma_id
Eu não tenho certeza se é isso mesmo, e se é isso mesmo que você quer mas acho que é assim que funciona, testa e me avisa.
Então teoricamente você pode puxar as informações que quiser normalmente como:
Turma.all(:joins => :aluno).serie_turma
Ou:
Turma.joins(:aluno).where("aluno.name" => selected_aluno)
Aqui tem um tutorial bem legal:
Pedro Lima, isso eu coloco na view? Não preciso mais mexer no controller, né?
Sou iniciante, confesso que as vezes ainda fico um pouco perdido.
Grato
Você só pode fazer isso no seu controller e mostrar o resultado na view
Exemplo:
seu controller
@resultado = Turma.all(:joins => :aluno)
Criei a variável "@resultado" é global pois tem o "@", assim você pode chama-lá em sua view, ela puxou todas as informações da query e se transformou em um array(vetor), então você pode fazer o que quiser com ela.
Para ver o que a variável está trazendo, basta usar o "raise ....inspect"
@resultado = Turma.all(:joins => :aluno)
raise @resultado.inspect
Tenta fazer alguns testes e veja se vai trazer todas as informações que deseja. Também sou iniciante rs, estou tentando te ajudar mas também não manjo muito. Qualquer dúvida estou ativo aqui. Boa sorte fera.
Se você pretende mostrar isso no index, terá que criar um método "index" no seu controller e configurar a rota dele.
Supondo que na sua "Turma.rb" (Model) tenha um has_many :alunos...
No seu controller ficaria assim:
def index
@resultado = Aluno.includes(:turma).all #Ou seja, tem um join e estará atribuindo a variável global '@resultado' um array(ou vetor) de todos os alunos.
end
Agora no seu aluno#index
<table class="table table-striped">
<thead>
<tr>
<th>"Matrícula"</th>
<th>"Nome"</th>
<th>"Cod. Turma"</th>
</tr>
</thead>
<tbody>
@resultado.each do |aluno|
<tr>
<td><%= link_to aluno.alunos.matricula_aluno, aluno_path(aluno) %></td>
<td><%= link_to aluno.alunos.nome, aluno_path(aluno) %></td>
<td><%=link_to aluno.id_turma, aluno_path(aluno) %></td>
</tr>
<% end %>
</tbody>
</table>
end
Veja no teu index o que rolou.Pedro Lima,
pintou uma urgencia em PHP, vou ter de resolver. Amanhã volto a mexer no Rails, daí posto o resultado desta sugestão.
Valeu.
Tudo bem,
Eu fiz alguns testes nessa semana e descobri que fazendo um...
#seu controller
@resultado = Aluno.includes(:turma).all
Irá trazer as informações dos alunos mas não da turma. Porém ele faz um join e a relação está feita, você pode usar o where que vai filtrar a sua pesquisa tranquilo. Exemplo:
#seu controller
@resultado = Aluno.includes(:turma).where("id_turma = ?", 1)
Então desse modo ele vai te trazer somente os alunos que sejam da turma de id "1".
Ainda não descobri como fazer para imprimir as informações das 2 tabelas juntas, se eu descobrir te informo, mas esse é o jeito que eu tenho certeza que vai funcionar.
tenta dar um raise @resultado.inspect em seu controller em baixo dessa dica que eu passei para ver o output.
Olá felipebmfaria, lido com ruby e rails há 6 meses então creio que tenho dicas interessantes para passar para você. Sendo um framework, Ruby on Rails(RoR) facilitará o seu trabalho absurdamente desde que você deixe que ele te ajude. Infelizmente há poucos artigos e tutoriais sobre ruby on rails em português (se você tem costume de ler artigos em inglês vai ser tranquilo progredir nesta senda do RoR). Caso você precise de artigos em português, eu aconselho a acompanhar o blog do Fábio Akita, seus artigos são simplesmente fantásticos.
Introdução feita, vamos ao que interessa. No seu caso não será necessário nenhum tipo de join explicito.
Primeiramente, para criar um banco de dados rapidamente e com menor chance de erros eu ( e o Rails também) aconselho a usar o seguinte:
-
Abra o prompt de comando.
-
Digite: rails generate scaffold NomeQueEuQuero campo_com_chave_estrangeira:reference campo_string:string (Observe que NÃO é necessário definir a chave primaria, o rails trata de criar sozinho! Seu nome padrão é id. O campo_com_chave_estrangeira vai ficar como campo_com_chave_estrangeira _id, pois é uma referencia. Com este comando (scaffold) vai ser gerado Model, View e Controller; tudo automatico! Aconselho abrir a pasta db/migrate e ver os arquivos que foram gerados)
Em seguida, será necessário configurar as associações da sua model. Vamos lá:
class Aluno < ActiveRecord::Base
belongs_to :turma
end
Com o belongs_to será criado uma associação Um-para-Um com a outra model, no caso, a model Turma. Explicando de um modo prático para facilitar a memorização; a model que possuir belongs_to será a entidade que possuirá a chave estrangeira (por convenção no RoR o nome do campo que possui a chave estrangeira é nomedocampo_id, no caso, turma_id). Quando é informado para a model o belongs_to, todas suas instâncias terão uma instância da model que o belongs_to está recebendo como parametro. Por exemplo:
@aluno = Aluno.new #criando um objeto da classe aluno
@aluno.turma.id #pegará o ID da turma que o aluno pertence
Como Ruby é totalmente orientado a objetos, para dominá-lo é necessário conhecer programação orientada a objetos, aconselho a estudar em paralelo e lembre-se: Sempre estude conceitos. Tecnologias têm como fundação conceitos.
No model Turma é necessário informar o tipo de associação também, no caso será uma associação de Vários-para-Um. Será inserido:
class Turma < ActiveRecord::Base
has_many :alunos
end
Nota-se que é pluralizado o parâmetro do has_many, isso por que o RoR tem como principio a “Convenção acima de configuração”. Pronto, as associações já estão configuradas.
Para mostrar os dados em uma view é necessário lembrar que o RoR usa a arquitetura MVC, ou seja, cada view terá um controller.
Indo ao cerne da questão:
>
Preciso exibir o id do aluno, o nome do aluno e a serie da turma dele.
Como posso fazer um join para trazer a serie da turma e exibi-la na grid?
Primeiro configure o Controller. Os dados pelo que entendi serão mostrados no index, então o código ficará o seguinte:
def index
@alunos = Aluno.all
end
Todos os alunos puxados para o atributo @alunos, o qual é um array, então é só codificar a view index:
...
<tbody>
<% @alunos.each do |aluno| %>
<tr class='<%= aluno.matricula_aluno %>'>
<td><%= link_to aluno.matricula_aluno, aluno_path(aluno) %></td>
<td><%= aluno.nome_aluno %></td>
<td><%= aluno.turma.serie_turma %></td>
<td>
<%= link_to t('.edit', :default => t("helpers.links.edit")),
edit_aluno_path(aluno), :class => 'btn btn-mini' %>
<%= link_to t('.destroy', :default => t("helpers.links.destroy")),
aluno_path(aluno),
:method => :delete,
remote: true,
:data => { :confirm => t('.confirm', :default => t("helpers.links.confirm", :default => 'Are you sure?')) },
:class => 'btn btn-mini btn-danger' %>
</td>
</tr>
<% end %>
</tbody>
O Rails segue o padrão "Convenção acima de configuração"
http://guides.rubyonrails.org/association_basics.html
Para você não precisar configurar a chave estrangeira, você poderia usar a seguinte convenção:
Você tem duas opções, seguir a convenção, ou configurar assim:
belongs_to :turma, foreign_key: "id_turma"