Вложенная форма Rails с Ajax - PullRequest
       3

Вложенная форма Rails с Ajax

5 голосов
/ 23 декабря 2010

У меня есть интересная проблема, связанная с созданием объекта в моем музыкальном приложении на Rails 3.

У меня есть две модели (не фактические модели; но для простоты): Playlist Песня

Плейлист has_many Песни; Песня принадлежит к плейлисту.

Каждый объект списка воспроизведения должен иметь точное количество песен. Каждая песня должна принадлежать плейлисту.

Учитывая это, я хочу создать процесс для создания списка воспроизведения, который также включает в себя создание всех необходимых песен одновременно.

Другое дело, что для получения данных Song пользователь вводит запрос (который я не буду сохранять в модели Song), после чего я собираю данные из API. Это данные, которые должны быть использованы для создания объекта Song. Поэтому я не могу (не думаю?) Использовать традиционную форму form_for.

Вместо этого я использую удаленный тег form_tag. Эта форма запрашивает запрос, а затем использует запрос Ajax для извлечения данных, которые помещаются во временный объект Song, а затем отображаются на странице создания списка воспроизведения с использованием представления Song. Эта форма используется повторно для всех необходимых объектов Song для списка воспроизведения.

Таким образом, идея заключается в том, что, когда пользователь ввел требуемое количество запросов (т.е. добавил требуемое количество песен в список воспроизведения), ему предоставляется новая кнопка, которая позволяет ему отправить информацию о списке воспроизведения и продолжить в процесс. После этого будет создан список воспроизведения со всеми объектами Song, которые были созданы с помощью Ajax в качестве дочерних элементов.

На самом деле, я не могу найти способ, чтобы это работало элегантно. Хотя я создаю объекты Song с помощью Ajax, они нигде не сохраняются и не знают, в какой список воспроизведения они должны быть добавлены (поскольку объект Playlist еще не существует в базе данных). Следовательно, когда я перехожу к следующему шагу, я остаюсь без всех данных песни. Я рассмотрел использование вложенных форм с accepts_nested_attributes_for, но не могу найти способ использовать его с моей установкой (не основанной на модели формы с использованием Ajax.)

Итак, я застрял. Если кто-то может помочь, это будет очень цениться.

Ответы [ 2 ]

1 голос
/ 23 декабря 2010

Я сталкивался с проблемами, подобными этому прежде. Кстати, я никогда не находил удаленные теги полезными и никогда не использовал их для чего-то такого сложного. Вы правы - вложенные формы с accepts_nested_attributes_for были созданы для такого рода вещей, и, безусловно, есть способ заставить это работать.

Что вам нужно сделать, так это после того, как Ajax-запрос сгенерирует вложенные поля Song на лету с помощью JavaScript. Например, скажем, у вас есть:

<form...>
  <input type="text" name="playlist[name]" />
  <div class="songs">
  </div>
</form>

Вы захотите, чтобы ваш обратный вызов Ajax делал что-то вроде (я предполагаю, что jQuery здесь):

<script type="text/javascript">
  $(function() {
    var songs = $('form .songs') // Store a reference to the DOM song container
    // Insert Ajaxy goodness for song lookup here.
    // When it's finished, it should call add_song and pass in any data it needs
  })

  function add_song(song_name, artist_name, artist_id) {
    var num_songs = $(songs).size()
    $(songs).append('<p>'+song_name+' by '+artist_name+
      '<input type="hidden" name="playlist[songs_attributes]['+num_songs+'][name]" value="'+song_name+'" />' +
      '<input type="hidden" name="playlist[songs_attributes]['+num_songs+'][artist_id]" value="'+artist_id+'" /></p>')
  }
</script>

Там происходит несколько вещей:

  1. Имя поля "playlist [songs_attributes] ..." - это то, что сообщает Rails, что это поле принадлежит вложенному атрибуту
  2. Индекс num_songs после "playlist [songs_attributes] ..." чрезвычайно важен. Скорее, чрезвычайно важно, чтобы она была уникальной для каждой песни. Думайте об этом как индекс массива. Так что основывать его на размерах постоянно растущего списка песен идеально. (Это самая сложная и наименее очевидная часть динамического создания вложенных полей формы, IMO.)

Мой код, вероятно, не идеален, и я уверен, что я все равно не правильно назвал ваши поля. Но это должно быть хорошим началом. Кроме того, просмотр отправленных данных формы в журнале разработки вашего приложения весьма полезен для отладки этого материала.

0 голосов
/ 24 декабря 2010

Вот несколько вещей для рассмотрения:

  • А как насчет ваших пользователей, у которых нет JavaScript? (Мне сказали, что эти люди существуют.)
  • Почему вы хотите связать процесс создания списка воспроизведения с процессом создания песни? Что не так с созданием плейлиста как собственного процесса? Таким образом, плейлист может быть сохранен. Затем вы можете создавать песни (так как это требует сбора данных из отдельного API), чтобы песни могли быть сохранены. Затем вы можете связать песни в плейлист. Подумайте о том, чтобы сохранить ввод пользователя на каждом шаге, чтобы, если он остановится посередине, он не потеряет все существующие данные.
  • Если вы сначала реализуете интерфейс не-Ajax, тогда вам будет проще собрать части, чтобы создать окончательный интерфейс Ajax. Таким образом, у вас есть все необходимые ресурсы на месте. Ajax просто становится хорошим связующим звеном, так что обновлений страниц не так много.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...