2012-02-11 36 views
5

Tôi có một mô-đun mà tôi kể cả trong một số mô hình với nội dung này:Làm thế nào để luôn sử dụng lớp cơ sở và bỏ qua STI trong Rails?

self.class.find_by_foo(bar) 

Tất cả mọi thứ vẫn ổn cho đến khi tôi bắt đầu sử dụng STI. dòng đó nên luôn luôn tạo ra các truy vấn

select * from table where foo=bar" 

không

select * from table where foo=bar AND type="Whatever" 

Có một cách đơn giản để tránh nó?

Tôi mặc dù có hai giải pháp. Đi bộ lên hệ thống phân cấp lớp cho đến khi tôi tìm thấy những lớp đầu nhất trước ActiveRecord::Base hoặc chạy các truy vấn bằng tay, như:

self.class.find_by_sql("select * from #{self.class.table_name} where foo=bar") 

tôi không thích một trong hai giải pháp. Có cái nào tốt hơn không?

Trả lời

2

Cho đến khi có một câu trả lời tốt hơn, tôi đang sử dụng mã này để tìm lớp cơ sở của chuỗi STI:

klass = self.class 
self.class.ancestors.each do |k| 
    if k == ActiveRecord::Base 
    break # we reached the bottom of this barrel 
    end 
    if k.is_a? Class 
    klass = k 
    end 
end 
19

Trước tiên, bạn luôn có thể tới lớp cơ sở với base_class phương pháp:

self.class.base_class.find_by_foo(bar) 

Tuy nhiên, trong ví dụ trên, bạn không cần phải truy cập vào lớp cơ sở. Bạn chỉ có thể làm như sau và Rails sẽ biết tên bảng chính xác:

self.class.where(:foo => bar) 

Thực tế có rất ít trường hợp bạn cần truy cập vào lớp cơ sở.

+0

Trong Rails 4 'self.class' bất ngờ trả về lớp cha của đối tượng, trong Rails 5' self.class' trả về, như được loại trừ, lớp mô hình. 'self.class.base_class' có thể được sử dụng để có được lớp cha. – Kris

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