Rails: Rails'te has_one ilişkilendirmesi olan derlemeyi kullanma


143

Bu örnekte, userno ile bir oluşturuyorum profile, daha sonra profilebu kullanıcı için bir oluştur . Bir has_onedernek ile build kullanmayı denedim ama bu patladı. Bu çalışmayı görmenin tek yolu kullanmak has_many. userSadece en birisinde olması gerekiyordu profile.

Bunu deniyorum. Sahibim:

class User < ActiveRecord::Base
  has_one :profile
end

class Profile < ActiveRecord::Base
  belongs_to :user
end

Ama yaptığım zaman:

user.build_profile 

Hatayı alıyorum:

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

Raylarda 0 veya 1 ilişki kurmanın bir yolu var mı?


tam olarak ne denedin Lütfen biraz kod gönderebilir misiniz?
Ju Nogueira

Yanıtlar:


359

buildYöntem imzası için farklıdır has_oneve has_manydernekler.

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

has_manyİlişkilendirme için yapı sözdizimi :

user.messages.build

has_oneİlişkilendirme için yapı sözdizimi :

user.build_profile  # this will work

user.profile.build  # this will throw error

Daha fazla ayrıntı için has_oneilişkilendirme belgelerini okuyun .


28
Has_one için farklı sözdizimi beni her zaman yakalar ... kahretsin!
Galaxy

11
Burada en çok oylanan ve kabul edilen cevabın OP'nin sorduğundan farklı bir soruyu nasıl cevapladığı komik.
Ajedi32

Sözde kullanıcı profile aitse (yani kullanıcı tablosunun tablosunda foreign_key profile_id değeri varsa), kullanıcı için profil oluşturma da yukarıda belirtildiği gibi çalışacaktır, ancak yalnızca user.build_profile düzenleme için yeni eylem için user.build_profile if user.profile.nil? ve kullanıcı oluştururken profil oluşturmak istiyorsanız accepts_nested_attributes_for :profilebunu yazın Kullanıcı modeli. ve hangi kullanıcının yaratıldığı şeklinde <%= f.simple_fields_for :profile do |p| %>bunu yazın ve devam edin.
azim

ama bu farklı davranış neden has_one veya has_many için saklandı? Bence tasarım yaparken bir sebep olabilir.
meraklı

@ Ajedi32 cevap sorunun başlığıyla eşleşir, ancak gövde ile eşleşmez. Bunun ( build_<association>) Rails'te oldukça garip ve beklenmedik bir davranış olduğu düşünüldüğünde, bu cevabı arayan, ne demek istediğimi biliyorsanız, gerçek soruların cevabından çok daha fazla insan var.
Max Williams

19

Hata mesajına bir göz atın. Eğer sütun gerekli olmadığıdır Seni anlatıyor user_idiçinde profil tablosunun . Modeldeki ilişkilerin ayarlanması cevabın sadece bir parçasıdır.

Ayrıca user_id, profil tablosuna sütun ekleyen bir taşıma oluşturmanız gerekir . Raylar bunun orada olmasını bekler ve eğer değilse profile erişemezsiniz.

Daha fazla bilgi için lütfen şu bağlantıya göz atın:

Dernek Temelleri


1
Sorunumu çözdüm. Öğrendiğim kitap yabancı anahtar oluşumunu çok iyi açıklamadı. Modelime yabancı anahtar ekleyen yeni bir geçiş oluşturdum. Teşekkürler.
espinet

Sütunu her seferinde kendiniz oluşturmanız gerekiyor mu? Otomajik olarak olduğu fikrimi aldım. Bu fikri nereden bulduğumu bilmiyorum.
Rimian

Komut satırını kullanarak bir model oluştururken sütunu ekleyebilirsiniz rails g model profile user:references:index address:string bio:text.
duykhoa

1

Kullanım durumuna bağlı olarak, yöntemi sarmak ve bulunmadığında ilişkiyi otomatik olarak oluşturmak uygun olabilir.

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

şimdi #profileyöntemi çağırmak ya ilişkili profili döndürür ya da yeni bir örnek oluşturur.

Kaynak: Maymun bir yöntemi yama, yeni uygulamadan geçersiz kılınan yöntemi çağırabilirsiniz?


1
Geçerli raylar size bu kolaylaştırabilirsiniz (6.0.2.2 üzerinde test): def profile; super || build_profile; end.
glasz

-14

Bir olmalıdır has_one. Eğer buildçalışmıyorsa, sadece kullanabilirsiniz new:

ModelName.new( :owner => @owner )

aynıdır

@owner.model_names.build

11
Bu aynı değildir: build ile yeni bir model_name oluşturursanız, @owner kaydedildiğinde yeni model_name de kaydedilir. Böylece, birlikte kaydedilecek bir ebeveyn ve çocukları yapmak için build'i kullanabilirsiniz. .New ile bir model_adı yaparsanız durum böyle değildir
Max Williams
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.