2010-01-27 3 views
5

has_and_belongs_to_many 협회를 통해 :has_many : 나는 루비 온 레일스 프로젝트에서 다음을 수행하려고

class FoodItem < ActiveRecord::Base 
    has_and_belongs_to_many :food_categories 
    has_many :places, :through => :food_categories 
end 

class FoodCategory < ActiveRecord::Base 
    has_and_belongs_to_many :food_items 
    belongs_to :place 
end 

class Place < ActiveRecord::Base 
    has_many :food_categories 
    has_many :food_items, :through => :food_category 
end 

을하지만 인스턴스 메서드 some_food_item.places를 호출 나에게 다음과 같은 오류 제공 :

ActiveRecord::StatementInvalid: PGError: ERROR: column 
food_categories.food_item_id does not exist 
LINE 1: ...laces".id = "food_categories".place_id WHERE (("food_cate... 

: SELECT "places".* FROM "places" INNER JOIN "food_categories" ON "places".id = "food_categories".place_id WHERE (("food_categories".food_item_id = 1)) 

을 어느 완벽한 의미가 있습니다 - FoodItem 및 FoodCategory의 HABTM 때문에 매핑 테이블이 food_categories_food_items입니다.

테이블에서 food_item_id을 찾는 대신 some_food_item.places이 매핑 테이블을 통해 올바르게 표시되도록하려면 어떻게해야합니까?

답변

6

내 첫 번째 버전의 대답이 잘못되었지만 완벽하게 작동합니다. 처음 몇 가지 오타를 만들었지 만 (실제로 테스트 할 앱을 만들지 않는 위험) 이번에는 확인했습니다. 그리고 플러그인이 필요하지만 이것은 쉽습니다. 먼저 플러그인을 설치하십시오.

script/plugin install git://github.com/ianwhite/nested_has_many_through.git 

이 방법은 Ian White의 대안을 설치하고 원활하게 작동합니다. 이제 모델은 테스트 응용 프로그램에서 직접 복사하여이 작업을 수행합니다.

class FoodItem < ActiveRecord::Base 
    has_many :food_category_items 
    has_many :food_categories, :through => :food_category_items 
    has_many :places, :through => :food_categories 
end 

class FoodCategory < ActiveRecord::Base 
    has_many :food_category_items 
    has_many :food_items, :through => :food_category_items 
    belongs_to :place 
end 

class FoodCategoryItem < ActiveRecord::Base 
    belongs_to :food_item 
    belongs_to :food_category 
end 

class Place < ActiveRecord::Base 
    has_many :food_categories 
    has_many :food_category_items, :through => :food_categories 
    has_many :food_items, :through => :food_category_items 
end 

"멀리있는"연결이 올바르게 작동합니다. place_instance.food_itemsfood_item.places은 모두 관련없는 간단한 연관뿐만 아니라 완벽하게 작동합니다. 참고로 모든 외래 키의 위치를 ​​보여주는 스키마는 다음과 같습니다.

create_table "food_categories", :force => true do |t| 
    t.string "name" 
    t.integer "place_id" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
end 

create_table "food_category_items", :force => true do |t| 
    t.string "name" 
    t.integer "food_item_id" 
    t.integer "food_category_id" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
end 

create_table "food_items", :force => true do |t| 
    t.string "name" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
end 

create_table "places", :force => true do |t| 
    t.string "name" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
end 

희망이 있습니다.

업데이트 :이 질문은 최근에 몇 차례 나 나왔습니다. 나는 상세하게 설명 할 기사 인 nesting your has_many :through relationships을 썼다. GitHub에 첨부 된 예제 응용 프로그램도 다운로드하여 사용할 수 있습니다.

+0

확실히 도움이됩니다! 솔루션과 HABTM의 헤드 업 모두에게 감사드립니다. 이 솔루션을 적용 할 수있는 유일한 곳이 아닐 것이라고 확신합니다! –

2

몇 달 전 나는 an article about this이라고 썼습니다. 간단히 말해, has_many에서 has_and_belongs_to_many까지의 연관은 Rails에서 허용되지 않습니다. 그러나 부분적으로이 같은 일을 수행하여 관계를 시뮬레이션 할 수 있습니다 :

class FoodItem < ActiveRecord::Base 
    has_and_belongs_to_many :food_categories 
    named_scope :in_place, lambda{ |place| 
    { 
     :joins  => :food_categories, 
     :conditions => {:food_categories => {:id => place.food_category_ids}}, 
     :select  => "DISTINCT `food_items`.*" # kill duplicates 
    } 
    } 
end 

class FoodCategory < ActiveRecord::Base 
    has_and_belongs_to_many :food_items 
    belongs_to :place 
end 

class Place 
    has_many :food_categories 
    def food_items 
    FoodItem.in_place(self) 
    end 
end 

이 당신에게 당신이 찾는 some_food_item.places 방법을 제공 할 것입니다.

-1

조인 테이블에서 "has many through"를 수행 할 수 없으므로이 내용이 정확합니다. 본질적으로, 당신은 실제로 할 수있는 것보다 한 차원 더 관계를 확장하려고합니다. HABTM (has_and_belongs_to_many)은 대부분의 문제에 대한 강력한 솔루션이 아닙니다.

귀하의 경우 FoodCategoryItem이라는 모델을 추가하고 조인 테이블의 이름을 일치하도록 바꾸는 것이 좋습니다. 또한 기본 키 필드를 다시 추가해야합니다. 이 같은 다음 설정 모델 협회 :

class FoodItem < ActiveRecord::Base 
    has_many :food_categories, :through => :food_category_items 
    has_many :places, :through => :food_categories 
end 

class FoodCategory < ActiveRecord::Base 
    has_many :food_items, :through => :food_category_items 
    belongs_to :place 
end 

class FoodCategoryItems < ActiveRecord::Base 
    belongs_to :food_item 
    belongs_to :food_category 
end 

class Place < ActiveRecord::Base 
    has_many :food_categories 
    has_many :food_items, :through => :food_categories 
end 

주, 나 또한 "- : food_items> has_many 장소"에 오타가 수정되었습니다. 이렇게하면 필요한 것을 처리하고 앞으로 FoodCategoryItem "조인"모델에 기능을 추가 할 수 있다는 보너스를줍니다.

+0

나는 이것을 사용할 수 없다. some_food_item.places를 호출 할 때 같은 오류가 발생한다. ActiveRecord의 제한 사항입니다 (http://www.ruby-forum.com/topic/115029 참조). –

+0

네 말이 맞아. 미안. 나는 모든 것을 고치는 대답을 추가했다. –

1

레일 3.2를 사용 중입니다.13 및 Rasmus, 원래 설치 프로그램은 HABTM에서 정상적으로 작동하는 것 같습니다.

사용자가 대안을 시도하기 전에 먼저 시도해 보시기 바랍니다.

관련 문제