Вложенная форма Rails с помощью has_many: как редактировать атрибуты модели соединения? - PullRequest
103 голосов
/ 02 февраля 2010

Как редактировать атрибуты модели соединения при использовании accepts_nested_attributes_for?

У меня есть 3 модели: темы и статьи, к которым присоединились линкеры

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

Поэтому, когда я собираю статью в «новом» действии контроллера тем ...

@topic.articles.build

... и создайте вложенную форму в themes / new.html.erb ...

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

... Rails автоматически создает компоновщик, и это здорово. Теперь по моему вопросу: Моя модель компоновщика также имеет атрибуты, которые я хочу изменить через форму «Новая тема». Но компоновщик, который автоматически создает Rails, имеет нулевые значения для всех своих атрибутов, кроме topic_id и article_id. Как я могу поместить поля для этих других атрибутов компоновщика в форму "новая тема", чтобы они не выходили ноль?

Ответы [ 3 ]

90 голосов
/ 17 февраля 2010

разобрался с ответом.Уловка была:

@topic.linkers.build.build_article

, которая создает компоновщики, а затем создает статью для каждого компоновщика.Итак, в моделях:
topic.rb нужно accepts_nested_attributes_for :linkers
linker.rb необходимо accepts_nested_attributes_for :article

Тогда в виде:

<%= 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...
6 голосов
/ 08 мая 2013

Когда форма, сгенерированная Rails, отправляется на Rails controller#action, params будет иметь структуру, похожую на эту (некоторые добавленные атрибуты добавлены):

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."
        }
      }
    }
  }
}

Обратите внимание, что linkers_attributes на самом деле является индексированным нулями Hash с String ключами, а не Array? Ну, это потому, что ключи поля формы, которые отправляются на сервер, выглядят так:

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

Создание записи теперь так же просто, как:

TopicController < ApplicationController
  def create
    @topic = Topic.create!(params[:topic])
  end
end
3 голосов
/ 18 июля 2012

Быстрый GOTCHA для использования has_one в вашем решении. Я просто скопирую и вставлю ответ пользователя KandadaBoggu в этой теме .


Подпись метода build отличается для has_one и has_many ассоциаций.

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

Синтаксис сборки для has_many ассоциации:

user.messages.build

Синтаксис сборки для has_one ассоциации:

user.build_profile  # this will work

user.profile.build  # this will throw error

Прочитайте has_one ассоциацию документацию для получения более подробной информации.

...