Удаление нескольких записей в Rails - PullRequest
0 голосов
/ 04 декабря 2009

Я работаю над приложением, которое позволяет пользователю выбирать несколько записей. После того, как эти записи выбраны, пользователь может удалить их все. При нажатии на кнопку удаления (после выбора одной или нескольких записей) отображается модальное диалоговое окно, в котором отображаются записи, выбранные пользователем с помощью кнопки подтверждения.

В настоящее время все вышеперечисленное выполняется с помощью jQuery на стороне клиента. Мне удалось все это настроить, чтобы кнопка подтверждения (которая является link_to с использованием :method => :delete) имела URL-адрес /entries/12,13,16,17, где числа представляют собой идентификаторы записей, выбранных пользователем. Я также попытался отправить URL в формате /entries/[1,2,3,4], но безуспешно. У меня такое чувство, что я не отправляю массив real .

Вот мой метод удаления, который прекрасно работает, когда используется один идентификатор (т.е. /entries/1), и, надеюсь, продолжит работать с одним идентификатором:

def destroy
 @entry = current_user.entries.find(params[:id])
 @entry.destroy

 respond_to do |format|
  format.html { redirect_to(entries_url) }
  format.xml  { head :ok }
 end
end

Когда я отправляю несколько идентификаторов (в формате 1,2,3,4,5), удаляется только первая запись, а остальные остаются нетронутыми. Вот как выглядит мой журнал вебрик после выполнения действия:

Processing EntriesController#destroy (for 127.0.0.1 at 2009-12-03 23:07:24) [DELETE]
  Parameters: {"action"=>"destroy", "_method"=>"delete", "id"=>"19,22", "controller"=>"entries"}
  User Load (0.3ms)   SELECT * FROM "users" WHERE ("users"."id" = '2') LIMIT 1
  User Update (0.3ms)   UPDATE "users" SET "updated_at" = '2009-12-04 04:07:24', "last_request_at" = '2009-12-04 04:07:24' WHERE "id" = 2
  Entry Load (0.2ms)   SELECT * FROM "entries" WHERE ("entries"."id" = 19 AND ("entries".user_id = 2)) 
  Tagging Load (0.4ms)   SELECT * FROM "taggings" WHERE ("taggings".taggable_id = 19 AND "taggings".taggable_type = 'Entry' AND (taggings.context = 'tags')) 
  Tag Load (0.2ms)   SELECT * FROM "tags" WHERE ("tags"."id" IN (22,23,24,29)) 
  Tagging Destroy (0.2ms)   DELETE FROM "taggings" WHERE "id" = 66
  Tagging Destroy (0.1ms)   DELETE FROM "taggings" WHERE "id" = 67
  Tagging Destroy (0.0ms)   DELETE FROM "taggings" WHERE "id" = 68
  Tagging Destroy (0.1ms)   DELETE FROM "taggings" WHERE "id" = 69
  Tagging Load (0.1ms)   SELECT * FROM "taggings" WHERE ("taggings".taggable_id = 19 AND "taggings".taggable_type = 'Entry') 
  Entry Destroy (0.1ms)   DELETE FROM "entries" WHERE "id" = 19
  Entry Load (0.5ms)   SELECT * FROM "entries" WHERE ("entries".user_id = 2) 
Redirected to http://localhost:3000/entries

Как видите, идентификаторы отправляются ("id"=>"19,22"), но загружается только первая запись. После этого связанные с ним теги будут удалены (я использую плагин acts_as_taggable_on). Затем первая запись (id => 19) уничтожается, и пользователь перенаправляется обратно на страницу списка записей.

Что нужно сделать, это повторить этот процесс (до перенаправления) для каждого переданного идентификатора. Я запутался, потому что Документы RoRs утверждают, что:

id - может быть целым числом или Массив целых чисел.

Что я делаю не так? Я чувствую, что я так близко, я могу попробовать это! Для меня было огромным триумфом заставить работать весь jQuery, так что теперь я знаю единственную часть, отсутствующую в методе контроллера, обрабатывающем множественные идентификаторы.

Любая помощь будет принята с благодарностью!

Ответы [ 5 ]

3 голосов
/ 04 декабря 2009

Существует метод ActiveRecord, который делает именно то, что вы хотите - проверьте destroy_all . Ожидается удаление строки, массива или хеша идентификаторов.

Я часто добавляю к контроллеру еще одно действие для destroy_multiple - не забудьте также добавить маршрут сбора:

def destroy_multiple
  current_user.entries.destroy_all(:id => params[:user_ids])
  redirect_to entries_url
end
0 голосов
/ 04 декабря 2009

Вы пробовали отладку и проверку того, что возвращается в @entry. Я думаю, что вы не можете получить весь массив. Вы можете попробовать использовать плагин ruby-debug для отладки вашего кода. Кстати, удаление с помощью GET может быть не лучшим вариантом

0 голосов
/ 04 декабря 2009

Вот что помог мне друг, придумав:

def destroy
    params[:id].split(',').each do |id| 
        @entry = current_user.entries.find(id)
        @entry.destroy
    end

    respond_to do |format|
        format.html { redirect_to(entries_url) }
        format.xml  { head :ok }
    end
end

Я уверен, что все это можно сделать намного лучше и эффективнее, но для Альфы это сработает. Спасибо всем за помощь!

0 голосов
/ 04 декабря 2009

Быстрое исправление:

Лично я бы отправил ids другим способом, но я не хочу испортить вашу маршрутизацию. Так что это будет работать, но я обращаюсь только к части destroy:

current_user.entries.destroy(params[:id].split(','))

Это ограничивает область до current_user, но вызывает функцию destroy напрямую с массивом идентификаторов.

Лучший путь:

Как я могу предложить сделать это более очевидным, примерно так:

Вместо /entries/12,13,16,17 Я бы использовал /entries/multiple?del[]=12&del[]=13&del[]=16&del[]=17

Я знаю, что это дольше, но это больше соответствует тому, как рельсы работают естественным образом. Затем на контроллере:

def destroy
   id = params[:id]
   id = (params[:del] || []) if(id == "multiple")

   current_user.entries.destroy(id)

   respond_to do |format|
     format.html { redirect_to(entries_url) }
     format.xml  { head :ok }
   end 
end

Теперь ваша функция поддерживает обычное одиночное действие destroy, а также ваш новый кратный destroy.

0 голосов
/ 04 декабря 2009

Вы можете разобрать параметры [: id] и создать массив из него, а затем использовать его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...