Saya mencoba memahami apa has_many :through
itu dan kapan menggunakannya (dan bagaimana). Namun, saya tidak mengerti. Saya membaca Beginning Rails 3 dan saya mencoba Googling, tetapi saya tidak dapat memahami.
Saya mencoba memahami apa has_many :through
itu dan kapan menggunakannya (dan bagaimana). Namun, saya tidak mengerti. Saya membaca Beginning Rails 3 dan saya mencoba Googling, tetapi saya tidak dapat memahami.
Jawaban:
Katakanlah Anda memiliki dua model: User
dan Group
.
Jika Anda ingin pengguna menjadi bagian dari grup, maka Anda dapat melakukan sesuatu seperti ini:
class Group < ActiveRecord::Base
has_many :users
end
class User < ActiveRecord::Base
belongs_to :group
end
Bagaimana jika Anda ingin melacak metadata tambahan di sekitar pengaitan? Misalnya, ketika pengguna bergabung dengan grup, atau mungkin apa peran pengguna dalam grup?
Di sinilah Anda menjadikan pengaitan sebagai objek kelas pertama:
class GroupMembership < ActiveRecord::Base
belongs_to :user
belongs_to :group
# has attributes for date_joined and role
end
Ini memperkenalkan tabel baru, dan menghilangkan group_id
kolom dari tabel pengguna.
Masalah dengan kode ini adalah Anda harus memperbarui setiap tempat lain Anda menggunakan kelas pengguna dan mengubahnya:
user.groups.first.name
# becomes
user.group_memberships.first.group.name
Jenis kode ini menyebalkan, dan membuat perubahan seperti ini menyakitkan.
has_many :through
memberi Anda yang terbaik dari kedua dunia:
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
Sekarang Anda dapat memperlakukannya seperti biasa has_many
, tetapi dapatkan manfaat dari model pengaitan saat Anda membutuhkannya.
Perhatikan bahwa Anda juga dapat melakukan ini dengan has_one
.
Edit: Memudahkan untuk menambahkan pengguna ke grup
def add_group(group, role = "member")
self.group_associations.build(:group => group, :role => role)
end
user.groups << group
? Ataukah semuanya ditangani oleh asosiasi ini?
Katakanlah Anda memiliki model ini:
Car
Engine
Piston
Sebuah mobil has_one :engine
Sebuah mesin belongs_to :car
Sebuah mesin has_many :pistons
Pistonbelongs_to :engine
has_many :pistons, through: :engine
Piston mobilhas_one :car, through: :engine
Pada dasarnya Anda mendelegasikan hubungan model ke model lain, jadi daripada harus menelepon car.engine.pistons
, Anda bisa melakukannyacar.pistons
has_many :through
dan has_and_belongs_to_many
hubungan berfungsi melalui tabel gabungan , yang merupakan tabel perantara yang mewakili hubungan antara tabel lain. Tidak seperti kueri JOIN, data sebenarnya disimpan dalam tabel.
Dengan has_and_belongs_to_many
, Anda tidak memerlukan kunci utama, dan Anda mengakses rekaman melalui relasi ActiveRecord daripada melalui model ActiveRecord. Anda biasanya menggunakan HABTM saat ingin menghubungkan dua model dengan hubungan banyak-ke-banyak.
Anda menggunakan has_many :through
hubungan saat Anda ingin berinteraksi dengan tabel gabungan sebagai model Rails, lengkap dengan kunci utama dan kemampuan untuk menambahkan kolom kustom ke data yang digabungkan. Yang terakhir ini sangat penting untuk data yang relevan dengan baris yang digabungkan, tetapi tidak benar-benar milik model terkait - misalnya, menyimpan nilai terhitung yang berasal dari bidang di baris yang digabungkan.
Dalam A Guide to Active Record Associations , rekomendasinya berbunyi:
Aturan praktis yang paling sederhana adalah Anda harus menyiapkan hubungan has_many: through jika Anda perlu menggunakan model hubungan sebagai entitas independen. Jika Anda tidak perlu melakukan apa pun dengan model hubungan, mungkin lebih mudah untuk menyiapkan hubungan has_and_belongs_to_many (meskipun Anda harus ingat untuk membuat tabel penggabungan dalam database).
Anda harus menggunakan has_many: through jika Anda memerlukan validasi, callback, atau atribut tambahan pada model gabungan.
user
model untuk menambahkan grup. Sesuatu seperti hasil edit yang baru saja saya buat. Semoga ini membantu.