Rails вкладена форма з has_many: через, як редагувати атрибути моделі приєднання?


103

Як редагувати атрибути моделі приєднання, використовуючи acceptts_nested_attributes_for?

У мене є 3 моделі: теми та статті, приєднані Linkers

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

... і внесіть вкладену форму в теми / new.html.erb ...

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

... Рейки автоматично створюють лінкер, що чудово. Тепер до мого питання: Моя модель Linker також має атрибути, які я хочу мати змогу змінити за допомогою форми "нова тема". Але посилання, яке Rails автоматично створює, має нульові значення для всіх його атрибутів, крім topic_id та article_id. Як я можу помістити поля для цих інших атрибутів лінкера у форму "нової теми", щоб вони не вийшли нульовими?


3
Я намагаюся зробити те саме, що і ви, лише в новому / створенні дії ... Цікаво, чи можете ви поділитися своїми діями контролера. Я хочу , щоб створити Userчерез Accountвикористовуючи в Relationshipякості linker... але я не можу зрозуміти, що нові і створюють дії покликані виглядати ... НЕ могли б ви?
Мохамад

Відповіді:


90

З’ясував відповідь. Трюк був:

@topic.linkers.build.build_article

Це будує посилання, а потім створює статтю для кожного лінкера. Отже, у моделях:
topic.rb потребує accepts_nested_attributes_for :linkers
linker.rbaccepts_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...

13
Дайте мені знати, чи це було корисно
Арколій,

13
Оновлення Rails 3: form_for та field_for потребують <% =%> замість <%%>, якщо ви використовуєте Rails 3.
Arcolye

Я б додав кодові звороти навколо двох доданих вами рядків acceptts_nested_attributes_. Я неодноразово пропускав цю інформацію під час просто сканування коду - як тільки я її ретельно прочитав, я зрозумів цю пропущену деталь, і це вирішило мою проблему. Дякую!
TJ Schuck

2
чесно кажучи, саме такий повний приклад потрібен керівництву rubyonrails.org.
ahnbizcad

Візуальна чіткість дійсно проходить довгий шлях, TJ Schuck.
ahnbizcad

6

Коли форма, створена 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

Я не впевнений, але я вважаю, що це було припущено разом зaccepts_nested_attributes_for
Arcolye

2
@Arcolye - Пошук такої інформації в Інтернеті для такої асоціації, як це було в той час, - можливо, мій google-fu був у той день. Я хотів би принаймні задокументувати це тут, як я як мій колега, і я просто припустив, що рейки перетворюють linked_attributes в масив замість нульового хеш-індексу. Сподіваємось, цей лайф допоможе комусь у майбутньому :)
Даніель Доезема

3

Швидкий 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асоціацію для отримання більш детальної інформації.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.