Немає маршрутів, які відповідають «/ користувачам / виходу» на рейки 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, що це може бути проблема з новітньою дорогоцінною дорогоцінною коштовністю, не сумісною з Rails 3.0.3, тому я спробував змінити свій gem для розробки з 1.4.2 на gem 'devise', :git => 'git://github.com/plataformatec/devise.git'. Але це нічого не зробило.
vich

Чи не змінив запис у Gemfile просто ви отримаєте все новішу версію Devise? Ви спробували вказати нижчий номер версії?
Лев Кассарані

Чи можете ви опублікувати файл route.rb
felix

1
Друга відповідь Джессі нижче, спрацювала чудово.
vich

Відповіді:


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
Я зіткнувся з цим самим питанням, і пропозиція Джессі працювала на мене. Я сподіваюсь, що кожен, хто пробігає через розроблений рельсовий канал, врешті-решт опиниться тут завдяки цій зміні ...
johnnygoodman

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

і це почало працювати для мене.


22
Як це було зроблено раніше, потрібно було вийти за допомогою "GET / users / sign_out", але вони змінили його на "DELETE", щоб зробити його RESTful. Автор пояснив, що GET не повинен вносити зміни на сервер, такі як вихід із системи.
Джонатан Аллард

2
це працювало для мене. Хоча я ціную, що це не найкраща практика, інші відповіді не вдалися. Я не бачу чому !!
Легкий фуз

8
Можна також використовувати масив, якщо ви хочете підтримувати кілька методів. Наприклад: config.sign_out_via = [ :post, :delete ]або devise_for :users, :sign_out_via => [ :post, :delete ], як описано у розробці / рейках / маршрутах.rb .
Хосам Алі

2
Я б не використовував GET-запит для виходу, оскільки він відкриває користувача до XSRF-атаки. (Хакер створює веб-сайт із тегом зображення з src = " foo.com/users/sign_out ", користувач відвідує його та виходить із системи).
Райан Догерті

1
@RyanDoherty Id Я не помиляюся, XSRF все ще можливий (зловмисник просто повинен використовувати форму з action = "DELETE" на цільовому URL-адресі, а потім автоматично надіслати його при завантаженні сторінки).
Maël Nison

60

Ви, ймовірно, не включили файл JavaScript jaquery_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):

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

І все буде добре.


8
У мене було: method => 'delete' у своєму link_to, проблема не була включена у jquery_ujs, це рішення вирішило мою проблему. Не забудьте помістити у свій gemfile gem 'jquery-rails'.
Роб Базінет

2
Дякую, це працювало на мене. Замість використання значень за замовчуванням ви також можете використовуватиjavascript_include_tag "jquery_ujs"
Bnicholas

Гарний улов, дякую! Я використовую requ.js для асинхронного завантаження файлів і забув вимагати jquery_ujs.
Dan Fairaizl

Я припустив, що "u" означав нестиснений і видалив цю лінію з application.js. Я вважаю, що це погано. Дякую.
Джефф

Цю проблему вирішено (у моєму 100-му додатку, що базується на розробці) після зміни завантажувального твіттера з меншого на sass, і я забув додати // = вимагати 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 зробить важкий підйом при здійсненні належного вилучення. Потім ви можете стилізувати кнопку, щоб вона виглядала як посилання, якщо ви хочете.

Перехід від link_to на button_to працював для мене, але я насправді не розумію, чому? Що саме змінилося крім html / css?
Spyros Mandekis

1
Це пов'язано з "магією" рейок, яка автоматично генерує html з таких функцій, як button_to та link_to. Так буває, що магія рейок для кнопки_тож визначає правильний RESTful DELETE виклик, а link_to не робить. Якби мені довелося здогадатися, я б сказав, що причина полягає в тому, що елементи кнопки html можуть обробляти виклик DELETE (або пакет із прихованим полем, що вказує дію), а звичайні посилання не можуть.
Буде Натан

Дякую за це Я налаштував свій додаток на обробку jquery вручну, тому у мене не було jquery-ujs. Встановлення за допомогою баудера або постачальника та включення відповідного рядка для конвеєра активів вирішує проблему.
jrhorn424

1
Це здається мені найбезпечнішим і портативним рішенням.

О button_to, Rails створює formдля всієї дії. Ось чому можливо використовувати :deleteметод з, button_toа не з link_to, просто дивіться створений HTML.
Фернандо Фабреті

25

Спробуйте додати новий маршрут для розробки / знищення # знищення та посилання на нього. Наприклад:

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

вид:

<%= link_to "Logout", logout_path %>

Отримання такої ж помилки, як і mmichael. Цей вище тест працює для мене.
rtfminc

1
У мене також була така ж помилка, що і в mmichael. Наведене вище рішення спрацює, але це не так, як це слід виправити. Маршрути за замовчуванням у Devise вже включають маршрут виходу як метод DELETE. Зазвичай вам не потрібно змінювати маршрути за замовчуванням самі. Ось чому ви можете це виправити, просто додавши окремий параметр до link_toвиклику, як описано в іншій відповіді.
Джессі Дедекер

Вам не потрібно додавати маршрут до файлу route.rb, програма devise дозволяє змінити метод у devise.rb, який знаходиться в каталозі / confit / Initiators /.
Travis Pessetto

6
Ніколи не майте шлях виходу як GET.
Jagira

@Jagira чому? Чому б не ВИДАЛИТИ і отримати?
hrdwdmrbl


13

У мене була така ж проблема з рейками 3.1.0, і я вирішив додавання у файл наступних рядків:

app/assets/javascripts/application.js
//= require_tree
//= require jquery
//= require jquery_ujs

Якщо ви використовуєте bower, спробуйте // = вимагати jquery-ujs.
monteirobrena

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 працює для мене зараз.
buk

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
Звичайно. Ваш веб-сайт насправді не надсилає жодних DELETE-запитів. Відверто кажучи, він буде використовувати лише GET і POST. Оскільки в спільноті Rails було домовлено, що (з поважних причин) ми хочемо видалити записи при подачі DELETE-запиту, нам потрібно використовувати невелику хитрість. Коли в ERB ви вкажете метод:: delete rails перетворить це в тег HTML5: data-method = "delete" та подасть його як GET. Тепер тут починаються jQuery-ujs та jQuery. Вони дозволяють додатку розпізнавати це те, що ви робите. Так що ваш запит може відповідати дії контролера.
Лукаш Музика

без цих самоцвітів це не вийде. Звичайно, ви можете змінити налаштування devise (у розробці ініціалізатора) і попросити його використовувати 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

Але як писав Стів Клабнік у своєму блозі (http://blog.steveklabnik.com/2011/12/11/devise-actioncontroller-routingerror-no-route-matches-get-slash-users-slash-sign-out.html ) спробуйте використовувати DELETE через семантичність цього методу.


Лише ця відповідь працювала для мене в Devise 3.5.1 & Rails 4.2.3
sagar junnarkar

Не забудьте перезапустити сервер :)
jackmin

6

Якщо ви використовуєте Rails 3.1, переконайтесь, що вигляд application.html.erb виглядає так:

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

І що ваш рядок включення JavaScript виглядає наступним чином

<%= javascript_include_tag 'application' %>

Я здогадуюсь, що деякі дорогоцінні камені замінюють нову структуру розташування default.js.


Дякую! Це зводило мене з розуму!
Доріан

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) %>

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 %>потрібно включити, нагадав мені, що я нещодавно додав сценарій Java JQuery і використовував прості <script src=""/>теги для їх включення.

Коли я перемістив їх з після: за замовчуванням до раніше, вивіска знову почала працювати.

Сподіваємось, це комусь допомагає.


5

Більшість відповідей є частковими. Я вже багато разів торкався цього питання. Необхідно вирішити дві речі:

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

метод видалення потрібно вказати

Потім devise використовує jquery, тому вам потрібно завантажити їх

   <%= javascript_include_tag "myDirectiveJSfile" %> 

і переконайтесь, що BOTH 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 з приладом , він розірветься, якщо ваше посилання для виходу з не захищеної версії. На задньому кінці він переспрямовує на захищену версію. Це переадресація - це GET, що спричиняє проблему.

Переконайтеся, що у вашому посиланні використовується HTTPS. Ви можете змусити його використовувати protocol: "https"у своєму помічнику URL-адреси (переконайтеся, що ви використовуєте помічник URL-адреси, а не помічник шляху).

<%= link_to "Sign out", destroy_user_session_url(protocol: "https"), method: :delete %>


3

Проблема починається з рейок 3.1 ... /app/assets/javascript/просто шукайте application.js.

Якщо файл не існує, створіть файл з таким ім'ям, я не знаю, чому мій файл зникає або ніколи не створювався "rails new app"....

Цей файл є примірником для jquery....


3

Багато рішень є. але в основному використовують це,

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

або налаштувати devise.rb за допомогою належного методу виходу

В 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.
Тейлоризовані веб-сайти

2

У маршрутах.rb:

 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: користувачі, то get повинні бути поміщені в devise_scope: user NOT NOT: singular: user for devise_scope
Taylored Web Sites

2

Це те, що я зробив (з Rails 3.0 та Devise 1.4.2):

  1. Переконайтеся, що ваша сторінка завантажує rails.js
  2. Використовуйте цей парам: 'data-method' => 'delete'
  3. Хороша ідея додати цей парам:: rel => 'nofollow'

1

Перевірте, чи має ваш route.rb "ресурс: користувачів" перед "devise_for: users", тоді спробуйте поміняти їх:

  1. Працює

    • devise_for: користувачів
    • ресурси: користувачі
  2. Невдачі

    • ресурси: користувачі
    • devise_for: користувачів

1

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


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>

Сподіваємось, що допоможе копати когось із цієї дуже страшної нори!


0

Як правило, коли ви отримуєте "Не збігається маршрут", але ви думаєте, що цей маршрут визначений, то двічі перевірте метод дієслова / запиту http (чи його отримати, поставити, опублікувати, видалити тощо) для цього маршруту .

Якщо ви запускаєте рейкові маршрути, ви побачите очікуваний метод, і ви можете порівняти це з журналом запитів.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.