Какова цель использования :method =› delete в button_to?

Насколько я понимаю, HTTP-глагол DELETE не поддерживается в HTML, и поэтому при создании форм удаления требуется другой маршрут.

Если это так, почему этот код работает нормально,

<%=button_to 'Delete', {:controller => :users, :action => 'destroy', :id => user.id}, :method => :delete%>

но следующий код не работает

<%=button_to 'Delete', {:controller => :users, :action => 'destroy', :id => user.id}%>

и выдает ошибку: 'No route matches [POST] "users/1/"'

не должен ли URL-адрес, который это разрешает, быть users/destroy/1 ?


person A S-R    schedule 20.10.2018    source источник
comment
Это HTTP-глагол.   -  person Sid    schedule 21.10.2018


Ответы (4)


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

DELETE может не работать как свойство в HTML-теге <form>, но это все равно допустимый HTTP-запрос.

Являются ли PUT, DELETE, HEAD, методы, доступные в большинстве веб-браузеров?

В чем польза HTTP-запроса PUT и DELETE методы?

person Ken    schedule 20.10.2018
comment
Я понимаю, что это допустимые HTTP-глаголы, и, хотя вы правы в том, что у меня есть работающее кодовое решение, нехорошо использовать код, который я не понимаю. Знакомы ли вы с какой-либо документацией о том, как работает :method=›:delete? Мне не удалось найти вопрос, касающийся этого, или документацию, связанную с его поведением (как документация для url_for, так и для button_to не очень помогла) - person A S-R; 21.10.2018
comment
Очень уважаю ваше желание знать все, что происходит. Но если вы сделаете это для всего в Rails, вы потратите много времени на понимание идиом, которые пытаются облегчить вашу жизнь. Я считаю, что и преимуществом, и недостатком Rails является то, что так много делается за кулисами. Это делает его отличным для прототипирования, но сложным для настройки. В какой-то момент вам придется либо пойти с ним, либо перейти с другой системы. Либо так, либо вы станете участником Rails. :) - person Ken; 21.10.2018

Старые версии HTML поддерживают только GET и POST. Более новая версия включает PUT, PATCH и DELETE, которые обрабатываются как XHR(XMLHttpRequest) запросы или просто AJAX запросы всеми основными веб-браузерами.

Когда выполняются запросы на PUT, PATCH или DELETE, Rails под капотом с помощью Javascript обрабатывает эти запросы как XHR запросы к клиенту. Когда Javascript в вашем приложении не работает или отключен, эти запросы будут возвращаться к GET

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

<%= button_to 'Delete', {:controller => :users, :action => 'destroy', :id => user.id}%>

button_to по умолчанию создает форму и отправляет запрос как POST, если только вы явно не переопределяете его, как вы делаете в первом случае с :method => :delete. Таким образом, приведенный выше фрагмент кода генерирует URL-адрес, подобный users/1/, но как POST, который в конечном итоге дает сбой, поскольку у вас нет такого маршрута, определенного в routes.rb

Разве URL-адрес не должен быть user/destroy/1 ?

Нет, когда вы используете :method => :delete в своем коде, сгенерированный URL будет users/1, но запрос будет отправлен как DELETE, что в конечном итоге будет работать, поскольку это действительный запрос в соответствии с вашими маршрутами, которые определены в routes.rb

person Pavan    schedule 21.10.2018

В Rails принято упоминать метод (HTTP-глагол) со ссылкой, чтобы Rails знал, какой метод контроллера вызывать, потому что без HTTP-глагола 3 действия show, update и destroy все эти 3 генерируют один и тот же путь URL-адреса, который "/users/:id" (если контроллер "UsersController"). Для дальнейшего чтения, я предлагаю взглянуть на:

https://guides.rubyonrails.org/routing.html#crud-verbs-and-actions

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

Как вы можете видеть на снимке экрана, если вы установите глагол HTTP в DELETE, Rails автоматически узнает, что он должен выполнить действие уничтожения, в противном случае путь для показа, обновления и уничтожения одинаков.

введите здесь описание изображения

person Saqib Shahzad    schedule 20.10.2018
comment
У меня сложилось впечатление, что button_to по умолчанию будет отправлять сообщения, но даже если это не так, я убедился, что :method=›:post не работает. Мне любопытно, что рельсы делают за кулисами, чтобы эмулировать форму с HTTP-глаголом DELETE - person A S-R; 21.10.2018
comment
я обновил свой ответ и перешел по ссылке, которую я упомянул, она обязательно ответит на ваш вопрос. - person Saqib Shahzad; 21.10.2018
comment
Я не думаю, что вы точно понимаете, о чем я спрашиваю. Я понимаю, что маршрутизация работает путем объединения глаголов HTTP с URL-адресом, и я понимаю, что rails может сделать вывод о том, какой метод контроллера вызывать на основе комбинации глаголов HTTP и URL-адреса, но вы не можете использовать method=delete с html-формой. Я спрашиваю, как rails эмулирует это поведение, используя хэш :method=›:delete. - person A S-R; 21.10.2018

Помещение :method=>:delete сигнализирует Rails о создании формы со скрытыми значениями, которые затем будут использоваться для эмуляции функции формы с

method="delete"

Если бы кто-нибудь мог объяснить, почему удаление :action => :destroy приводит к тому, что :id => user.id рассматривается как ключ и значение в URL-адресе (т.е. users?id=1 вместо users/1 ), я был бы признателен.

person A S-R    schedule 20.10.2018
comment
Похоже, он возвращается к методу GET - person Ken; 21.10.2018
comment
Я полагаю, это потому, что в этом случае вы явно устанавливаете :id => user.id, который будет автоматически параметризован для отправки с URL-адресом. Я думаю, что вам нужно <%= button_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' } %>. Rails выводит тип контроллера из переменной Active Record user (предполагается, что контроллер соответствует модели), и идентификатор не нужно устанавливать, потому что user уже содержит его. - person Devin; 21.10.2018