2010-09-20 33 views
15

Greetings,lọc đối tượng trẻ em trong một has_many: thông qua mối quan hệ trong Rails 3

Tôi có một ứng dụng mà CompaniesUsers cần phải thuộc về nhau thông qua một mô hình CompanyMembership, trong đó có thông tin thêm về tư cách thành viên (đặc biệt, Người dùng có phải là quản trị viên của công ty hay không, thông qua giá trị boolean admin). Một phiên bản đơn giản của các mã:

class CompanyMembership < ActiveRecord::Base 
    belongs_to :company 
    belongs_to :user 
end 

class Company < ActiveRecord::Base 
    has_many :company_memberships 
    has_many :users, :through => :company_memberships 
end 

class User < ActiveRecord::Base 
    has_many :company_memberships 
    has_many :companies, :through => :company_memberships 
end 

Tất nhiên, điều này làm cho nó đơn giản để có được tất cả các thành viên của một công ty thông qua company.users.all, et al. Tuy nhiên, tôi đang cố gắng để có được danh sách tất cả Người dùng trong Công ty là quản trị viên của Công ty đó (và cũng để kiểm tra xem người dùng có phải là quản trị viên của một công ty cụ thể hay không). giải pháp đầu tiên của tôi đã được như sau trong company.rb:

def admins 
    company_memberships.where(:admin => true).collect do |membership| 
    membership.user 
    end 
end 

def is_admin?(user) 
    admins.include? user 
end 

Trong khi làm việc này, một cái gì đó cảm thấy không hiệu quả về nó (nó lặp lại trên mỗi thành viên, thực hiện SQL mỗi lần, ngay Hoặc là Relation thông minh hơn mà?), và tôi 'không chắc chắn nếu có một cách tốt hơn để đi về điều này (có lẽ bằng cách sử dụng phạm vi hoặc fancy mới Relation đối tượng Rails 3 sử dụng?).

Bất kỳ lời khuyên nào về cách tốt nhất để xử lý (tốt nhất là sử dụng thực hành tốt nhất Rails 3) sẽ được đánh giá cao!

Trả lời

16

Tôi tin rằng tôi đang diễn ra về việc này một cách sai lầm, quy định cụ thể điều kiện về company_memberships thay vì users, đó là những gì tôi thực sự muốn (một danh sách các Users, không phải là một danh sách CompanyMemberships). Các giải pháp tôi nghĩ rằng tôi đang tìm kiếm là:

users.where(:company_memberships => {:admin => true}) 

mà tạo ra các SQL sau (đối với công ty với ID trong tổng số 1):

SELECT "users".* FROM "users" 
    INNER JOIN "company_memberships" 
    ON "users".id = "company_memberships".user_id 
    WHERE (("company_memberships".company_id = 1)) 
    AND ("company_memberships"."admin" = 't') 

Tôi không chắc chắn nhưng nếu tôi sẽ cần nó , nhưng phương pháp includes() sẽ biểu diễn bốc háo hức để giữ xuống số truy vấn SQL nếu cần thiết:

Active Record cho phép bạn chỉ định trong trước tất cả các hiệp hội có sẽ được tải. Điều này có thể là bằng cách chỉ định phương thức includes của cuộc gọi Model.find. Với bao gồm, Bản ghi đang hoạt động đảm bảo rằng tất cả các liên kết được chỉ định được tải bằng cách sử dụng số lượng tối thiểu có thể là truy vấn.queries. RoR Guides: ActiveRecord Querying

(Tôi vẫn mở cửa cho bất cứ đề nghị từ bất cứ ai nghĩ rằng đây không phải là tốt nhất/hiệu quả nhất/đúng con đường để đi về việc này.)

2

Làm thế nào về một cái gì đó như thế này:

Company.find(:id).company_memberships.where(:admin => true).joins(:user) 
+1

Một bước gần hơn! Trong khi nó không phải là câu trả lời tôi đang tìm kiếm, nó dẫn tôi đến nó :) –

7

Một cách mặc sạch sẽ để thêm liên kết vào mô hình Công ty của bạn, giống như sau:

has_many :admins, :through => :company_memberships, :class_name => :user, :conditions => {:admin => true} 

Bạn có thể phải đào sâu vào số rails doc để có được cú pháp chính xác.

Bạn không cần: bao gồm, trừ khi bạn có các lớp khác được liên kết với: người dùng mà bạn có thể tham chiếu trong chế độ xem của mình.

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