Ir para conteúdo

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

felipebmfaria

Como fazer um join

Recommended Posts

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>

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

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:

 

  • nome_da_tabela_id (na chave estrangeira, ao invés de id_nome_da_tabela)
  • id (na chave primaria, ao invés de id_nome_da_tabela)

Você tem duas opções, seguir a convenção, ou configurar assim:

 

belongs_to :turma, foreign_key: "id_turma"

Compartilhar este post


Link para o post
Compartilhar em outros sites

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

Compartilhar este post


Link para o post
Compartilhar em outros sites

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:

https://coderwall.com/p/u_bzaq

Compartilhar este post


Link para o post
Compartilhar em outros sites

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.

Compartilhar este post


Link para o post
Compartilhar em outros sites

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.

Compartilhar este post


Link para o post
Compartilhar em outros sites

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.

Compartilhar este post


Link para o post
Compartilhar em outros sites

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:

  1. Abra o prompt de comando.
  2. Vá até a pasta do projeto.
  3. 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)
  4. Digite: rake db:migrate (com este comando você vai migrar o que foi escrito no passo 3 para o banco de dados.)

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>
…

Não testei o código, porém creio que ira funcionar certinho. Foquei no que considero que irá ajudar você a usufruir melhor do RoR, não na solução em si. Desde que comecei usar o RoR nunca precisei fazer join, ele já te oferece metodos para evitar ter esse contato com o SQL. Pesquise tudo que eu não pude me aprofundar ou que você não conseguiu compreender direito... Há inúmeros artigos pela internet. Qualquer coisa prega o berro aqui no fórum! Abraço!

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.