2016-03-08 18 views
5

Tôi đã nhìn thấy một số câu trả lời cho câu hỏi mà giải quyết như thế nào để sử dụng khối phạm vi trong các hiệp hội ActiveRecord đó bao gồm đi qua các đối tượng chính nó vào khối như ...ActiveRecord has_many thông qua một hiệp hội có phạm vi với arg

class Patron < ActiveRecord::Base 
    has_many :bars, 
      ->(patron) { baz: patron.blah }, 
      foreign_key: :somekey, 
      primary_key: :somekey 
end 

class Bar < ActiveRecord::Base 
    belongs_to :patron, 
      ->(bar) { blah: bar.baz }, 
      foreign_key: :somekey, 
      primary_key: :somekey 
end 

Việc sử dụng PK và FK rõ ràng ở đây là do mối quan hệ cũ giữa các bảng bên dưới. Có hàng trăm triệu "khách hàng quen" trong hệ thống sản xuất.

Là điểm làm rõ @TJR - mối quan hệ giữa Patron và Bar thực sự là một khóa ngoại phức trên các trường: somekey và: baz (hoặc: blah theo hướng ngược lại). ActiveRecord's: tùy chọn ngoại tuyến không cho phép mảng.

Tôi đã phát hiện ra rằng rất tiếc điều này ngăn cản has_many tiếp theo: thông qua hoạt động như mong đợi.

class Patron < ActiveRecord::Base 
    has_many :bars, 
      ->(patron) { baz: patron.blah }, 
      foreign_key: :somekey, 
      primary_key: :somekey 
    has_many :drinks, through: :bars 
end 

Sử dụng thông qua hiệp hội sản xuất lỗi như ...

ArgumentError: wrong number of arguments (0 for 1)

Mối liên hệ giữa thanh và đồ uống là một has_many cổ điển với phím tiêu chuẩn nước ngoài và chính (bar_id, id).

Tôi đã đưa ra một số công việc xấu xí xung quanh cho phép tôi để thực hiện các chức năng mong muốn nhưng toàn bộ điều có mùi khủng khiếp. Cho đến nay là tốt nhất trong số này trông giống như

class Patron < ActiveRecord::Base 
    has_many :bars, 
      ->(patron) { baz: patron.blah }, 
      foreign_key: :somekey, 
      primary_key: :somekey 
    def drinks 
    bars.drinks 
    end 
end 

Tôi đã nhận lớp Bar hiện có và nó bao gồm hàng trăm triệu bản ghi, như trước đây tôi đã đề cập, làm cho một cơ sở dữ liệu thay đổi bên khó khăn.

Một số bài đăng dường như đề xuất đánh giá chuỗi động bên trong proc để tránh phải vượt qua đối tượng khách hàng hiện tại - nhưng như đã đề cập trong các bài đăng khác, điều này không hiệu quả.

Vui lòng thông báo cho tôi về những gì tôi có thể làm để làm cho mối quan hệ của has_many hoạt động.

+0

Bạn có thể xin vui lòng gửi mô hình thực sự của bạn, thay vì * thanh *, * baz *, * somekey * ...? Nó giúp trả lời đúng. –

+0

Tôi không rõ ràng về phạm vi của hiệp hội has_many đang cố gắng thực hiện. Bạn không thể sử dụng tùy chọn khóa ngoại để chỉ định cột của thanh có chứa khóa chính của người dùng do các lý do cũ mà bạn gọi ra không? I E. có một cái gì đó như 'has_many: bars, foreign_key:" some_column_on_bar_storing_patron_id "' không hoạt động? Mặc dù từ kịch bản bạn đã vạch ra, tôi cũng tự hỏi liệu Patron và Bar có nên có mối quan hệ has_many hay không (điều này phụ thuộc vào di sản bạn đề cập, nhưng thanh chỉ có một người bảo trợ hay không? bar?) – TJR

+0

Mối quan hệ giữa người bảo trợ và thanh thực sự được thực hiện bởi một mối quan hệ hợp chất khóa ngoại. Bởi vì: tùy chọn Foreign_key không chấp nhận một mảng các trường, tôi buộc phải sử dụng khối phạm vi để đạt được phần thứ hai của khóa ngoài hợp chất. –

Trả lời

0

Tôi vừa thử loại liên kết này trong Rails 4.2. Nó hoạt động khá tốt:

class Patron < ActiveRecord::Base 
    has_many :bars, 
      ->(patron) { where(baz: patron.blah) }, 
      foreign_key: :patron_id, 
      primary_key: :id 

    has_many :drinks, through: :bars 
end 

class Bar < ActiveRecord::Base 
    belongs_to :patron, 
      ->(bar) { where(blah: bar.baz) }, 
      foreign_key: :patron_id, 
      primary_key: :id 

    has_many :drinks 
end 

class Drink < ActiveRecord::Base 
end 

Kiểm tra các hiệp hội:

> p1 = Patron.first 
> p1.drinks 
    Drink Load (0.8ms) SELECT "drinks".* FROM "drinks" INNER JOIN "bars" ON "drinks"."bar_id" = "bars"."id" WHERE "bars"."patron_id" = 1 AND "bars"."baz" = 1 [["patron_id", 1], ["baz", 1]] 
=> #<ActiveRecord::Associations::CollectionProxy [#<Drink id: 3, name: "drink 3", bar_id: 2, created_at: "2017-04-07 03:30:06", updated_at: "2017-04-07 03:30:06">]> 
Các vấn đề liên quan