2011-02-01 37 views
11

Vì vậy, tôi có ý tưởng điên rồ này rằng tôi muốn áp dụng phạm vi cho một liên kết được bao gồm. Đây là những gì tôi đã tìm ra và dường như chỉ hoạt động tốt:sử dụng phạm vi liên kết

class Event < ActiveRecord::Base 
    has_many :races 
    has_many :bad_races, :conditions => Race.bad_medals_sql, :class_name => "Race" 
end 

class Race < ActiveRecord::Base 
    def self.bad_medals_sql 
    arel_table[:prizes].eq('medals').to_sql 
    # This returns a string 
    # "`races`.`prizes` = 'medals'" 
    end 

    def self.bad_medals 
    where(bad_medals_sql) 
    end 
end 

Event.includes(:bad_races) 
Reloading... 
    Event Load (0.4ms) SELECT `events`.* FROM `events` 
    Race Load (0.5ms) SELECT `races`.* FROM `races` WHERE (`races`.event_id IN (1,2,3,4) AND (`races`.`prizes` = 'medals')) 

Vấn đề là nó thực sự gây khó hiểu. Để có phạm vi được xác định trên Race (để sử dụng ở nơi khác) và để sử dụng nó trên sự kiện của hiệp hội tôi phải có hai phương pháp trên Race. Đối với mỗi phạm vi.

Tôi chắc chắn rằng tôi có thể gói mẫu vào một plugin hoặc một số thứ như vậy, nhưng tôi muốn sử dụng AR/AREL nguyên bản hơn nếu có thể. Bất kỳ ý tưởng để làm điều đó?

Trả lời

6

Mã này có vẻ quá phức tạp. Giả sử rằng mục tiêu của bạn là để có được tất cả các sự kiện có chứa các cuộc đua chỉ với "huy chương" cho giải thưởng, sẽ không phải là một công việc đơn giản scope?

class Event < ActiveRecord::Base 
    has_many :races 
    scope :bad_races, includes(:races).where("races.prizes=?", "medals") 
end 

class Race < ActiveRecord::Base 
    belongs_to :event 
end 

Sau đó, bạn chỉ có thể chạy Event.bad_races để nhận các cuộc đua xấu.

+7

"Vì vậy, tôi có ý tưởng điên rồ rằng tôi muốn áp dụng phạm vi cho một liên kết được bao gồm." – jsharpe

+2

AFAIK bạn có thể DRY mã này bằng cách làm cho 'xấu' một phạm vi trong' Race', và sau đó chỉ cần nói 'races.bad'. Hoặc có lẽ nó chỉ hoạt động với phạm vi, tôi chưa kiểm tra: ( –

+1

@AlexeiAverchenko Nhưng trong trường hợp này, anh ta muốn các sự kiện có cuộc đua đáp ứng các điều kiện (tức là anh ta không chỉ muốn đối tượng Race, anh ta muốn các đối tượng sự kiện họ thuộc về). –

0

Một nhiều hơn đến nay cách để thể hiện phạm vi của hiệp hội của bạn như sau:

scope :bad_races, -> { joins(:races).where(races: { prizes: 'medals' }) } 
0

Bạn có thể sử dụng phạm vi trên cả hai mô hình với merge phương pháp. Nó thực sự tiện dụng trong trường hợp này:

class Event < ActiveRecord::Base 
    has_many :races 
    scope :bad_races, -> { joins(:races).merge(Race.bad_medals) } 
end 

class Race < ActiveRecord::Base 
    belongs_to :event 
    scope :bad_medals, -> { where(price: 'medal') } 
end 
Các vấn đề liên quan