Немає маршрутів, які відповідають «/ користувачам / виходу» на рейки 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.