Глубоко вложенные формы Rails, использующие принадлежащие_, не работают?

Я работаю над грязной формой, которая, помимо прочего, должна управлять секцией с двухуровневой вложенностью. Это почти работает, но есть загвоздка, и единственное, что я вижу, отличается от других глубоко вложенных форм, которые работают, - это то, что есть отношение "принадлежат", а не "есть". Вот модели:

Event
  has_many :company_events, :dependent => :destroy
  accepts_nested_attributes_for :company_events

CompanyEvent
  belongs_to :company
  accepts_nested_attributes_for :company, :update_only => true
  belongs_to :event
  belongs_to :event_type

Company
  has_many :company_events
  has_many :events, :through => :company_events

Так что это довольно стандартное отношение "многие ко многим" через таблицу ссылок company_events. Форма, о которой идет речь, - это создание / редактирование события с динамической кнопкой "Добавить компанию" Javascript, все в значительной степени основанной на скринкасте Райана Бейтса и репозитории GitHub.

Основная форма:

<table id="companies">
  <tr><th>Company Name</th></tr>
  <% f.fields_for :company_events do |builder| %>
    <%= render 'company_event_fields', :f => builder, :f_o => nil %>
  <% end -%>
</table>
<p><br/><%= link_to_add_fields "Add Company", f, :company_events, "events" %></p>

И включенная форма выглядит следующим образом. Важно отметить, что идентификатор компании устанавливается с помощью обновления Javascript, которое я не буду здесь включать, потому что оно длинное. Обычно пользователь начинает вводить имя, отображается список автозаполнения, и при щелчке по названию в форме указываются как название компании, так и идентификатор.

<tr class="company_event_fields">
  <td>
    <% f.fields_for(:company) do |company_form| -%>
      <%= company_form.text_field :name, :size => 80 %>
      <%= company_form.hidden_field :id %>
    <% end -%>
  </td>
  <td>
    <%= f.hidden_field :_destroy %>
    <%= link_to_function "remove", "remove_co_fields(this)" %>
  </td>
</tr>

Когда я обновляю существующую запись, все работает просто отлично. Когда я пытаюсь сохранить форму с только что созданной записью, я получаю:

ActiveRecord::RecordNotFound in EventsController#update

Couldn't find Company with ID=12345 for CompanyEvent with ID=

С помощью трассировки стека:

/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/nested_attributes.rb:401:in `raise_nested_attributes_record_not_found'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/nested_attributes.rb:289:in `assign_nested_attributes_for_one_to_one_association'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/nested_attributes.rb:244:in `company_attributes='
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/base.rb:2906:in `send'

Я просмотрел код в nested_attributes и пробежал по нему с помощью отладчика. Кажется, что происходит из-за того, что существует Company.id, ActiveRecord предполагает, что запись уже есть, но, конечно, она не находит. Это кажется очень странным, поскольку, очевидно, мне нужно будет ввести идентификатор для создания новой записи CompanyEvent. Итак, я предполагаю, что что-то упустил.

Все примеры, которые, как я обнаружил, работают, похоже, все время вложены, используя отношения has_many, в то время как в этом случае это own_to, и мне интересно, является ли это корнем проблемы. Благодарим за любую идею...

2 ответа

Вот еще одно возможное решение, которое я разместил в аналогичном вопросе: /questions/42409460/ispolzovat-vlozhennuyu-model-relsov-dlya-sozdaniya-vneshnego-obekta-i-odnovremenno-redaktirovaniya-suschestvuyuschego-vlozhennogo-obekta/42409476#42409476

Что-то вроде этого...

  accepts_nested_attributes_for :company
  def company_attributes=(attributes)
    if attributes['id'].present?
      self.company = Company.find(attributes['id'])
    end
    super
  end

Я столкнулся с той же проблемой, просто кажется, что rails не поддерживает использование вложенных моделей, таких как это: вы не можете сохранить новый объект с существующей вложенной моделью, например, представьте такую ​​ситуацию:

class Monkey < ActiveRecord::Base
end
class Banana < ActiveRecord::Base
    belongs_to :monkey
    accepts_nested_attributes_for :monkey
end

Это не сработает, если вы попробуете на консоли:

banana = Banana.create!
monkey = Monkey.new
monkey.attributes = {:banana_attributes => { :id => banana.id}}

Но это просто обойти, в вашей форме вам не нужно устанавливать вложенные атрибуты, если ваш банан уже постоянен, вам просто нужно иметь скрытое поле в форме обезьяны с banana_id, что приведет к чему-то вроде:

monkey.attributes = {:banana_id => banana.id}

И это спасет просто отлично.

Другие вопросы по тегам