# Associações
Para interligar tabelas atravez dos **"forein_keys"**, criamos associações enre os modelos.
Existem 3 tipos de associações: 1 para 1, 1 para varios e varios para varios.
## 1 para 1
Tipo de associação de um objeto para outro. Util para quebrar uma tabela grande em varias partes. Sempre defina os dois lados da associação!
#### Exemplo
- subject-page
- Page has_one :subject
- Subject has_one :page
No modelo **Subject**:
class Subject < ActiveRecord::Base
has_one :page
end
No modelo **Page**:
class Page < ActiveRecord::Base
has_one :subject, {:foreign_key => "subject_id"}
end
Para utilizar as associações, carregue um objeto e chame o metodo associado para ter o objeto retornado:
```subject.page``` ou ```page.subject```
## 1 para varios
As associações de um objeto para varios são muito usadas dentro dos aplicativos em rails. Elas utilizm o termo no plural e retornam um array de objetos.
A classe com o ```belongs_to``` que deve ter o **foreign key**
#### Exemplo
- user-photos
- User has_many :photos
- Photo belongs_to :user
No modelo **User**:
class User < ActiveRecord::Base
has_many :photos
end
No modelo **Photo**:
class Photo < ActiveRecord::Base
belongs_to :user
end
#### Metodos
- ```user.photos```
- ```user.photos << photo```
- ```user.photos = [photo, photo, photo]```
- ```user.photos.delete(photo)```
- ```user.photos.clear```
- ```user.photos.empty?```
- ```user.photos.size```
- ```user.photos[1]```
## varios para varios
Este tipo de associação é utilizada quando um objeto está associado a varios outros objetos, mas não exclusivamente.
Para este tipo de associação, primeiro é necessario criar uma **join table**, ou seja, uma tabela simples que não tem um **primary key** e tem apenas duas colunas com os **ids** dos dois objetos das duas tableas sendo relacionados.
#### Join Table
A nova tabela que vai guardar as inforamções da associação tem algumas regras de nomeação especificas:
- Primeira_tabela + _ + segunda_tabela
- Os dois nomes são no plural
- Os nomes entram em ordem alfabetica
- Nome *default* que pode ser configurado
#### Exemplo
- posts-tags
- Post has_and_belongs_to_many :tags
- Tags has_and_belongs_to_many :posts
O nome da tabela vai ser: "posts_tags".
1 - Criar o arquivo de migração:
```rails generate migration CreatePostsTagsJoin```
2 - Editar o arquivo de migração:
class CreatePostsTagsJoin < ActiveRecord::Migration
def self.up
create_table :posts_tags, :id => false do |t|
t.integer "post_id"
t.integer "tag_id"
end
add_index :posts_tags, ["post_id", "tag_id"]
end
def self.down
drop_table :posts_tags
end
end
3 - Rodar a migração:
```rake:db:migrate```
4 - No arquivo do modelo Post:
class Post < ActiveRecord::Base
has_and_belongs_to_many :tags
end
5 - No arquivo do modelo Tag:
class Tag < ActiveRecord::Base
has_and_belongs_to_many :blog_posts, :class_name => "Post"
end
## Associações Avançadas
Outra maneira de fazer associações de varios objeos para varios outros é criando um modelo proprio para administrar essas associaçãos e outras informações.
A diferença é que a tabela precisa de um **primary key** e não precisa seguir nenhuma conveção para o nome.
#### Exemplo
Neste exemplo vamos criar um log de edição das páginas do sistema.
- User has_many :page_edits
- PageEdit belongs_to :user
- Page has_many :page_edits
- PageEdit belongs_to :page
1 - Criar um modelo:
```rails generate model PageEdit```
2 - Editar o arquivo de migração:
class CreatePageEdits < ActiveRecord::Migration
def self.up
create_table :posts_tags do |t|
t.references :page
t.references :user
t.string "new_content"
t.timestamps
end
add_index :page_edits, ["page_id", "user_id"]
end
def self.down
drop_table :posts_tags
end
end
3 - Rodar a migração:
```rake:db:migrate```
4 - No arquivo do modelo Page:
class Page < ActiveRecord::Base
has_many :page_edits
end
5 - No arquivo do modelo User:
class User < ActiveRecord::Base
has_many :page_edits
end
6 - No arquivo do modelo PageEdit:
class User < ActiveRecord::Base
belongs_to :page
belongs_to :editor, :class_name => "User", :foreign_key => "user_id"
end
#### Traversing
-----------------
## Informações adicionais
* [A Rule of Thumb for Strong Parameters](http://patshaughnessy.net/2014/6/16/a-rule-of-thumb-for-strong-parameters)
-----------------
[Index](index.md)