Raylar: has_one ilişkilendirmesinde oluştur


100

Merhaba (burada büyük Rails acemi), aşağıdaki modellere sahibim:

class Shop < ActiveRecord::Base
  belongs_to :user
  validates_uniqueness_of :title, :user_id, :message => "is already being used"
end

ve

class User < ActiveRecord::Base
  has_one :shop, :dependent => :destroy
end

Yeni bir mağaza açmak üzereyken şu hatayı alıyorum:

private method `create' called for nil:NilClass

Bu benim denetleyicim:

@user = current_user
@shop = @user.shop.create(params[:shop])

Burada ve orada kılavuzları ve öğreticileri okuyarak farklı varyasyonları denedim, ancak öncekinden daha fazla kafam karıştı ve işe yarayamıyorum. Herhangi bir yardım çok takdir edilecektir.


Soruyu yansıtmak için soru başlığı düzenlendi. Kopyası raylar bir has_one birliği ile bir yapı kullanılarak
Marc-Andre Lafortune

1
ayrıca kullanabilirsiniz@user.build_shop(params)
ImranNaqvi

Yanıtlar:


123

Her şeyden önce, işte istediğiniz şeyi nasıl yapacağınız:

@user = current_user
@shop = Shop.create(params[:shop])
@user.shop = @shop

Şimdi sürümünüzün neden işe yaramadığı:

Muhtemelen bunun işe yarayacağını düşündünüz çünkü Kullanıcının has_manyMağaza ile bir ilişkisi @user.shops.create(params[:shop]) olsaydı işe yarardı. Bununla birlikte, has_manyilişkiler ve has_oneilişkiler arasında büyük bir fark vardır :

Bir has_manyilişkiyle, shopsbir kullanıcıya mağaza eklemek ve bir kullanıcıdan mağaza eklemek ve kaldırmak için kullanabileceğiniz yöntemlere sahip bir ActiveRecord koleksiyon nesnesi döndürür. Bu yöntemlerden biri de createyeni bir mağaza açıp bunu kullanıcıya eklemektir.

Bir has_oneilişki ile, böyle bir koleksiyon nesnesini değil, sadece kullanıcıya ait olan Mağaza nesnesini geri alırsınız - veya kullanıcının henüz bir mağazası yoksa sıfır. Ne Shop nesnelerinin ne de nil'in bir createyöntemi olmadığından, createbu yolu has_oneilişkilerde kullanamazsınız .


Cevabınız için teşekkürler, sepp2k. Kodumun neden çalışmadığını şimdi anlıyorum.
Neko

119
Ayrıca kullanabilirsiniz @user.create_shop(params[:shop]). Has_one tarafından eklenen yöntemlere bakın .
nates

Seçilen cevap işe yarıyor, ancak @nates çözümü de işe yarıyor. İkinize de +1.
nfriend21

Aynı şeyi merak ettiğim için yanıta +1, bunun neden olduğunu açıklamak için yanıta +1 ve en iyi çözümü vermek için yoruma +1.
Temmuz'13

224

Bunu yapmanın daha kısa bir yolu şudur:

@user.create_shop(params[:shop])

Ruby on Rails kılavuzlarında has_one tarafından eklenen yöntemlere bakın .


6
Bu kesinlikle daha iyi bir yaklaşım
Magnum

7
Bir kez daha create_shop yaparsanız, önceki mağazayı sileceğine dikkat edin. Örneğin, çalıştırırsanız @user.create_shop(params[:shop_one_info])shop_one oluşturacak, ANCAK onu çalıştırırsanız @user.create_shop(params[:shop_two_info])ilk dükkanı silecek ve ikincisini oluşturacaktır.
ecoding5

Önceki mağazayı silme ile ilgili yukarıdaki yorum Rails 3.2.18 içindir, daha yeni sürümleri bilmiyorum. 5 dak. Sonra yorum düzenlenemiyor -_-
ecoding5

Bir çözüm buldum, ilişkili modelde benzersizlik belirlemedim, bu nedenle bu örneğin Mağaza modelinde nasıl ayarlandığını yaptığınızdan emin olun.
ecoding5

Ayrıca kullanabilirsiniz@user.build_shop(params)
ImranNaqvi

7

saveBunun yerine isterseniz iki yol daha create:

shop = @user.build_shop
shop.save

shop = Show.new
shop.user = @user
shop.save

1

Sadece yukarıdaki cevaplara eklemek için -

@user.create_shop(params[:shop])

Yukarıdaki sözdizimi yeni kayıt oluşturur ancak daha sonra benzer mevcut kaydı siler.

Alternatif olarak, silme geri aramasını tetiklemek istemiyorsanız

Shop.create(user_id: user.id, title: 'Some unique title')

Bu ileti dizisi yardımcı olabilir. Buraya Tıkla

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.