link_to_remote в Rails отображает неверный URL при визуализации из RJS

#ruby-on-rails #prototypejs #rjs

#ruby-on-rails #prototypejs #rjs

Вопрос:

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

 <%= link_to_remote "remove", :url => { :action => "destroy", :id => guest.id } %>
  

При вызове из ERB-представления он работает нормально, например

 <div id="guests">
  

<%= рендеринг :частичный => @event.guests %>

То есть он отображает что-то вроде:

 <a href="#" onclick="new Ajax.Request('/guests/destroy/10', {[options removed]}); return false;">remove</a>
  

Проблема в том, что когда эта часть отображается из RJS в результате операции создания, подобной этой:

 page.insert_html :bottom, :guests, :partial => @guest
  

Вместо ссылки на действие destroy он ссылается на действие detail / show для гостя, например

 a href="#" onclick="new Ajax.Request('/events/1/guests/10', {[options removed]}); return false;">remove</a>
  

Кто-нибудь может сказать мне, что я делаю не так, или есть ли способ отладить то, что здесь происходит? Как вы могли бы заметить, я полный новичок в Rails 😉

Ответ №1:

Вы делали это почти правильно, но вы не совсем следуете соглашению. Позвольте мне объяснить.

Ссылки, согласно спецификации HTTP, предназначены для получения запросов — извлечения данных. Вы не должны использовать ссылки для изменения состояния ресурса. В принципе, не используйте ссылки для потенциально разрушительных действий, поскольку за ними может следовать паук или ускоритель. Rails по умолчанию делает каждую ссылку запросом GET. Итак, когда вы сделали это:

 <%= link_to_remote "remove", :url => { :action => "destroy", :id => guest.id } %>
  

Он отправил запрос GET. Я предполагаю, что в вашем файле routes.rb есть что-то вроде

карта.ресурсы:гости

Это создает массу маршрутов, которые вы могли бы использовать следующим образом:

 <%= link_to_remote "remove", :url => guest_path(guest) %>
  

При использовании маршрутов ресурсов в Rails используемый МЕТОД определяет вызываемое действие контроллера.

URL /guests/1, вызываемый с запросом GET, вызывает действие SHOW. Вам необходимо указать метод в вашем вызове link_to_remote — либо :get, :put, :post, либо :delete. :put предназначен для обновлений, :post предназначен для создания, :delete предназначен для, ну, удаления.

 <%= link_to_remote "remove", :url => { :action => "destroy", :id => guest.id }, :method => :delete %>
  

или очиститель,

 <%= link_to_remote "remove", :url => guest_path(guest), :method => :destroy %>
  

Но серьезно, не используйте ссылки. Используйте кнопки.

 <%= button_to_remote "remove", :url => guest_path(guest), :method => :destroy %>
  

Надеюсь, это поможет!

Комментарии:

1. Ссылки на самом деле являются прекрасным подходом для удаления данных. Довольно часто используются кнопки для генерации или созидания данных и ссылки для их удаления или уничтожения, особенно в таблицах. Почему бы ему не использовать их?

2. Спасибо @Brian за примеры наилучшей практики — это очень помогает! Я склонен согласиться с @Yaraher в том, что использование ссылок на деструктивные действия в некоторых случаях приемлемо, тем более что действие выполняется при onclick, поэтому сканеры и предварительные загрузчики не выполнили бы действие случайно (я думаю?). Но я понимаю вашу точку зрения, что это не самая безопасная вещь. Еще раз спасибо Брайану и Ярахеру за ваш вклад!

3. @Yaraher: Нет, ссылки не являются «прекрасным» подходом, и их обычное использование не является хорошим оправданием. Запросы GET предназначены для извлечения данных с сервера, а не для изменения данных на серверной части. ajaxian.com/archives/… Обратите внимание, что использование ссылок с другими методами в Rails работает только с включенным Javascript, что может сделать страницу бесполезной для тех, у кого программы чтения с экрана отключили JS, или для мобильных пользователей, у которых нет поддержки JS. CSS может исправить проблемы с рендерингом кнопок внутри ячеек таблицы, и сделать кнопку похожей на ссылку тривиально.

4. Разве метод (в данном случае GET против DELETE) не является гораздо, гораздо большим аспектом правильности подхода? Является ли это ссылкой или кнопкой, это проблема презентации, а не проблема протокола. Установка метода в значение DELETE не позволит поисковым роботам переходить по ссылке. Если отключенный JS вызывает беспокойство (и да, так и должно быть), мое личное мнение заключается в том, что вы должны учесть это, используя другие методы. Было бы стыдно позволить соображениям, не относящимся к JS, чрезмерно влиять на пользовательский интерфейс, представленный посетителям сайта с поддержкой JS. Но, кроме другого мнения о кнопках, я подумал, что ваш ответ был правильным.

Ответ №2:

Оказывается, «уничтожить» имеет особое значение в Rails. Вместо этого я переименовал действие уничтожения в delete, и оно работает нормально.