Не найдено ни одного маршрута «/ users / sign_out» devise rails 3

386

Я установил devise в своем приложении и применил в своем application.html.erbфайле следующее:

<div id="user_nav">
    <% if user_signed_in? %>
        Signed in as <%= current_user.email %>. This cannot be cheese?
        <%= link_to 'Sign out', destroy_user_session_path %>
    <% else %>
        <%= link_to 'Register', new_user_registration_path %> or <%= link_to 'Sign in', new_user_session_path %>
    <% end %>
</div>

Я побежал rake routesи подтвердил, что все маршруты действительны.

Кроме того, в моем routes.rbфайле я devise_for :usersи root :to => "home#index".

Я получаю следующую ошибку при нажатии на ссылку «Выйти»:

No route matches "/users/sign_out"

Есть идеи, что является причиной ошибки?

вич
источник
1
Вы перезапустили свое приложение после добавления маршрутов? Изменения маршрута вступают в силу только при запуске.
Тило-Александр Гинкель
2
Да. Просто сделал это снова, чтобы быть в безопасности. Кроме того, я читал где-то еще в Stack, что это может быть проблемой из-за того, что новейший гем devise не совместим с Rails 3.0.3, поэтому я попытался изменить свой гем devise с 1.4.2 на gem 'devise', :git => 'git://github.com/plataformatec/devise.git'. Это ничего не сделало, хотя.
вич
Разве изменение записи в Gemfile не даст вам еще более новую версию Devise? Вы пытались указать меньший номер версии?
Лео Кассарани
Не могли бы вы опубликовать свой файл rout.rb
Феликс
1
Второй ответ Джесси ниже работал отлично.
вич

Ответы:

568

Я думаю, что путь для выхода - это DELETEметод. Это означает, что ваша ссылка для выхода должна выглядеть так:

<%= link_to "Sign out", destroy_user_session_path, :method => :delete %>

Ваш не включает в себя :method => :deleteчасть. Также обратите внимание, что для того, чтобы это работало, вы также должны включить его <%= javascript_include_tag :defaults %>в файл макета ( application.html.erb).

Джесси Дедекер
источник
3
Я могу с уверенностью сказать, что мне никогда не приходилось делать это ни в одном из моих приложений на Rails. link_to "Sign out", destroy_user_session_pathвсегда был достаточно хорош для меня.
Лео Кассарани
8
Я сделал тест, и он работает для меня. Не забывайте, что вещи меняются от одной версии к другой (будь то в Rails или Devise). Кроме того, выход из системы - это поведение, изменяющее состояние, которое не должно выполняться методами GET (по моему скромному мнению).
Джесси Дедекер
23
Для получения дополнительной информации объяснение, почему это было изменено в последней версии Devise, описано здесь и здесь .
Джесси Дедекер
6
Я столкнулся с той же самой проблемой, и предложение Джесси работало на меня. Я ожидаю, что любой, кто проходит через разработку Railscast, в конечном итоге окажется здесь из-за этого изменения ...
Джонни Гудман
2
Вы также можете ввести это в веб-консоль, чтобы проверить это $("<a href='/users/sign_out' data-method='delete'>Sign out</a>").appendTo('body');- если на странице загружен jQuery.
mraaroncruz
133

Я изменил эту строку в devise.rb:

config.sign_out_via = :delete

в

config.sign_out_via = :get

и это начало работать для меня.

kitdesai
источник
22
Чтобы сделать это раньше, нужно было выйти с помощью «GET / users / sign_out», но они изменили его на «DELETE», чтобы сделать его более RESTful. Автор объяснил, что GET не должен вносить изменения в сервер, такие как выход из системы.
Джонатан Аллард
2
это сработало для меня. Хотя я понимаю, что это не лучшая практика, другие ответы не дали результатов. Я не понимаю почему !!
Мягкий пух
8
Также можно использовать массив, если вы хотите поддерживать несколько методов. Например: config.sign_out_via = [ :post, :delete ]или devise_for :users, :sign_out_via => [ :post, :delete ], как описано в DEViSE / рельсы / routes.rb .
Хосам Али
2
Я бы не использовал запрос GET для выхода из системы, поскольку он открывает пользователю возможность атаки XSRF. (Хакер создает сайт с тегом изображения с src = " foo.com/users/sign_out ", пользователь посещает его и выходит из системы).
Райан Доэрти
1
@RyanDoherty Id Я не ошибаюсь, XSRF все еще возможен (злоумышленнику просто нужно использовать форму с action = "DELETE" в целевом URL, а затем автоматически отправить ее при загрузке страницы).
Maël Nison
60

Возможно, вы не включили javascript-файл jquery_ujs. Убедитесь, что вы используете последнюю версию jquery-ujs: https://github.com/rails/jquery-ujs и последние доступные файлы:

rails generate jquery:install

У вас не должно быть больше файла rails.js. Если вы это сделаете, вы, вероятно, устарели. Убедитесь, что этот файл загружен с настройками по умолчанию, в config / application.rb

config.action_view.javascript_expansions[:defaults] = %w(jquery.min jquery_ujs)

(Опять же, у вас не должно быть файла rails.js здесь). Наконец, добавьте ссылку, как описано в вики Devise (haml-style):

= link_to('Logout', destroy_user_session_path, :method => 'delete')

И все будет хорошо.

Gravis
источник
8
У меня было: method => 'delete' в моей ссылке, проблема была в том, что jquery_ujs не был включен, это решение решило мою проблему. Не забудьте поместить гем 'jquery-rails' в ваш гемфайл.
Роб Базинет
2
Спасибо, это сработало для меня. Вместо использования значений по умолчанию вы также можете использоватьjavascript_include_tag "jquery_ujs"
Bnicholas
Хороший улов, спасибо! Я использую require.js для асинхронной загрузки файлов и забыл требовать jquery_ujs.
Дэн Файрайзл
Я предположил, что «u» означает несжатый и удалил эту строку из application.js. Плохое предположение, я полагаю. Спасибо.
Джефф
Эта проблема возникла (в моем приложении, основанном на сотых разработках) после изменения начальной загрузки Twitter с менее на sass, и я забыл добавить обратно // = require jquery_ujs в мой application.js.
Джо
31

Чтобы сделать ссылку выхода из системы вызовом DELETE RESTful, необходим атрибут html data-method = "delete"с использованием кода rails= link_to('Logout', destroy_user_session_path, :method => :delete) .

Однако, если у вас не установлен гем jquery-ujsили вы не вызываете полученный javascript в вашем application.html через = javascript_include_tag "application", ответ будет отправлен как GET-запрос, и маршрут потерпит неудачу.

У вас есть несколько вариантов, если вы не хотите использовать jquery-ujsили не можете найти способ заставить его работать:

  1. Изменить config.sign_out_viaна равный :getвнутриdevise.rb (не рекомендуется, так как DELETE - это соответствующий запрос RESTful)
  2. ИЛИ Изменение link_toк = button_to('Logout', destroy_user_session_path, :method => :delete). С button_toRails сделает тяжелую работу по правильному вызову DELETE. Затем вы можете оформить кнопку, чтобы она выглядела как ссылка, если хотите.
Уилл Натан
источник
Переход от link_to к button_to сработал для меня, но я действительно не понимаю, почему? Что именно изменилось, кроме HTML / CSS?
Спирос Мандекис
1
Это связано с магией рельсов, которая автоматически генерирует html из таких функций, как button_to и link_to. Просто так получилось, что магия рельсов для button_to определяет правильный вызов RESTful DELETE, а link_to - нет. Если бы мне пришлось угадывать, я бы сказал, что причина в том, что элементы HTML-кнопки могут обрабатывать вызов DELETE (или связывать со скрытым полем, определяющим действие), в то время как обычные ссылки не могут.
Уилл Натан
Спасибо за это. Я настроил свое приложение на ручную обработку jquery, поэтому у меня не было jquery-ujs. Установка с использованием bower или bundler и включение соответствующей линии для конвейера ресурсов решает проблему.
jrhorn424
1
Это кажется мне самым безопасным и наиболее портативным решением.
О button_to, Rails генерирует formдля всего действия. Вот почему можно использовать :deleteметод с, button_toа не с link_to, просто посмотреть сгенерированный HTML.
Фернандо Фабрети
25

Попробуйте добавить новый маршрут для devise / session # destroy и создать ссылку на него. Например:

routes.rb
devise_for :users do
  get 'logout' => 'devise/sessions#destroy'
end

Посмотреть:

<%= link_to "Logout", logout_path %>
Кевин Цой
источник
Получаю ту же ошибку, что и Микаэль. Этот тест выше работает для меня.
rtfminc
1
У меня тоже была та же ошибка, что и у Майкла. Решение выше будет работать, но это не так, как это должно быть исправлено. Маршруты по умолчанию в Devise уже включают маршрут выхода из системы как метод DELETE. Обычно вам не нужно менять маршруты по умолчанию. Вот почему вы можете исправить это, просто добавив отдельный параметр к link_toвызову, как описано в другом ответе.
Джесси Дедекер
Вам не нужно добавлять маршрут в файл route.rb, devise позволяет вам изменить метод в devise.rb, который находится в каталоге / confit / initializers /.
Трэвис Пессетто
6
Никогда не иметь путь выхода из системы как GET.
Ягира
@ Джагира, почему? Почему бы не DELETE и GET?
hrdwdmrbl
14

Используйте его в вашем файле rout.rb:

devise_for :users do
    get '/users/sign_out' => 'devise/sessions#destroy'
end
Ума Махесварарао
источник
13

У меня была та же проблема с рельсами 3.1.0, и я решил добавить в файл следующие строки:

app/assets/javascripts/application.js
//= require_tree
//= require jquery
//= require jquery_ujs
гринго
источник
Если вы используете bower, попробуйте // = require jquery-ujs.
Монтейробрена
10

Ответ Джесси работал за одним исключением:

<%= link_to "Sign out", destroy_user_session_path, :method => :delete %>

изменение:

:delete

... для:

'delete'

Итак, код, который работал для меня:

<%= link_to "Sign out", destroy_user_session_path, :method => 'delete' %>
гален
источник
Спасибо за публикацию этого фрагмента кода, у меня сейчас работает sign_out.
Бук
9

Много ответов уже на вопрос. Для меня проблема была в два раза:

  1. когда я расширяю свои маршруты:

    devise_for :users do 
       get '/users/sign_out' => 'devise/sessions#destroy'
    end
  2. Я получал предупреждение, что это устарело, поэтому я заменил его на:

    devise_scope :users do
       get '/users/sign_out' => 'devise/sessions#destroy'
    end
  3. Я думал, что я удалю свой JQuery. Плохой выбор. Devise использует jQuery для "подделки" запроса DELETE и отправки его как GET. Поэтому вам необходимо:

    //= require jquery
    //= require jquery_ujs
  4. и, конечно, та же ссылка, что и многие упомянутые ранее:

    <%= link_to "Sign out", destroy_user_session_path, :method => :delete %>
Лукаш Музыка
источник
Можете ли вы объяснить 3-й пункт ... Я был жертвой этого, и я хочу понять это больше
Рахул Десс
1
Безусловно. Ваш веб-сайт на самом деле не отправляет запросы на УДАЛЕНИЕ. Откровенно говоря, он будет использовать только GET и POST. Поскольку в сообществе Rails было решено, что (по уважительным причинам) мы хотим удалять записи при отправке запроса DELETE, нам нужно использовать небольшую хитрость. Когда в вашем ERB вы указываете метод:: delete rails преобразует это в тег HTML5: data-method = "delete" и отправляет его как GET. Теперь вот где jQuery-ujs и jQuery включаются. Они позволяют приложению распознавать, что вы делаете. Так что ваш запрос может быть сопоставлен с действием контроллера.
Лукаш Музыка
без этих камней это не сработает. Конечно, вы можете изменить настройки devise (в devise initializer) и попросить его использовать GET вместо DELETE.
Лукаш Музыка
7

Добавить:

  <%= csrf_meta_tag %>  and 
  <%= javascript_include_tag :defaults %>  to layouts

Используйте эти теги link_to

 link_to 'Sign out', destroy_user_session_path, :method => :delete

  or

 link_to 'Sign out', '/users/sign_out', :method => :delete

В маршруты добавьте:

  devise_for :users do
    get '/users/sign_out' => 'devise/sessions#destroy'
  end
Амаль Кумар С
источник
7

Другой вариант - настроить выход из GET вместо DELETE, это можно сделать, добавив следующую строку в /config/initializers/devise.rb

config.sign_out_via = :get

Но, как Стив Клабник написал в своем блоге ) попробуйте использовать DELETE из-за семантики этого метода.

Родриго Флорес
источник
Только этот ответ работал для меня для Devise 3.5.1 и Rails 4.2.3
sagar junnarkar
Не забудьте перезапустить сервер :)
Джекмин
6

Если вы используете Rails 3.1, убедитесь, что ваш выход из application.html.erb выглядит следующим образом:

<%= link_to "Sign out", destroy_user_session_path, :method => :delete %>

И что ваша строка включения JavaScript выглядит следующим образом

<%= javascript_include_tag 'application' %>

Я предполагаю, что некоторые драгоценные камни перезаписывают новую структуру местоположения default.js.

StlTenny
источник
Спасибо! Это сводило меня с ума!
Дориан
5

Проверьте это с помощью исходного кода в github:

https://github.com/plataformatec/devise/commit/adb127bb3e3b334cba903db2c21710e8c41c2b40#lib/generators/templates/devise.rb (дата: 27 июня 2011 г.)

  • # Метод HTTP по умолчанию, используемый для выхода из ресурса. По умолчанию: получить. 188
  • # config.sign_out_via =: получить 187
  • # Метод HTTP по умолчанию, используемый для выхода из ресурса. По умолчанию: удалить. 188
  • config.sign_out_via =: удалить
Шейн
источник
5

Ну, ребята, для меня это было только удалить: method =>: delete

<%= link_to('Sign out', destroy_user_session_path) %>
workdreamer
источник
5

Это означает, что вы не сгенерировали файлы jquery после того, как установили гем jquery-rails. Итак, сначала вам нужно его сгенерировать.

rails generate devise:install

Первый вариант:

Это означает, что вы должны изменить следующую строку на /config/initializers/devise.rb

config.sign_out_via =: удалить в config.sign_out_via =: получить

Второй вариант:

Вы только измените эту строку <%= link_to "Sign out", destroy_user_session_path %>на<%= link_to "Sign out", destroy_user_session_path, :method => :delete %> на файл просмотра.

Обычно :method => :deleteне пишется по умолчанию.

Дипак Ламичхане
источник
5

Я хочу добавить к этому, хотя он немного стар.

ссылка "sign_out" не работает, несмотря на наличие: method =>: delete.

Комментарий, указывающий, что <%= javascript_include_tag :defaults %>должен быть включен, напомнил мне, что я недавно добавил jQ-скрипт JQuery и использовал простой<script src=""/> теги для их включения.

Когда я переместил их с после: default по умолчанию на before, sign_out снова начал работать.

Надеюсь, это кому-нибудь поможет.

Greg
источник
5

Большинство ответов являются частичными. Я сталкивался с этой проблемой много раз. Необходимо учесть две вещи:

<%= link_to(t('logout'), destroy_user_session_path, :method => :delete) %>

метод удаления должен быть указан

Затем devise использует jquery, поэтому вам нужно загрузить

   <%= javascript_include_tag "myDirectiveJSfile" %> 

и убедитесь, что ОБА jquery и jquery-ujs указаны в вашем myDirectiveJSfile.js

//= require jquery
//= require jquery_ujs
Джером
источник
5

Не забудьте включить следующую строку в ваш application.js (Rails 3)

//= require_self
//= require jquery
//= require jquery_ujs

Включите jquery_ujsв мое приложение рельсы, и это работает сейчас.

Ленивый Бревно
источник
4

Если вы используете HTTPS с устройством devise , оно прервется, если ваша ссылка для выхода будет иметь небезопасную версию. На бэкэнде он перенаправляет на защищенную версию. Это перенаправление является GET, который вызывает проблему.

Убедитесь, что ваша ссылка использует HTTPS. Вы можете использовать его protocol: "https"в вашем помощнике по URL (убедитесь, что вы используете помощника по URL, а не по пути).

<%= link_to "Sign out", destroy_user_session_url(protocol: "https"), method: :delete %>
Тайлер Кольер
источник
4
  devise_for :users
  devise_scope :user do
    get '/users/sign_out' => 'devise/sessions#destroy'
  end
dipole_moment
источник
3

Проблема начинается с рельсов 3.1 ... /app/assets/javascript/просто посмотрите на application.js.

Если файл не существует, создайте файл с таким именем, я не знаю, почему мой файл исчез или никогда не создавался в "rails new app"... .

Этот файл является экземпляром для jquery....

rome3ro
источник
3

Много решений там. но в основном используют это,

<%= link_to 'Sign out', destroy_user_session_path, method: :delete %>

или настройте devise.rb с правильным методом sign_out

В devise.rb

config.sign_out_via = :delete ( or  :get which u like to use.) 
Джон Сноу
источник
3

Используйте :getи :deleteметод для вашего пути:

devise_scope :user do
  match '/users/sign_out' => 'devise/sessions#destroy', :as => :destroy_user_session, via: [:get, :delete]
end
Закария
источник
Примечание: должен быть devise_for: пользователи, объявленные отдельно от этого. смотрите ответ от dipole_moment.
Taylored Web Sites
2

В ваших маршрутах:

 devise_for :users do
    get '/sign_out' => 'devise/sessions#destroy'
    get '/log_in' => 'devise/sessions#new'
    get '/log_out' => 'devise/sessions#destroy'
    get '/sign_up' => 'devise/registrations#new'
    get '/edit_profile' => 'devise/registrations#edit'
 end

и в вашем application.html.erb:

<%if user_signed_in?%>
          <li><%= link_to "Sign_out", sign_out_path %></li>
<% end %>
Мац хери
источник
1
Синтаксис теперь такой: devise_for: пользователи, затем значения должны быть помещены в devise_scope: user do ПРИМЕЧАНИЕ: singular: user для devise_scope
веб-сайты Taylored
2

Вот что я сделал (с Rails 3.0 и Devise 1.4.2):

  1. Убедитесь, что ваша страница загружает rails.js
  2. Используйте этот параметр: 'data-method' => 'delete'
  3. Хорошая идея добавить этот параметр:: rel => 'nofollow'
Larry
источник
1

Посмотрите, есть ли у вашего route.rb «resource: users» перед «devise_for: users», затем попробуйте поменять их местами:

  1. Работает

    • devise_for: пользователи
    • ресурсы: пользователи
  2. Сбой

    • ресурсы: пользователи
    • devise_for: пользователи
Чарльз Магид
источник
1

':method => :delete«в странице» data-method="delete"'так что ваша страница должна иметь jquery_ujs.js, он будет представлять ссылку с помощью метода удаления не метод GET

user1599712
источник
1

Я знаю, что это старый вопрос, основанный на Rails 3, но я столкнулся и решил его на Rails 4.0.4. Так что я подумал, как я могу исправить это для тех, кто столкнулся с этой проблемой в этой версии. Ваш пробег может варьироваться, но вот что сработало для меня.

Сначала убедитесь, что у вас установлены гемы, и запустите пакетную установку.

gem 'jquery-rails'

gem 'turbolinks'

gem 'jquery-turbolinks'

В application.js проверьте, что все требуется, как показано ниже.

Осторожно, если это правильно : это //= require jquery.turbolinksи не//= require jquery-turbolinks

//= require jquery
//= require jquery_ujs
//= require jquery.turbolinks
//= require turbolinks
//= require_tree .

Затем добавьте соответствующие ссылки в заголовок application.html.erb.

<%= javascript_include_tag  "application", "data-turbolinks-track" => true %>
<%= javascript_include_tag :defaults %>

Кажется, есть много вариантов реализации метода удаления, который, как я полагаю, зависит от версии Rails, которую вы используете. Это deleteсинтаксис, который я использовал.

<p><%= link_to "Sign Out", destroy_user_session_path, :method => 'delete' %></p>

Надеюсь, что это поможет выкопать кого-то из этой очень неприятной дыры!

mikeym
источник
0

В общем, когда вы получаете «Нет совпадений маршрутов», но думаете, что этот маршрут определен, дважды проверьте метод глагола / запроса http (будь то get, put, post, delete и т. Д.) Для этого маршрута. .

Если вы запускаете рейковые маршруты, вы увидите ожидаемый метод и сможете сравнить его с журналом запросов.

Muntasim
источник