Estou tentando entender o que has_many :through
é e quando usá-lo (e como). No entanto, eu não estou entendendo. Estou lendo Beginning Rails 3 e tentei pesquisar no Google, mas não consigo entender.
fonte
Estou tentando entender o que has_many :through
é e quando usá-lo (e como). No entanto, eu não estou entendendo. Estou lendo Beginning Rails 3 e tentei pesquisar no Google, mas não consigo entender.
Digamos que você tenha dois modelos: User
e Group
.
Se você quiser que os usuários pertençam a grupos, faça algo assim:
class Group < ActiveRecord::Base
has_many :users
end
class User < ActiveRecord::Base
belongs_to :group
end
E se você quiser rastrear metadados adicionais em torno da associação? Por exemplo, quando o usuário ingressou no grupo, ou talvez qual a função do usuário no grupo?
É aqui que você faz da associação um objeto de primeira classe:
class GroupMembership < ActiveRecord::Base
belongs_to :user
belongs_to :group
# has attributes for date_joined and role
end
Isso introduz uma nova tabela e elimina a group_id
coluna da tabela do usuário.
O problema com esse código é que você precisaria atualizar em todos os lugares em que usar a classe de usuário e alterá-la:
user.groups.first.name
# becomes
user.group_memberships.first.group.name
Esse tipo de código é péssimo e dificulta a introdução de alterações como essa.
has_many :through
oferece o melhor dos dois mundos:
class User < ActiveRecord::Base
has_many :groups, :through => :group_memberships # Edit :needs to be plural same as the has_many relationship
has_many :group_memberships
end
Agora você pode tratá-lo como um normal has_many
, mas obtenha o benefício do modelo de associação quando precisar.
Observe que você também pode fazer isso com has_one
.
Editar: facilitando adicionar um usuário a um grupo
def add_group(group, role = "member")
self.group_associations.build(:group => group, :role => role)
end
user
modelo para adicionar o grupo. Algo como a edição que acabei de fazer. Espero que isto ajude.user.groups << group
? Ou tudo é tratado por essa associação?Digamos que você tenha estes modelos:
Um carro
has_one :engine
Um motor
belongs_to :car
Um motor
has_many :pistons
Pistão
belongs_to :engine
Um carro de
has_many :pistons, through: :engine
pistão
has_one :car, through: :engine
Essencialmente, você está delegando um relacionamento de modelo para outro modelo; portanto, em vez de precisar chamar
car.engine.pistons
, bastacar.pistons
fonte
Tabelas de junção ActiveRecord
has_many :through
e oshas_and_belongs_to_many
relacionamentos funcionam por meio de uma tabela de junção , que é uma tabela intermediária que representa o relacionamento entre outras tabelas. Ao contrário de uma consulta JOIN, os dados são realmente armazenados em uma tabela.Diferenças práticas
Com
has_and_belongs_to_many
, você não precisa de uma chave primária e acessa os registros por meio das relações do ActiveRecord, e não por um modelo do ActiveRecord. Você costuma usar o HABTM quando deseja vincular dois modelos a um relacionamento muitos-para-muitos.Você usa um
has_many :through
relacionamento quando deseja interagir com a tabela de junção como um modelo Rails, completo com chaves primárias e a capacidade de adicionar colunas personalizadas aos dados ingressados. O último é particularmente importante para dados que são relevantes para as linhas unidas, mas realmente não pertencem aos modelos relacionados - por exemplo, armazenar um valor calculado derivado dos campos na linha unida.Veja também
Em Um guia para associações de registros ativos , a recomendação diz:
fonte