【问题标题】:Different '/' root path for users depending if they are authenticated (using devise)用户的不同“/”根路径取决于他们是否经过身份验证(使用设计)
【发布时间】:2011-08-09 03:59:47
【问题描述】:

我正在编写一个 Rails 应用程序,其中有一个 Editor 和一个 Publication 模型。我正在使用设计进行编辑器身份验证,并且由于编辑器不能以访客身份执行任何操作,因此我编写了一个自定义布局用于登录页面,并且我希望访客用户只能看到登录页面。

现在我试图在我的应用中实现以下行为但没有成功:

require 'spec_helper'
require 'capybara/rails'

describe "Authentication" do

  describe "when logged in" do
    before(:each) do
      @editor = Factory(:editor, :password => 'secret')
      visit '/'
      fill_in 'Login', :with => @editor.login
      fill_in 'Password', :with => 'secret'
      click_button 'Sign in'
      page.should have_content('Signed in successfully.')
    end

    it "getting / should render publication page with no redirection" do
      visit '/'
      page.should_not have_content('Login')
      page.should have_content('Publications')
      # assert that there is no redirection
      page.current_path.should == '/'
    end

    it "visits the sign_in page should redirect to /" do
      visit '/editors/sign_in'
      page.should have_content('Publications')
      page.current_path.should == '/'
    end

  end

  describe "when not logged in" do
    it "getting / should not display the sign in warning" do
      visit '/'
      # I want to get rid of this message
      page.should_not have_content('You need to sign in or sign up before continuing.')
    end

    it "getting / should not redirect to the sign_in default page" do
      visit '/'
      page.should have_content('Login')
      # assert that there is no redirection
      page.current_path.should == '/'
    end

    it "getting the the sign_in default path works" do
      visit '/editors/sign_in'
      page.should have_content('Login')
      page.current_path.should == '/editors/sign_in'
    end

    it "login works and redirect me to the publications page (with /)" do
      @editor = Factory(:editor, :password => 'secret')
      visit '/'
      fill_in 'Login', :with => @editor.login
      fill_in 'Password', :with => 'secret'
      click_button 'Sign in'
      page.should have_content('Signed in successfully.')
      page.current_path.should == '/'
      page.should have_content('Publications')
    end
  end
end

主要问题是我想摆脱“您需要先登录或注册才能继续”。访客用户访问“/”时的消息。

我尝试使用来自 herehere 的提示,但没有成功。

关于如何用设计实现这一点的任何提示?

谢谢。

【问题讨论】:

  • 听起来你可以创建一个命名空间......你考虑过这个吗?
  • 什么意思?你能解释一下吗?谢谢。

标签: ruby-on-rails routes devise


【解决方案1】:

我认为你应该使用类似的东西

authenticated :user do
  root :to => 'users#index', as: :authenticated_root
end
root :to => 'welcome#index'

因为 rails4 不允许您需要将具有相同名称的路由指定为:

【讨论】:

    【解决方案2】:

    This post 解释如何实现:

    authenticated :user do
      root :to => "main#dashboard"
    end
    
    root :to => "main#index"
    

    这是pull request,它通过一些技术细节实现了这一点

    【讨论】:

    • 我听从了他的指示,但得到了@wildmonkey 所暗示的关于重复路线的错误。指定 as: 对我来说是一个重要的缺失步骤。
    【解决方案3】:
    authenticated :user do
      root :to => 'home#index', :as => :authenticated_root
    end
    root :to => redirect('/users/sign_in')
    

    直接从马嘴How to's for the devise gem。 :D

    【讨论】:

      【解决方案4】:

      另外,由于您需要在 Rails 4 中命名这些根路径,您可能会发现当您只想在 say your logo 上使用 root_path 将您带回仪表板或主页时会很烦人分别。我刚刚在 ApplicationHelper 中创建了可以轻松解决该问题的助手。

      module ApplicationHelper
        def root_path
          if user_signed_in?
            authenticated_root_path
          else
            unauthenticated_root_path
          end
        end
      
        def root_url
          if user_signed_in?
            authenticated_root_url
          else
            unauthenticated_root_url
          end
        end
      end
      

      【讨论】:

        【解决方案5】:

        是的,这个问题也让我很沮丧。

        最后我只是在 session#new 页面上隐藏了 flash 消息。根本不是一个很好的解决方案,因为有时您/do/希望显示该消息..

        一段时间后我放弃了,但我想知道你是否可以使用这个approach,但在那个 lambda 中设置一些标志,并在你的会话控制器中设置一个 before_filter,如果它存在则清空 flash。比如……

        #routes
        => 'users#dashboard', :constraints => lambda {|r| r.env["skip_flash"] = true; r.env["warden"].authenticate? }
        
        
        #sessions_controller.rb
        before_filter :only=>[:new] do
          flash[:notice] = nil if request.env["skip_flash"]
          request.env["skip_flash"] = false
        end
        

        我对路由约束和请求对象的工作方式不太熟悉.. 只是一个想法。这只会在您尝试访问“/”而不是其他页面时关闭 Flash 消息..

        我希望有人有一个很好的解决方案!

        【讨论】:

        • 我也是,我不喜欢这种解决方案。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多