해당 포스트는 활성 레코드관계(Active Record Association)에 대한 안내 - 루비온 레일즈 가이드 를 요약 & 정리한 글 입니다.
아래와 같이 아무런 관계 설정이 없는 고객 모델과 주문 모델이 있다고 가정하자.
class Customer < ActiveRecord::Base
end
class Order < ActiveRecord::Base
end
여기서 이미 존재하는 고객의 새로운 주문을 추가하려면, 고객의 id를 가져와 주문을 생성해야 한다.
@order = Order.create(:order_date => Time.now,
:customer_id => @customer.id)
만약 해당 고객과 고객의 모든 주문을 삭제하길 원한다면 아래와 같이 고객 id로 모든 주문을 찾아 삭제한 후, 고객 데이터까지 따로 삭제해줘야 한다. 매우 복잡하다.
@orders = Order.where(:customer_id => @customer.id)
@orders.each do |order|
order.destroy
end
@customer.destroy
관계 설정이 된 모델의 경우 1)의 사례보다 훨씬 쉽게 주문 생성 / 삭제가 가능하다.
우선 아래와 같이 관계 설정을 할 수 있다.
class Customer < ActiveRecord::Base
has_many :orders, :dependent => :destroy
end
class Order < ActiveRecord::Base
belongs_to :customer
end
주문을 생성하려면 아래와 같이 깔끔하게 코드를 작성할 수 있다.
@order = @customer.orders.create(:order_date => Time.now)
그리고 해당 고객의 모든 주문과, 고객 데이터를 삭제하려면 그냥 고객 하나만 지우면 된다.
:dependent => :destroy
관계 설정이 되어있기 때문에 고객을 지우면 해당 고객의 주문까지 동시에 삭제된다.
@customer.destroy
belongs_to
has_one
has_many
has_many :through
has_one :through
has_and_belongs_to_many
class Order < ActiveRecord::Base
belongs_to :customer
end
class Supplier < ActiveRecord::Base
has_one :account
end
class Customer < ActiveRecord::Base
has_many :orders
end
has_many :through
관계를 사용할 수 있다. 제 3의 모델인 '예약' 모델이 중간 다리의 역할을 한다.class Physician < ActiveRecord::Base
has_many :appointments
has_many :patients, :through => :appointments
end
class Appointment < ActiveRecord::Base
belongs_to :physician
belongs_to :patient
end
class Patient < ActiveRecord::Base
has_many :appointments
has_many :physicians, :through => :appointments
end
physician.patients = patients
새로 연결된 객체에 대해 새로운 연결 모델이 자동으로 생성된다. 이전에 존재했던 일부가 누락 된 경우 해당 연결행(row)은 자동으로 삭제된다.
참고: 연결 모델의 자동 삭제는 바로 이루어지며, destroy 콜백이 트리거되지 않는다.
class Supplier < ActiveRecord::Base
has_one :account
has_one :account_history, :through => :account
end
class Account < ActiveRecord::Base
belongs_to :supplier
has_one :account_history
end
class AccountHistory < ActiveRecord::Base
belongs_to :account
end
class Assembly < ActiveRecord::Base
has_and_belongs_to_many :parts
end
class Part < ActiveRecord::Base
has_and_belongs_to_many :assemblies
en
연결 모델을 만들때에 “독립된” 것으로 간주되어야 할 경우에는 직접적인 has_and_belongs_to_many
관계 보다는, has_many :through
를 사용하는 것이 더 좋다.
반대로, 관계 모델을 사용하여 작업을 수행 할 필요가 없는 경우 has_and_belongs_to_many
관계를 설정하는 것이 더 간단 할 수 있다.
연결 모델에서 유효성 검사, 콜백 또는 추가 속성이 필요한 경우 has_many :through
를 사용해야 한다.
class Picture < ActiveRecord::Base
belongs_to :imageable, :polymorphic => true
end
class Employee < ActiveRecord::Base
has_many :pictures, :as => :imageable
end
class Product < ActiveRecord::Base
has_many :pictures, :as => :imageable
end
@employee.pictures
을 통해 Employee에 종속된 pictures들을 검색 할 수 있다.Picture 모델의 instance가 있는 경우, @picture.imageable을 통해 부모에게 접근할 수 있다. 이 작업을 수행하려면 Model에서 polymorphic 인터페이스를 선언하는 외래키 컬럼과 type(유형) 컬럼을 모두 선언해야 한다.
class CreatePictures < ActiveRecord::Migration
def self.up
create_table :pictures do |t|
t.string :name
t.integer :imageable_id
t.string :imageable_type
t.timestamps
end
end
def self.down
drop_table :pictures
end
end
위 마이그레이션은 t.references 문법을 통해 더 간략하게 표현할 수 있다.
def self.up
create_table :pictures do |t|
t.string :name
t.references :imageable, :polymorphic => true
t.timestamps
end
end
class Employee < ActiveRecord::Base
has_many :subordinates, :class_name => "Employee",
:foreign_key => "manager_id"
belongs_to :manager, :class_name => "Employee"
end
@employee.subordinates
와 @employee.manager
를 검색할 수 있다.참고: