铁轨和设计:覆盖 SessionsController

发布于 2024-11-09 13:19:00 字数 2664 浏览 0 评论 0原文

我正在尝试在主页上设置登录表单。我设法按照 Wiki

除外,如果登录信息不正确,则会呈现 /devise/session/new.html.erb。 我不想要这样。我希望我的用户被重定向到 root_url WITH 错误提示信息。

我能够覆盖 registrations_controller.rb 以获得其他功能,但覆盖 sessions_controller.rb 给我带来了很多麻烦。

我应该改变什么才能做我想做的事?如果登录正确,我仍然希望将用户重定向到 after_sign_in_path。 原始控制器位于此处

到目前为止,我知道我必须在我的 routes.rb

devise_for :users, :controllers => 中执行此操作{:注册=> “注册”,:会话=> "sessions" }

我还设置了 controller/sessions_controller.rb

class SessionsController < Devise::SessionsController

  # GET /resource/sign_in
  def new
    resource = build_resource
    clean_up_passwords(resource)
    respond_with_navigational(resource, stub_options(resource)){ render_with_scope :new }
  end

end

我感觉我必须更改 render_with_scope :new 但是...如何? 在该版本中,我收到错误 undefined method 'users_url' for #

好吧,我会等待您的宝贵帮助

PS:帖子对我处理订阅错误有很大帮助。也许它会对登录错误有所帮助?

====编辑====

按照第一个答案建议,我还添加到initializers/devise.rb

config.warden do |manager|
  manager.failure_app = CustomFailure
 end

当用户未登录并尝试访问“受限”区域,他被重定向到 root_url 但当登录出错时,我现在出现以下错误:

The action 'devise/sessions#new' could not be found for Devise::SessionsController

(PS:我删除了我对会话控制器所做的所有操作,如果成功则登录有效)

=== 编辑 2 ===

遵循此 Wiki 重定向工作完美但是我没有任何错误通知。

我正在显示警报/通知闪存消息,如果这改变了任何内容

<% flash.each do |name, msg| %>          
  <% if msg.class == Array %>
    <% msg.each do |message| %>
    <%= content_tag :p, message, :id => "flash_#{name}" %>
  <% end %>
  <% else %>          
    <%= content_tag :p, msg, :id => "flash_#{name}" %>          
  <% end %>
<% end %>

===最终更新===

接受的答案有效。只是不要忘记显示闪光警报

I'm trying to set up a sign in form on my home page. I managed to do it by following the Wiki

Except, if the login infos are incorrect, the /devise/session/new.html.erb is rendered.
I don't want that. I want my user to be redirected to the root_url WITH the errors in a flash message.

I was able to override registrations_controller.rb for another feature but override sessions_controller.rb gives me a lot of trouble.

What am I suppose to change to do what I want ? I still want the user to be redirected to after_sign_in_path if the sign in went right.
The original controller is here

So far, I know I have to do that in my routes.rb

devise_for :users, :controllers => { :registrations => "registrations", :sessions => "sessions" }

And I also set up controller/sessions_controller.rb

class SessionsController < Devise::SessionsController

  # GET /resource/sign_in
  def new
    resource = build_resource
    clean_up_passwords(resource)
    respond_with_navigational(resource, stub_options(resource)){ render_with_scope :new }
  end

end

I have the feeling that I have to change the render_with_scope :new but ...how?
With that version, I get the error undefined method 'users_url' for #<SessionsController:0x5072c88>

Well, I'll wait for your precious help

PS: That post helped me a lot for handling errors on subscription. Maybe it'll help for sign in errors?

==== EDIT ====

Following the 1rst answer advice, I also added to initializers/devise.rb:

config.warden do |manager|
  manager.failure_app = CustomFailure
 end

When the user is not logged and tries to access a "restricted" area, he gets redirected to root_url but when the sign in goes wrong, I now have the following error :

The action 'devise/sessions#new' could not be found for Devise::SessionsController

(PS: I deleted everything I did with Session Controller and the log in works if successful)

=== EDIT 2 ===

Following this Wiki the redirection works perfectly BUT I don't have any error notification.

And I'm displaying the alert/notice flash message with that if that changes anything

<% flash.each do |name, msg| %>          
  <% if msg.class == Array %>
    <% msg.each do |message| %>
    <%= content_tag :p, message, :id => "flash_#{name}" %>
  <% end %>
  <% else %>          
    <%= content_tag :p, msg, :id => "flash_#{name}" %>          
  <% end %>
<% end %>

=== FINAL UPDATE ===

The accepted answer works. Just don't forget to display flash alerts

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

箜明 2024-11-16 13:19:00

您必须覆盖您的自定义故障设计类。

在 lib/custom_failure.rb 下添加此自定义失败类

class CustomFailure < Devise::FailureApp
  def respond
    if http_auth?
      http_auth
    elsif warden_options[:recall]
        recall
    else
      redirect
    end
  end

  def redirect
      store_location!
      flash[:alert] = i18n_message unless flash[:notice]
      redirect_to "/"
  end

  def recall
    env["PATH_INFO"] = attempted_path
    flash.now[:alert] = i18n_message(:invalid)
    self.response = recall_controller.action(warden_options[:recall]).call(env)
  end

  protected

  def i18n_message(default = nil)
    message = warden.message || warden_options[:message] || default || :unauthenticated

    if message.is_a?(Symbol)
      I18n.t(:"#{scope}.#{message}", :resource_name => scope,
             :scope => "devise.failure", :default => [message, message.to_s])
    else
      message.to_s
    end
  end

  def warden_options
    env['warden.options']
  end

  def warden
    env['warden']
  end

  def recall_controller
    "#{params[:controller].camelize}Controller".constantize
  end


  def attempted_path
    warden_options[:attempted_path]
  end

  def store_location!
    session[:"#{scope}_return_to"] = attempted_path if request.get? && !http_auth?
  end

  def attempted_path
    warden_options[:attempted_path]
  end

  def http_auth?
    !Devise.navigational_formats.include?(request_format) || (request.xhr? && Devise.http_authenticatable_on_xhr)
  end
end

在 config/application.rb 下写入

config.autoload_paths += %W(#{config.root}/lib)

__________________编辑 __________________

你说当“注册出错”时,这意味着控件应该在 Registrations_controller create 方法中。我猜一定是出了什么问题。尝试添加这些路由。

devise_for :users

  devise_scope :user do
    root :to => "devise/sessions#new"
    get "sign_in", :to => "devise/sessions#new"
    get "sign_out", :to => "devise/sessions#destroy"
    get "sign_up", :to => "devise/registrations#new"
  end

________________编辑2 ________________

将其添加到views/devise/registrations/new.html.erb中

<%= devise_error_messages! %>

You have to override your custom failure devise Class.

Add this custom failure class under lib/custom_failure.rb

class CustomFailure < Devise::FailureApp
  def respond
    if http_auth?
      http_auth
    elsif warden_options[:recall]
        recall
    else
      redirect
    end
  end

  def redirect
      store_location!
      flash[:alert] = i18n_message unless flash[:notice]
      redirect_to "/"
  end

  def recall
    env["PATH_INFO"] = attempted_path
    flash.now[:alert] = i18n_message(:invalid)
    self.response = recall_controller.action(warden_options[:recall]).call(env)
  end

  protected

  def i18n_message(default = nil)
    message = warden.message || warden_options[:message] || default || :unauthenticated

    if message.is_a?(Symbol)
      I18n.t(:"#{scope}.#{message}", :resource_name => scope,
             :scope => "devise.failure", :default => [message, message.to_s])
    else
      message.to_s
    end
  end

  def warden_options
    env['warden.options']
  end

  def warden
    env['warden']
  end

  def recall_controller
    "#{params[:controller].camelize}Controller".constantize
  end


  def attempted_path
    warden_options[:attempted_path]
  end

  def store_location!
    session[:"#{scope}_return_to"] = attempted_path if request.get? && !http_auth?
  end

  def attempted_path
    warden_options[:attempted_path]
  end

  def http_auth?
    !Devise.navigational_formats.include?(request_format) || (request.xhr? && Devise.http_authenticatable_on_xhr)
  end
end

Write this under config/application.rb

config.autoload_paths += %W(#{config.root}/lib)

_________________Edit __________________

You said when the 'sign up goes wrong', this means the control should be in registrations_controller create method. Something must be wrong there, I guess. Try to add these routes.

devise_for :users

  devise_scope :user do
    root :to => "devise/sessions#new"
    get "sign_in", :to => "devise/sessions#new"
    get "sign_out", :to => "devise/sessions#destroy"
    get "sign_up", :to => "devise/registrations#new"
  end

________________Edit 2 ________________

Add this in views/devise/registrations/new.html.erb

<%= devise_error_messages! %>

如果您在覆盖设计会话控制器时遇到错误 undefined method 'users_url' for #,您可以提供如下路径名。您错过的重要补充是 , :as =>; :用户

  devise_scope :user do
    root :to => "devise/sessions#new", :as => :users
    get "sign_in", :to => "devise/sessions#new"
    get "sign_out", :to => "devise/sessions#destroy"
    get "sign_up", :to => "devise/registrations#new"
  end

上述路由名称可能与现有或将来的路由冲突。作为替代方案,我发现这种设置往往效果很好:

  devise_for :users,
    :path_names  => { :sign_out => 'logout', 
                      :sign_in  => 'login', 
                      :sign_up  => 'register' },
    :controllers => { :sessions => 'users/sessions' } do

      # Sessions
      post '/login'         => 'users/sessions#create',       :as => :user_session
      get  '/login'         => 'users/sessions#new',          :as => :new_user_session
      get  '/logout'        => 'users/sessions#destroy',      :as => :destroy_user_session

      # Passwords
      post '/password'      => 'devise/passwords#create',     :as => :user_password
      put  '/password'      => 'devise/passwords#update'
      get  '/password/new'  => 'devise/passwords#new',        :as => :new_user_password
      get  '/password/edit' => 'devise/passwords#edit',       :as => :edit_user_password

      # Registrations
      post   '/register'    => 'devise/registrations#create', :as => :user_registration
      get    '/register'    => 'devise/registrations#new',    :as => :new_user_registration
      get    '/account'     => 'devise/registrations#edit',   :as => :edit_user_registration
      put    '/account'     => 'devise/registrations#update'
      delete '/account'     => 'devise/registrations#destroy'

  end

If you're running into the error undefined method 'users_url' for #<SessionsController:0x5072c88> when overriding the devise sessions controller you can provide a path name as below. The important addition that you missed is the , :as => :users.

  devise_scope :user do
    root :to => "devise/sessions#new", :as => :users
    get "sign_in", :to => "devise/sessions#new"
    get "sign_out", :to => "devise/sessions#destroy"
    get "sign_up", :to => "devise/registrations#new"
  end

The above route name might conflict with existing or future routes. As an alternative, I have found that this setup tends to work well:

  devise_for :users,
    :path_names  => { :sign_out => 'logout', 
                      :sign_in  => 'login', 
                      :sign_up  => 'register' },
    :controllers => { :sessions => 'users/sessions' } do

      # Sessions
      post '/login'         => 'users/sessions#create',       :as => :user_session
      get  '/login'         => 'users/sessions#new',          :as => :new_user_session
      get  '/logout'        => 'users/sessions#destroy',      :as => :destroy_user_session

      # Passwords
      post '/password'      => 'devise/passwords#create',     :as => :user_password
      put  '/password'      => 'devise/passwords#update'
      get  '/password/new'  => 'devise/passwords#new',        :as => :new_user_password
      get  '/password/edit' => 'devise/passwords#edit',       :as => :edit_user_password

      # Registrations
      post   '/register'    => 'devise/registrations#create', :as => :user_registration
      get    '/register'    => 'devise/registrations#new',    :as => :new_user_registration
      get    '/account'     => 'devise/registrations#edit',   :as => :edit_user_registration
      put    '/account'     => 'devise/registrations#update'
      delete '/account'     => 'devise/registrations#destroy'

  end
朕就是辣么酷 2024-11-16 13:19:00

调试提示尝试删除任何记录(用户会保持一致);如果您进行显示操作,则这不是设备配置问题。对于这种情况,请继续(其他情况在此处得到解答)

我看不到您在视图中调用根 javascript 文件的位置。

我已经在这个问题上碰过好几次了,在不同的布局中使用不同的 JavaScript 设置。无论您的标头读取什么,调用都

<%= javascript_include_tag 'my-differntly-fangled-application' %>

需要包含相关的清单文件

//= require jquery
//= require jquery_ujs

debugging hint attempt to delete any record (a user would be coherent); if you go to the show action, it is not a devise configuration matter. For this case, follow along (other cases are answered around here)

I cannot see where in the view you are calling the root javascript file.

I've banged my head on this one a few times, using different javascript set-ups in different layouts. Whatever your header reads, the call

<%= javascript_include_tag 'my-differntly-fangled-application' %>

needs to have the relevant manifest file include

//= require jquery
//= require jquery_ujs
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文