0

와 has_many 관계는 5.1레일 오, 나는 레일에서 사용자 정의 이름을 가진 <code>has_many</code> 관계에 문제가 있어요 정의 이름 검사 오류

내가 사용자와 도메인 모델을 가지고, 카탈로그 및 즐겨 찾기에서 항목. 사용자는 많은 즐겨 찾기 항목을 가질 수 있습니다.

즐겨 찾기에 추가 항목이있을 수 있습니다.

나는 소재 기존 응용 프로그램 수정에 대한 학습 운동으로이 일을 해요, 그래서 전용 마이그레이션 각 관계를 추가했습니다 :

class AddUserToFavourite < ActiveRecord::Migration[5.1] 
    def change 
    add_reference :favourites, :user, foreign_key: true 
    end 
end 

class AddItemToFavourite < ActiveRecord::Migration[5.1] 
    def change 
    add_reference :favourites, :item, foreign_key: true 
    end 
end 

class AddAdditionalItemsToFavourite < ActiveRecord::Migration[5.1] 
    def change 
    add_reference :favourites, :additional_item, foreign_key: { to_table: :items } 
    end 
end 

결과 스키마는 다음과 같습니다

ActiveRecord::Schema.define(version: 20170921111049) do 

    # These are extensions that must be enabled in order to support this database 
    enable_extension "plpgsql" 

    create_table "favourites", force: :cascade do |t| 
    t.string "name" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
    t.bigint "user_id" 
    t.bigint "item_id" 
    t.bigint "additional_item_id" 
    t.index ["additional_item_id"], name: "index_favourites_on_additional_item_id" 
    t.index ["item_id"], name: "index_favourites_on_item_id" 
    t.index ["user_id"], name: "index_favourites_on_user_id" 
    end 

    create_table "items", force: :cascade do |t| 
    t.string "description" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
    end 

    create_table "users", force: :cascade do |t| 
    t.string "name" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
    end 

    add_foreign_key "favourites", "items" 
    add_foreign_key "favourites", "items", column: "additional_item_id" 
    add_foreign_key "favourites", "users" 
end 

이를 내 모델의 모습입니다.

# user.rb 
class User < ApplicationRecord 
    has_many :favourites 
end 

# item.rb 
class Item < ApplicationRecord 
    belongs_to :additional_item, class_name: 'Favourite', optional: true 
end 

# favourite.rb 
class Favourite < ApplicationRecord 
    belongs_to :user 
    belongs_to :item 

    has_many :additional_items, class_name: 'Item', foreign_key: 'additional_item_id' 
end 

이것은 내 모델입니다. 나는이 오류 테스트를 실행하면

# favourite_spec.rb 
require 'rails_helper' 

RSpec.describe Favourite, type: :model do 
    it { should belong_to :user } 
    it { should belong_to :item } 
    it { should have_many(:additional_items).with_foreign_key('additional_item_id') } 

    it 'can be created with no additional items' do 
    expect(Favourite.create!(name: 'Name', user: User.create!, item: Item.create!).additional_items).to be_empty 
    end 
end 

: 4,813,210은

ActiveRecord::StatementInvalid: 
     PG::UndefinedColumn: ERROR: column items.additional_item_id does not exist 
     LINE 1: SELECT 1 AS one FROM "items" WHERE "items"."additional_item... 
               ^
     : SELECT 1 AS one FROM "items" WHERE "items"."additional_item_id" = $1 LIMIT $2 

나는 오류가 무엇을 의미하는지 이해합니다. 테이블 items에는 additional_item_id 열이 없습니다. 당신은 스키마에서도 그것을 볼 수 있습니다.

내가 이해할 수없는 것은 왜 그곳에 있어야하는 이유입니까? 즐겨 찾기 테이블에 외래 키가 충분하지 않습니까?

모델에서 마이그레이션 또는 관계를 작성하는 방법에 문제가 있습니까?

저는 Rails와 DB 이론과 디자인이 매우 녹슬었기 때문에 제가 만든 어리석은 실수를 지적하십시오. 감사합니다 :)

답변

0

나는 그것을 알아 냈다.

즐겨 찾기 항목과 추가 항목 간의 관계를 모델링하는 방법에 문제가있었습니다. 나는 ... 내 DB 지식을 좋아하는이 additional_itemshas_many 모델을 정의 할 때와 같은 관계를 설명 할 수있는 올바른 방법임을 의미하는 것은 아니다라는 관계에서 많은 항목을 가질 수

사실을 조금을 갱신했다 .

특히 has_manyone-to-many relationship의 "one"면을 정의합니다.

내 추가 항목 관계는 many-to-many입니다. 네, 하나의 즐겨 찾기는 많은 추가 항목을 가질 수 있지만, 동시에 하나의 항목은 많은 즐겨 찾기의 추가 항목 세트의 일부가 될 수 있습니다.

레일즈는 다 대다 관계를 설명하는 방법으로 has_many :throughhas_and_belongs_to_many을 제공합니다.

내 경우에 has_and_belogns_to_manyRails guide on choosing between the two options에서 제안 된 것과 같이 가장 적절한 선택이었습니다.그때 무슨 짓을

했다 :

1.Favourite 모델 favourite에서 items에 대한 참조, 상대 스키마 업데이트 및 has_many 정의를 추가 마이그레이션을 커밋을 되돌립니다.

class CreateFavouritesAdditionalItemsJoinTable < ActiveRecord::Migration[5.1] 
    def change 
    create_join_table :favourites, :items, table_name: 'additional_items_favourites' 
    end 
end 

: bundle exec rake db:drop

3.은 many-to-many 연관을 표현하기 위해 테이블 ​​에 가입 추가 할 수있는 새로운 마이그레이션을 생성

2 데이터베이스를 드롭, 4.Favourite 모델의 사양 업데이트 :

5.

require 'rails_helper'require 'rails_helper' 

RSpec.describe Favourite, type: :model do 
    it { should belong_to :user } 
    it { should belong_to :item } 
    it { should have_and_belong_to_many(:additional_items) } 

    # These tests here are just for me to ensure I configured things properly. 
    # In a real app you wouldn't need to do this because there would be other 
    # tests that implicitly act on how the association is setup. 
    it 'can be created without additional items' do 
    expect(Favourite.create!(user: User.create!, item: Item.create!).additional_items).to be_empty 
    end 

    it 'can be updated adding additional items' do 
    f = Favourite.create!(user: User.create!, item: Item.create!) 
    item1 = Item.create!(description: 'foo') 
    item2 = Item.create!(description: 'bar') 
    f.additional_items << [item1, item2] 

    expect(f.additional_items.length).to eq 2 
    expect(f.additional_items).to include item1 
    expect(f.additional_items).to include item2 
    end 
end 
Faovurite에 실제 연결을 구현 : 방법 때문에 협회의 사용자 정의 이름의

class Favourite < ApplicationRecord 
    belongs_to :user 
    belongs_to :item 

    has_and_belongs_to_many :additional_items, 
    join_table: 'additional_items_favourites', 
    association_foreign_key: 'item_id', 
    class_name: 'Item' 
end 

공지 사항의 join_table의 이름과 관련된 모델의 class_name을 지정할 수있다, 그렇지 않으면 ActiveRecord가 :additional_items에서 그 테이블과 클래스를 찾지 못했을 것으로 추측합니다.

나는 그들이 클래스 이름에서 유추 할 수 있듯이, 어느 것도 foreign_key이나 association_foreign_key, favourite_iditem_id 각각 지정할 필요가 없습니다 것을 말할 기쁩니다.