2012-02-20 14 views
19

Tôi đang lập bản đồ 2 mô hình:Rails mô hình mà có cả 'has_one' và 'has_many' nhưng với một số contraints

User 
Account 

class Account 
    has_many :users 


class User 
    has_one :account 

Bảng sử dụng như ACCOUNT_ID trong đó.

Bây giờ trên mô hình Tài khoản, tôi muốn tạo 'người dùng chính' mà tài khoản chỉ có 1 lần tắt. Bảng người dùng có cờ boolean: is_primary, làm cách nào tôi có thể tạo has_one ở phía tài khoản cho người dùng có ánh xạ is_primary và account_id.

Vì vậy, SQL sẽ trông như thế:

SELECT * FROM users where account_id=123 and is_primary = 1 

Vì vậy, tôi muốn:

Một người sử dụng có một tài khoản. Tài khoản có nhiều người dùng và cũng có một người dùng chính.

Trả lời

41

Cách tiếp cận 1 - Thêm một hiệp hội mới

Thêm một hiệp hội has_one với một lambda where. Điều này cho phép bạn làm việc trong lược đồ hiện tại của bạn.

class Account 
    has_many :users 
    has_one :primary_user, -> { where(is_primary: true) }, :class_name=> "User" 
end 

Bây giờ là:

account.users #returns all users associated with the account 
account.primary_user #returns the primary user associated with the account 
# creates a user with is_primary set to true 
account.build_primary_user(name: 'foo bar', email: '[email protected]') 

Cách tiếp cận 2 - Thêm một phương pháp liên kết

class Account 
    has_many :users do 
    def primary 
     where(:is_primary => true).first 
    end 
    end 
end 

Bây giờ là:

account.users.primary # returns the primary account 
+0

cảm ơn bạn đã cung cấp các tùy chọn! – Blankman

+0

sẽ đánh giá cao nhận xét của bạn về vấn đề này vì nó có liên quan: http://stackoverflow.com/questions/9365068/rails-model-that-has-both-has-one-and-has-many-but-with-some -contraints – Blankman

+0

Cách tiếp cận đẹp và sạch sẽ. Bạn có thể giải thích làm thế nào để cập nhật primary_user trong một tài khoản # mẫu cập nhật với một (collection_) chọn của tất cả người dùng, sử dụng phương pháp tiếp cận 1? Cảm ơn bạn – Patient55

6

Nó có lẽ sẽ đơn giản hơn để thêm một lĩnh vực primary_user_id vào Tài khoản, và thêm một hiệp hội 'has_one' cho primary_user:

class Account 
    has_many :users 
    has_one :primary_user, :class_name => "User" 
end 

class User 
    has_one :account 
end 

Nếu bạn phải sử dụng sơ đồ hiện có (với: is_primary cờ boolean) , bạn có thể thêm một phạm vi như thế này:

class User 
    has_one :account 
    scope :primary, where(:is_primary => true) 
end 

và sau đó chuỗi phạm vi để tra cứu người sử dụng:

account = Account.find(1) 
primary_user = account.users.primary.first 
+0

+1 cho cách tiếp cận đầu tiên. Mặc dù 'account.users.primary' có tính biểu cảm cao hơn' account.users.primary.first' –

+1

Rất đúng khi quy ước đặt tên không hoạt động tốt. Nhưng điều này có thể được sửa chữa một cách dễ dàng bằng cách gọi phạm vi 'primaries' và tạo ra một phương thức lớp được định nghĩa là' def self.primary; primaries.first; kết thúc'. Bây giờ bạn có thể sử dụng phạm vi chung 'primaries', hoặc phương thức' primary' để tham chiếu tới một bản ghi duy nhất (nơi chỉ có 1 được mong đợi) – PinnyM

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