2010-03-18 24 views
123

Trong ví dụ này, tôi tạo một user không có profile, sau đó tạo một profile cho người dùng đó. Tôi đã thử sử dụng xây dựng với một hiệp hội has_one nhưng điều đó thổi lên. Cách duy nhất tôi thấy hoạt động này là sử dụng has_many. user được cho là chỉ có tối đa profile.Sử dụng bản dựng có liên kết has_one trong đường ray

Tôi đã thử cách này. Tôi có:

class User < ActiveRecord::Base 
    has_one :profile 
end 

class Profile < ActiveRecord::Base 
    belongs_to :user 
end 

Nhưng khi tôi làm:

user.build_profile 

tôi nhận được lỗi:

ActiveRecord::StatementInvalid: Mysql::Error: Unknown column 'profiles.user_id' in 'where clause': SELECT * FROM `profiles` WHERE (`profiles`.user_id = 4) LIMIT 1 

Có cách nào trong đường ray có 0 hoặc 1 liên kết?

+0

chính xác bạn đã thử gì? bạn có thể, xin vui lòng, đăng một số mã? –

Trả lời

324

Phương pháp chữ ký build là khác nhau cho has_onehas_many hiệp hội.

class User < ActiveRecord::Base 
    has_one :profile 
    has_many :messages 
end 

Việc xây dựng cú pháp cho has_many hiệp hội:

user.messages.build 

Việc xây dựng cú pháp cho has_one hiệp hội:

user.build_profile # this will work 

user.profile.build # this will throw error 

Đọc has_one hiệp hội documentation để biết thêm chi tiết.

+22

Cú pháp khác nhau cho has_one luôn luôn bắt tôi ra ... chết tiệt! – Galaxy

+2

Học các phương pháp ma thuật mới lạ ... – tackleberry

+0

@tackleberry, được gọi là metaprogramming –

-13

Nó phải là has_one. Nếu build không hoạt động, bạn chỉ có thể sử dụng new:

ModelName.new(:owner => @owner) 

cũng giống như

@owner.model_names.build 
+10

Điều này không giống nhau: nếu bạn tạo model_name mới với bản dựng, khi @owner được lưu thì model_name mới cũng sẽ được lưu. Vì vậy, bạn có thể sử dụng công cụ xây dựng để tạo phụ huynh và con cái sẽ được lưu cùng nhau. Đây không phải là trường hợp nếu bạn thực hiện một model_name với .new –

16

Xem qua thông báo lỗi. Nó cho bạn biết rằng bạn không cần cột user_id trong bảng hồ sơ . Đặt các mối quan hệ trong mô hình chỉ là một phần của câu trả lời.

Bạn cũng cần phải tạo di chuyển để thêm cột user_id vào bảng hồ sơ. Rails hy vọng điều này sẽ ở đó và nếu không, bạn không thể truy cập hồ sơ.

Để biết thêm thông tin xin hãy xem tại liên kết này:

Association Basics

+0

Tôi chỉ tìm ra vấn đề của mình. Cuốn sách tôi học hỏi không giải thích được sự sáng tạo của khóa ngoại quốc rất tốt. Tôi tạo ra một di cư mới mà thêm một chìa khóa nước ngoài vào mô hình của tôi. cảm ơn. – espinet

+0

Bạn có cần tự tạo cột mỗi lần không? Tôi đã có ý tưởng này rằng nó đã xảy ra tự động. Tôi không biết nơi tôi có ý tưởng đó. – Rimian

0

Tùy thuộc vào trường hợp sử dụng, nó có thể được thuận tiện để quấn phương pháp và tự động xây dựng hiệp hội khi không tìm thấy.

old_profile = instance_method(:profile) 
define_method(:profile) do 
    old_profile.bind(self).call || build_profile 
end 

bây giờ gọi phương thức #profile sẽ trả lại hồ sơ liên quan hoặc tạo một phiên bản mới.

nguồn: When monkey patching a method, can you call the overridden method from the new implementation?

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