2010-01-11 25 views
8

Tôi có hai mô hìnhRails - build_association không làm việc cho một mối quan hệ has_one và belongs_to

class Subscription < ActiveRecord::Base 
    belongs_to :client 
end 

class Client < ActiveRecord::Base 
    has_one :subscription 
end 

nhưng khi tôi cố gắng để tạo ra một bố mẹ từ đứa trẻ ví dụ sub.build_client khoá ngoài không được đặt, ví dụ:

>> sub = Subscription.new 
=> #<Subscription id: nil, token: nil, user_id: nil, created_at: nil, updated_at: nil, cancelled: nil, active: nil, client_id: nil> 
>> sub.save(false); 
?> client = sub.build_client 
=> #<Client id: nil, server_id: nil, ip: nil, created_at: nil, updated_at: nil> 
>> client.save(false) 
=> true 
>> sub.client_id 
=> nil 
>> sub 
=> #<Subscription id: 4, token: nil, user_id: nil, created_at: "2010-01-11 06:07:45", updated_at: "2010-01-11 06:07:45", cancelled: nil, active: nil, client_id: nil> 

Nó không làm việc nếu tôi làm client.build_subscription

?> client = Client.new 
=> #<Client id: nil, server_id: nil, ip: nil, created_at: nil, updated_at: nil> 
>> client.save(false) 
=> true 
>> sub = client.build_subscription 
=> #<Subscription id: nil, token: nil, user_id: nil, created_at: nil, updated_at: nil, cancelled: nil, active: nil, client_id: 4> 
>> sub.save(false) 
=> true 
>> sub 
=> #<Subscription id: 5, token: nil, user_id: nil, created_at: "2010-01-11 06:09:32", updated_at: "2010-01-11 06:09:32", cancelled: nil, active: nil, client_id: 4> 
>> client 
=> #<Client id: 4, server_id: nil, ip: nil, created_at: "2010-01-11 06:09:02", updated_at: "2010-01-11 06:09:02"> 
>> ^C 

Ive đã dành 3 tiếng đồng hồ loay hoay và cũng chẳng thể nhanh chóng. Bất cứ ai có thể giải thích những gì tôi đang làm sai, mọi thứ cần kiểm tra vv

Trả lời

9

Theo các hiệp hội mẫu của bạn, Subscription là con của một số Client.

Nếu bạn tạo đăng ký trước và sau đó tạo khách hàng theo ví dụ đầu tiên của bạn, Rails không có cách nào để đặt client_id giá trị khóa ngoài trong bảng subscriptions vì tại thời điểm đó bạn chưa tạo hồ sơ khách hàng, vì vậy không có gì để liên kết với đăng ký. Đó là lý do tại sao bạn phải tạo bản ghi gốc (ví dụ: một khách hàng) trước và sau đó liên kết nó với một bản ghi đăng ký con bằng cách sử dụng phương thức build_subscription.

+0

cảm ơn john, tôi nghĩ đây là trường hợp (tôi đã tham khảo hướng dẫn đường ray nhưng không thể tìm thấy giải thích này vì vậy muốn xác nhận ở đây trên stackoverflow). Nhưng làm thế nào đi kèm với has_many thuộc về mối quan hệ này có thể được thực hiện. – robodisco

+0

Tôi chỉ nghĩ rằng nếu nó không thể được thực hiện tại sao là phương pháp xây dựng ở đó? Nếu không thể đặt giá trị ngoại lệ cho phương thức đó trong mối quan hệ này? – robodisco

+1

Đó là một câu hỏi hay. –

1

Trong các dự án của tôi, tôi có nhiều hiệp hội tương tự, nhưng tôi thường cấm thiết client_id để null, vì vậy tôi không thể tạo đối tượng trẻ em mà không cần đối tượng cha.

Hãy thử:

sub = Subscription.new 
sub.build_client 
sub.save 

Nó sẽ tạo ra và lưu cả hai đối tượng.

0

Trong một trong các nhận xét, bạn hỏi tại sao phương thức build_client có ở đó. Khi bạn lưu khách hàng và sau đó kiểm tra client_id trên tiểu, nó là con số không, nhưng nếu bạn đã có thể còn gọi là

sub.save(validate: false) 

và sau đó kiểm tra các client_id trên tiểu, nó sẽ tồn tại. Vì vậy, mặc dù nó đòi hỏi một tiết kiệm thêm, nó vẫn làm phép thuật thiết lập khóa ngoại cho phụ.

1

Điều này dường như đã được sửa trong Rails 4.2.5 hoặc cũ hơn. (Tôi không chắc phiên bản đầu tiên với bản sửa lỗi là gì. Tôi chỉ được thử nghiệm 4.2.5.)

Khi cha mẹ được lưu, sau khi chèn bản ghi gốc, bản cập nhật sẽ tự động được thực hiện để thêm id mẹ cho bản ghi con. Tuy nhiên, tôi không tìm thấy bất kỳ tài liệu nào về hành vi này, mã có liên quan hoặc kiểm tra tự động, vì vậy tôi không chắc chắn liệu nó có cố ý cố định hay không và hành vi này nên được dựa vào. Nó có thể là tốt nhất để gắn bó với các giải pháp trong các câu trả lời khác ở đây.

Điều này cũng có vẻ là vẫn bị hỏng cho has_many trong Rails 4.2.5.

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