Has_many ile iç içe geçmiş Rails form: aracılığıyla, birleştirme modelinin öznitelikleri nasıl düzenlenir?


103

Accepts_nested_attributes_for kullanırken bir birleştirme modelinin özniteliklerini nasıl düzenlersiniz?

3 modelim var: Linkers ile birleştirilmiş Konular ve Makaleler

class Topic < ActiveRecord::Base
  has_many :linkers
  has_many :articles, :through => :linkers, :foreign_key => :article_id
  accepts_nested_attributes_for :articles
end
class Article < ActiveRecord::Base
  has_many :linkers
  has_many :topics, :through => :linkers, :foreign_key => :topic_id
end
class Linker < ActiveRecord::Base
  #this is the join model, has extra attributes like "relevance"
  belongs_to :topic
  belongs_to :article
end

Bu yüzden makaleyi konular denetleyicisinin "yeni" eyleminde oluşturduğumda ...

@topic.articles.build

... ve konular / new.html.erb'de iç içe geçmiş formu oluşturun ...

<% form_for(@topic) do |topic_form| %>
  ...fields...
  <% topic_form.fields_for :articles do |article_form| %>
    ...fields...

... Rails, bağlayıcıyı otomatik olarak oluşturur, bu harika. Şimdi soruma gelecek olursak : Bağlayıcı modelimde "yeni konu" formu aracılığıyla değiştirebilmek istediğim öznitelikler de var. Ancak Rails'in otomatik olarak oluşturduğu bağlayıcı, topic_id ve article_id dışındaki tüm öznitelikleri için nil değerlere sahiptir. Bu diğer bağlayıcı öznitelikleri için alanları "yeni konu" formuna nasıl koyabilirim, böylece sıfır çıkmazlar?


3
Seninle aynı şeyi yapmaya çalışıyorum, sadece yeni bir eylemde / eylemde ... Denetleyici eylemlerinizi paylaşıp paylaşamayacağınızı merak ediyorum. Ben oluşturmak istediğiniz Userbir içinden Accountbir kullanan Relationshipbir olarak linker... ama yeni ve eylemler gibi ... sakıncası olur bakmak içindir oluşturduğunuz şeyleri bilemiyorum?
Mohamad

Yanıtlar:


90

Cevabı buldum. İşin püf noktası şuydu:

@topic.linkers.build.build_article

Bu, bağlayıcıları oluşturur, ardından her bağlayıcı için makale oluşturur. Yani modellerde:
topic.rb'nin accepts_nested_attributes_for :linkers
linker.rb'ye ihtiyacı varaccepts_nested_attributes_for :article

Sonra formda:

<%= form_for(@topic) do |topic_form| %>
  ...fields...
  <%= topic_form.fields_for :linkers do |linker_form| %>
    ...linker fields...
    <%= linker_form.fields_for :article do |article_form| %>
      ...article fields...

13
Bunun yardımcı olup olmadığını bana bildirin
Arcolye

13
Rails 3 güncellemesi: Rails 3 kullanıyorsanız <%%> yerine form_for ve field_for need <% =%> <% =%>.
Arcolye

Eklediğiniz iki accepts_nested_attributes_for satırının etrafına kod geri işaretleri eklerdim. Kodu tararken bu bilgiyi defalarca gözden kaçırdım - iyice okuduktan sonra, kaçırılan o ayrıntıyı yakaladım ve sorunumu çözdü. Teşekkürler!
TJ Schuck

2
dürüst olmak gerekirse, rubyonrails.org kılavuzlarının ihtiyaç duyduğu tam örnek budur.
ahnbizcad

Görsel netlik gerçekten uzun bir yol kat ediyor, TJ Schuck.
ahnbizcad

6

Rails tarafından oluşturulan form Rails'e gönderildiğinde controller#action, paramsbuna benzer bir yapıya sahip olacaktır (bazı uydurma özellikler eklenmiştir):

params = {
  "topic" => {
    "name"                => "Ruby on Rails' Nested Attributes",
    "linkers_attributes"  => {
      "0" => {
        "is_active"           => false,
        "article_attributes"  => {
          "title"       => "Deeply Nested Attributes",
          "description" => "How Ruby on Rails implements nested attributes."
        }
      }
    }
  }
}

Uyarı nasıl linkers_attributesgerçekte sıfır endeksli olduğu Hashile Stringanahtar ve değil bir Array? Bunun nedeni, sunucuya gönderilen form alanı anahtarlarının aşağıdaki gibi görünmesidir:

topic[name]
topic[linkers_attributes][0][is_active]
topic[linkers_attributes][0][article_attributes][title]

Kayıt oluşturmak artık şu kadar basit:

TopicController < ApplicationController
  def create
    @topic = Topic.create!(params[:topic])
  end
end

Emin değilim, ama bunun accepts_nested_attributes_for
baştan

2
@Arcolye - Böyle bir dernek için internette bu bilgiyi bulmak o zamanlar çok acı vericiydi - belki google-fu'm o gün kapalıydı. İş arkadaşım olarak en azından burada belgelemek istedim ve sadece bağlantılı_öznitelikleri sıfır indeksli bir hash yerine bir diziye dönüştüren rayların olduğunu varsaydım. Umarım bu haber gelecekte birine yardımcı olur :)
Daniel Doezema

3

Çözümünüzde has_one kullanırken için hızlı bir GOTCHA. Sadece kullanıcı tarafından verilen cevabı yapıştırmak kopyalar KandadaBoggu içinde bu konuya .


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 derleme sözdizimi :

user.messages.build

has_oneİlişkilendirme için derleme 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 .

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.