하나의 상품은 복수의 카테고리에 속하고 하나의 카테고리는 복수의 상품이 존재하므로 상품과 카테고리의 관계는 N:N이라고 할 수 있습니다.
rails N:N을 구현하는 방법을 알아봅시다.
레일즈에서 N:N방식을 구현하는 방법은 ActiveRecord의has_many
나 has_and_belongs_to_many
를 사용하는 방법이 있습니다.
has_many와 has_and_belongs_to_many의 차이
Option name | Description |
---|---|
has_many | 중간테이블을 표현하는 클래스를 작성해야함, 확장성이 용이 |
has_and_belongs_to_many | 중간테이블을 표현하는 클래스를 작성하지 않아도됨, 확장성이 떨어짐 |
has_many를 쓰든 has_and_belongs_to_many를 쓰든 레일즈에서 N:N구현을 위해서 중간테이블 작성은 필수 입니다. 둘의차이는 중간테이블을 표현하는 클래스를 만드냐 안만드냐의 차이입니다.
특별한 이유가 없는한 확장성이 용이하는 has_many를 선택하는게 좋을듯 합니다.
프로젝트 작성
has_many용 프로젝트 작성
has_and_belongs_to_many용 프로젝트 작성
모델&테이블 작성
Category모델과Categories테이블을 작성해줍니다.
Product모델과Products테이블을 작성해줍니다.
has_many인경우,CategoryProduct모델과 categories_products테이블을 작성해줍니다.
has_and_belongs_to_many를 사용시에는 categories_products테이블만 작성해줍니다.
모델에has_many와belongs_to을 추가
has_many의 경우
has_and_belongs_to_many인 경우
사용가능해지는 커맨드(has_many/has_and_belongs_to_many 공통)
오브젝트 작성/db저장 관련
실행결과
(0.1ms) begin transaction
SQL (0.6ms) INSERT INTO "products" ("name", "price", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["name", "상품2"], ["price", 200], ["created_at", "2018-03-22 09:27:54.376770"], ["updated_at", "2018-03-22 09:27:54.376770"]]
SQL (0.3ms) INSERT INTO "category_products" ("category_id", "product_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["category_id", 1], ["product_id", 2], ["created_at", "2018-03-22 09:27:54.393183"], ["updated_at", "2018-03-22 09:27:54.393183"]]
(138.1ms) commit transaction
=> #<Product id: 2, name: "상품2", price: 200, created_at: "2018-03-22 09:27:54", updated_at: "2018-03-22 09:27:54">
릴레이션 관련
실행결과
(0.3ms) begin transaction
SQL (1.1ms) INSERT INTO "category_products" ("category_id", "product_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["category_id", 1], ["product_id", 3], ["created_at", "2018-03-22 09:36:57.731918"], ["updated_at", "2018-03-22 09:36:57.731918"]]
(117.9ms) commit transaction
Product Load (0.4ms) SELECT "products".* FROM "products" INNER JOIN "category_products" ON "products"."id" = "category_products"."product_id" WHERE "category_products"."category_id" = ? LIMIT ? [["category_id", 1], ["LIMIT", 11]]
=> #<ActiveRecord::Associations::CollectionProxy [#<Product id: 2, name: "상품2", price: 200, created_at: "2018-03-22 09:27:54", updated_at: "2018-03-22 09:27:54">, #<Product id: 3, name: "상품3", price: 1000, created_at: "2018-03-22 09:32:22", updated_at: "2018-03-22 09:32:22">]>
has_many의 경우 사용가능한 커맨드
※has_and_belongs_to_many는 모델이 없으므로 사용불가
중간테이블
메모
habtm
has_and_belongs_to_many
는 길어서 habtm
이라고 줄여서 사용함