Используйте acceptpts_nested_attributes_for для создания новых записей или обновления существующих - PullRequest
4 голосов
/ 15 сентября 2010

Прочитайте большое обновление для получения последней информации.

Привет всем,

У меня есть отношение многие ко многим в приложении rails, которое включает три таблицы: пользовательскую таблицутаблица интересов и объединяющая таблица user_interests, которая также имеет значение рейтинга, чтобы пользователь мог оценивать каждый из своих интересов по шкале от 1 до 10.

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

Я попытался ответить на этот вопрос Вложенная форма Rails с has_many: через, какотредактировать атрибуты модели соединения? , но проблема, с которой я сталкиваюсь, заключается в попытке включить список выбора в микс и иметь несколько интересов для оценки для пользователя.

Код модели:

user.rb
has_many :user_interests, :dependent => :destroy
has_many :interests, :through => :user_interests, :foreign_key => :user_id  
accepts_nested_attributes_for :user_interests

interest.rb
has_many :user_interests, :dependent => :destroy
has_many :users, :through => :user_interests, :foreign_key => :interest_id, :dependent => :destroy

user_interest.rb
belongs_to :user
belongs_to :interest

Просмотреть код:

app/views/user/_form.html.erb
<%= form_for(@user) do |form| %>
  ... user fields
  <%= form.fields_for :user_interests do |ui_form| %>
    ... loop through ALL interests
    <% Interest.all.each do |interest| %>
      <%= ui_form.select :rating, options_for_select(1..10) %>
      <%= ui_form.hidden_field :interest_id, :value => interest.id %>
    <% end %>
  <% end %>
<% end %>

Я также включил следующее в новые / редактировать действия в моем контроллере @user.interests.build.build_interest

Проблема, с которой я сталкиваюсь, заключается в том, что толькоодин интРейтинг erest передается в хэше params, когда я хочу иметь несколько.Также я получаю исключение, брошенное рельсами

Interest(#2172840620) expected, got Array(#2148226700)

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

РЕДАКТИРОВАТЬ:

Я нашелспособ заставить это работать, но это требует ручного редактирования HTML в инструментах разработчика Chrome, атрибут: name моих элементов формы генерируется как user[user_interests_attributes][rating], но если я изменю его на user[user_interests_attributes][][rating], он будет работать при обновлении записи,Однако я не могу вручную указать: имя элемента формы, который связан с объектом формы.Итак, что я могу сделать, чтобы показать, что несколько рейтинговых оценок проходят вместо того, который думает рельс?

БОЛЬШОЕ обновление:

Эй, ребята, у меня получилась полуфункциональная версия с небольшим количествомизменения:

Просмотреть код:

<% form.fields_for :user_interests do |ui_form| %>
<p>
    <%= ui_form.select :rating, options_for_select(1..5), :selected => :rating %>
    <%= ui_form.label :interest_title %>
    <%= ui_form.hidden_field :interest_id %>
</p>
<% end %>

Код контроллера:

def new
  @user = User.new
  Interest.all.each { |int| @user.user_interests.build({ :interest_id => int.id }) }
end

def edit
  @user = @current_user
  Interest.unrated_by_user_id(@user.id).each { |int| @user.user_interests.build({ :interest_id => int.id }) }
end

Теперь я могу редактировать и получать свои user_interests, которые обновляются или создаются, если рейтинг не существует,но я получаю сообщение об ошибке, что пользователь пуст при попытке создать нового пользователя.Также я не могу получить доступ к каким-либо атрибутам интереса в форме, чтобы отобразить интерес, который пользователь фактически оценивает.Кто-нибудь может помочь с этими предостережениями?

1 Ответ

3 голосов
/ 15 сентября 2010

Вам нужно только @user.interests.build, потому что это отношение has_many.build_interest - для случаев, когда существует отношение has_one / own_to.

При использовании fields_for :user_interests вы сообщаете модели User, что экземпляр одного или нескольких объектов user_interest будет в хеше параметров, когда пользовательсоздан / обновлен.Форма не создает и не обновляет какие-либо user_interests, но отправляет обратно массив хэшей user_interest_attributes, которые представляют user_interests для пользователя, на который ссылается форма.Это массив значений рейтинга user_interests, для которых user_interests не существует, так как вы ссылаетесь на них в форме, которая является причиной, по которой вы получаете сообщение об ошибке.

Поскольку вы передаете диапазон помощнику формы select, который вам нуженфактически не предоставляет никаких интересов в форме для выбора.Параметр select установит значение для столбца рейтинга в таблице user_interests со значением от 1 до 10. Пользователь не имеет значения для интереса для установки рейтинга, даже если таблица user_interests имеет столбец рейтинга.

проход :multiple => true в хэше options тега select создаст список множественного выбора, но я не думаю, что вы этого хотите.Я думаю, что вы хотите, чтобы на странице было много элементов, на которые пользователь может поставить рейтинг интересов.

Если вы хотите, чтобы пользователь мог выбирать много интересов, то это как использовать fields_for с accepts_nested_attributes_for для has_many :throughотношения:

<%= form_for(@user) do |f| %>
  <% f.fields_for :interest_ids  do |interest| %>
    <ul>
      <% Interest.all.each do |choice,i| %>
      <li class="selection">
        <%= interest.check_box [], { :checked => f.object.user_interest_ids.include?(choice.id) }, choice.id, ''  %>
        <%= interest.label [], choice.name %>
      </li>
    <% end %>
    </ul>
  <% end %>
<% end %>
...