轨道与设计:覆盖会话控制器 [英] Rails & Devise: Override SessionsController

查看:89
本文介绍了轨道与设计:覆盖会话控制器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在主页上设置一个登录表单。我设法通过遵循维基



除非登录信息不正确,否则 /devise/session/new.html .erb 被呈现。
我不想要。我希望我的用户被重定向到 root_url WITH 闪存消息中的错误。



我可以覆盖 registrations_controller.rb 为另一个功能,但覆盖 sessions_controller.rb 给了我很多麻烦。



我想改变做什么我想做什么?如果登录权限正确,我仍然希望将用户重定向到 after_sign_in_path
原始控制器是 here



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



devise_for:users,:controllers => {:registrations => 注册,:sessions => 会话}



我还设置了 controller / sessions_controller.rb / p>

  class SessionsController< Devise :: SessionsController 

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

end

我有这样的感觉,我必须更改 render_with_scope:new 但...如何?
有了这个版本,我得到错误 undefined方法'users_url'for#< SessionsController:0x5072c88>



嗯,我会等待你的宝贵帮助



PS:帖子帮助我很多处理订阅错误。也许这将有助于登录错误?



====编辑====



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

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

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

  Devise :: SessionsController 
找不到操作'devise / sessions#new'?

(PS:我删除了会话控制器所做的一切,如果成功则删除了登录)



===编辑2 ===



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



我正在显示警告/通知Flash消息,如果这更改任何

 <%flash.each do | name,msg | %GT; 
<%如果msg.class == Array%>
<%msg.each do | message | %GT;
<%= content_tag:p,message,:id => flash _#{name}%>
<%end%>
<%else%>
<%= content_tag:p,msg,:id => flash _#{name}%>
<%end%>
<%end%>

=== FINAL UPDATE ===



接受的答案有效。只要不要忘记显示 flash alert

解决方案

你必须覆盖您的自定义失败设计类。



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

  CustomFailure类Devise :: FailureApp 
def response
if http_auth?
http_auth
elsif warden_options [:回忆]
召回
else
重定向
结束
结束

def重定向
store_location!
flash [:alert] = i18n_message,除非flash [:notice]
redirect_to/
end

def recall
env [PATH_INFO] = attempts_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] ||默认|| :未认证的

如果message.is_a?(符号)
I18n.t(:#{scope}。#{message},:resource_name =>范围,
: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}控制器.constantize
end


def attempts_path
warden_options [:attempts_path]
end

def store_location!
session [:#{scope} _return_to] = attempts_path if request.get? &安培;&安培; !http_auth?
end

def attempts_path
warden_options [:attempts_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 )

_________________编辑__________________



注册错误,这意味着控件应该在注册控制器创建方法中。我猜,那里的东西一定是错的。尝试添加这些路线。

  devise_for:users 

devise_scope:user do
root :to => devise / sessions#new
getsign_in,:to => devise / sessions#new
getsign_out,:to => devise / sessions#destroy
getsign_up,:to => 设计/注册#新
结束

________________编辑2 ________________



在视图/ devise / registrations / new.html.erb中添加此内容

 <% = devise_error_messages! %GT; 


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

解决方案

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

这篇关于轨道与设计:覆盖会话控制器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆