2010-10-22 72 views
11

Tôi có hai bảng với mối quan hệ nhiều đến nhiều mà tôi đang sử dụng has_and_belongs_to_many để xác định liên kết.Tạo bảng nối không có khóa chính

class Foo < ActiveRecord::Base 
    ... 
    has_and_belongs_to_many :bar 
    ... 
end 

class Bar < ActiveRecord::Base 
    ... 
    has_and_belongs_to_many :foo 
    ... 
end 

Tôi cũng đã lớp được xác định để đại diện cho tham gia bảng

class BarFoo < ActiveRecord::Base 
    ... 
    belongs_to :foo 
    belongs_to :bar 
    ... 
end 

Khi tôi chạy rake db: hạt giống tôi nhận được lỗi sau:

Primary key is not allowed in a has_and_belongs_to_many join table (bar_foo) 

Nếu tôi chỉnh sửa cơ sở dữ liệu và loại bỏ trường khóa chính (ID) khỏi bảng bar_foo và sau đó chạy lại db rake: tất cả mọi thứ hạt giống hoạt động như mong muốn.

Được nêu ở trên, phương thức ưa thích của việc tạo bảng nối trong đường ray không có khóa chính là gì?

Tôi cũng đã thử sử dụng "has_many: bars,: through =>: foo" và vise versa nhưng có thông báo lỗi giống như "undefined method 'klass' cho nil: NilClass".

Trả lời

4

Nếu bạn muốn sử dụng liên kết HABTM, bạn không nên tạo mô hình cho nó - chỉ cần một bảng bars_foos với các cột số bar_idfoo_id số nguyên.

Nếu bạn cần mô hình ở giữa (ví dụ: nếu bạn muốn theo dõi created_at hoặc một số thuộc tính khác của mối quan hệ), bạn có thể thêm mô hình bổ sung, ví dụ: Barred và sau đó bạn sẽ có:

class Foo < ActiveRecord::Base 
    ... 
    has_many :bars, :through => :barred 
    ... 
end 

class Bar < ActiveRecord::Base 
    ... 
    has_many :foos, :through => :barred 
    ... 
end 

class Barred < ActiveRecord::Base 
    has_many :bars 
    has_many :foos 
end 
+0

Matt, cảm ơn phản hồi. Tôi là tương đối mới để RoR vì vậy phương tiện ưa thích của việc tạo ra một bảng không có tập tin mô hình tương ứng là gì? Điều này chỉ được thực hiện bằng cách tạo tệp di chuyển và sử dụng create_table để xác định bảng có hai thuộc tính bar_id và foo_id? – Keith

+0

Đây là câu trả lời hay về cách thực hiện: [Tôi có cần tạo thủ công việc di chuyển cho bảng tham gia HABTM không?] (Http://stackoverflow.com/questions/564306/do-i-need-to-manually-create -a-migration-cho-a-habtm-join-table) – Matt

22

Có, khóa chính không được phép cho has_and_belongs_to_many.

Bạn có 2 cách để giải quyết vấn đề này:

Xóa khóa chính trên bảng đó. Trong lớp chuyển đổi của bạn:

create_table :bar_foo, :id => false do |t| 
    t.integer :bar_id 
    t.integer :foo_id 
end 

Ngoài ra, bạn sẽ phải xóa các tập tin bar_foo.rb từ app/models và cũng loại bỏ bất kỳ tập tin cố định và thử nghiệm mà có thể đã được tạo ra. Một ý tưởng hay là gọi số script/destroy (hoặc rails destroy) để hủy các tệp và sau đó tạo lại quá trình di chuyển.

Hoặc chuyển sang has_many :through

class Foo < ActiveRecord::Base 
    ... 
    has_many :bar_foos 
    has_many :bars, :through => :bar_foos 
    ... 
end 

class Bar < ActiveRecord::Base 
    ... 
    has_many :bar_foos 
    has_many :foos, :through => :bar_foos 
    ... 
end 

class BarFoo < ActiveRecord::Base 
    ... 
    belongs_to :foo 
    belongs_to :bar 
    ... 
end 
3

Bạn không cần phải mô hình

class BarFoo < ActiveRecord::Base 
    ... 
    belongs_to :foo 
    belongs_to :bar 
    ... 
end 

hiệp hội has_and_belongs_to_many sẽ tìm kiếm một bảng gọi là bar_foo trong cơ sở dữ liệu của bạn những gì bạn cần làm là tạo ra một di chuyển để tạo bảng này.

ray tạo add_table_bar_foo_for_association di cư

sau đó bạn chỉnh sửa chuyển đổi của bạn và nó sẽ giống như thế này

class AddTableBarFooForAssociation < ActiveRecord::Migration 
    def up 
    create_table :bar_foo, :id => false do |t| 
     t.references :bar 
     t.references :foo 
    end 
    end 

    def down 
    drop_table :bar_foo 
    end 
end 

Bây giờ hiệp hội của bạn nên làm việc và cũng có thể nếu bạn cần hiệp hội để có các thuộc tính thêm vào tham gia bạn có thể sử dụng cách has_many :through và tạo mô hình liên quan đến điều này.

Các vấn đề liên quan