Na maioria das vezes é útil utilizar componentes de listas conhecidos como Combobox ou Dropdown para mostrar relacionamentos de dados entre tabelas e de uma forma amigável exibir a descrição dos itens de dados e manipular seu identificador único. Para isto o Rails nos disponibiliza componentes e classes no qual nos permite manipular dados através de objetos e persisti-los em um banco de dados relacional usando o Active Record. Um relacionamento de dados mais simples é criado através de duas tabelas, sendo uma tabela pai que contem os dados mestres e uma filho que contem um ou mais identificadores relacionados ao pai. Um modo de fácil de identificar e tradicional de utilizar relacionamentos em um banco de dados é através de chaves estrangeiras, uma chave estrangeira é um campo, que aponta para a chave primária de outra tabela ou da mesma tabela. Ou seja, passa a existir uma relação entre duas tabelas ou de uma única tabela. A finalidade da chave estrangeira é garantir a integridade dos dados referenciais, pois apenas serão permitidos valores que supostamente vão aparecer na base de dados e estão ligados ao registro mestre.
Com associações do Active Record, podemos agilizar os processos de operações declarativas dizendo ao Rails que há uma conexão entre os dois modelos. Você pode usar belongs_to e has_many para criar um ligação simples entre dois modelos, a associação has_many indica uma ligação de um-para-muitos com outro modelo. Muitas vezes você vai encontrar essa associação no “outro lado” de uma associação belongs_to.
Associations: http://guides.rubyonrails.org/association_basics.html
No conceito de aplicações Rails você não precisa de restrições de chave estrangeira para que o Active Record possa mapear corretamente os relacionamentos. Você pode usar as validações para garantir a integridade dos dados. O Rails Migration não fornece provedor ajudante para criar chaves estrangeiras. Você pode criar seu próprio SQL para a restrição na migração ou usar o do Foreigner Gem. O Foreigner irá fornecer métodos auxiliares para a criação de restrições em uma migração.
Foreigner Gem: https://github.com/matthuhiggins/foreigner
Exibindo Relacionamentos
1 – Após criar um novo projeto Rails, o configure adequadamente para acessar o banco de dados MySQL, crie os modelos disponibilizados com código abaixo:
# Modelo Participante rails g model participante nome:string sobrenome:string cargo_id:integer data:datetime salario:float genero:string ativo:boolean observacao:string # Modelo Cargo rails g model cargo desc_cargo:string
2 – Migre os modelos para criar as tabelas físicas no banco de dados:
3 – Abra o Rails Command e utilize o modelo Cargo para criar novos registros no banco de dados:
# Grava objetos no banco de dados Cargo.create(desc_cargo: "Vocalista") Cargo.create(desc_cargo: "Guitarrista") Cargo.create(desc_cargo: "Baixista") Cargo.create(desc_cargo: "Baterista")
4 – O ajudante de referências não cria restrições de chave estrangeira para você. Você precisar cria-las e executa-las manualmente utilizando scripts SQL ou um plug-in que adiciona suporte a chave estrangeira. Você pode utilizar o código abaixo para criar uma restrição no banco de dados:
-- Cria Chave Estangeira ALTER TABLE participantes ADD FOREIGN KEY (cargo_id) REFERENCES cargos(id)
5 – Utilize os códigos abaixo e rode sua aplicação:
6 – Assim que os dados forem enviados o Active Record gravará o conteúdo dos objetos no banco de dados relacional, você pode verificar na pagina que mostramos a descrição do campo cargo toda vez que utilizamos os dados da tabela de Cargos, porem na tabela Participante apenas seu identificador é gravado formando o relacionamento entre as duas tabelas:
Exemplo:
Neste exemplo criamos duas tabelas no banco de dados MySQL e as relacionamos através da chave primaria e uma chave estrangeira. Usamos um elemento Rails para tornar este relacionamento amigável, exibindo assim a descrição do relacionamento mas manipulando seu identificador e os persistindo através do Active Record.
Ruby
Model
Participante
class Participante < ActiveRecord::Base #Cria relacionamento belongs_to :cargo # Cria validação validates :nome, :sobrenome, :data, :salario, :genero, :presence => true#{:message => "Campo obrigatório"} # Regex - valores alphanumericos validates :nome, :sobrenome, :format => {:with => /[A-Za-z]+/, :message => "Permitido somente caracteres letras."} end
Cargo
class Cargo < ActiveRecord::Base # Relacionamento has_many :participante end
View
<h1>Desenvolvimento Aberto</h1> <h2>Ruby on Rails - Elementos - Form </h2> <%= form_for @modelo, :url => {:action => :create} do |cad|%> <% if @modelo.errors.any? %> <h3>Erros: </h3> <ul style="color:red"> <% @modelo.errors.full_messages.each do |menssagem| %> <li> <%= menssagem %> </li> <% end %> </ul> <% end %> <fieldset> <legend> Cadastro: </legend> <table> <tr> <td> <%= cad.label :nome%> </td> <td> <%= cad.text_field :nome %> </td> </tr> <tr> <td><%= cad.label :sobrenome%></td> <td><%= cad.text_field :sobrenome, :size => "35x10"%></td> </tr> <tr> <td><%= cad.label :cargo%></td> <td><%= collection_select(:participante, :cargo_id, Cargo.all, :id, :desc_cargo)%> </td> </tr> <tr> <td><%= cad.label :data%></td> <td><%= cad.date_field :data, :size => "15x10"%></td> </tr> <tr> <td><%= cad.label :salario%></td> <td><%= cad.text_field :salario, :size => "10x10"%></td> </tr> <tr> <td><%= cad.label :genero%></td> <td><%= cad.collection_radio_buttons :genero, [["Masculino", "Masculino"] ,["Feminino", "Feminino"]] , :first, :last, { item_wrapper_tag: false } %></td> </tr> <tr> <td><%= cad.label :ativo%></td> <td><%= cad.check_box :ativo %></td> </tr> <tr> <td><%= cad.label :observacao%></td> <td><%= cad.text_area :observacao , :size => "40x10" %></td> </tr> </table> </fieldset> <p> <%= cad.submit "Adicionar dados" %> </p> <% end %>
Controller
class MeucontroleController < ApplicationController # Controladores def index @modelo = Participante.new end def new @modelo = Participante.new end # Cria registro def create @modelo = Participante.new(modelo_params) if @modelo.save flash[:notice] = "Dados Salvos com sucesso." render "index" else # Você pode colocar uma menssagem aqui. render "index" end end # Define parametros requeridos private def modelo_params params.require(:participante).permit(:nome, :sobrenome, :cargo_id, :data, :salario, :genero, :ativo, :observacao) end end