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.