根据用户是否通过devise认证,为用户提供不同的'/'根路径。

16

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

现在我正在尝试在我的应用程序中实现以下行为,但没有成功:

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
主要问题是我想在访问'/'时,将"您需要在继续之前登录或注册"的消息删除,但是我没有成功。我已经参考了这里这里的提示,但都没用。请问如何在Devise中实现这个功能?谢谢。

听起来像是你需要创建一个命名空间... 你考虑过这个吗? - Christian Fazzini
什么意思?你能解释一下吗?谢谢。 - Fabio
5个回答

30

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

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

由于Rails4不允许具有相同名称的路由,因此您需要指定as:


24

这篇文章解释了如何实现以下操作:

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

root :to => "main#index"

这里是实现此功能的拉取请求,其中还包含一些技术细节。


2
我按照他的指示操作,但是出现了@wildmonkey所提到的重复路由错误。对我来说,指定“as:”是一个重要的遗漏步骤。 - doub1ejack

6
authenticated :user do
  root :to => 'home#index', :as => :authenticated_root
end
root :to => redirect('/users/sign_in')

以下内容来自于devise gem的使用指南


2

由于在Rails 4中需要为这些根路径命名,所以您可能会发现当您想要在例如徽标上使用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

0

是的,这个问题对我来说也非常令人沮丧。

最终,我只是在sessions#new页面上隐藏了闪存消息。这并不是一个好的解决方案,因为有时候你确实希望那条消息出现。

过了一段时间后,我放弃了,但我想知道你是否可以使用这个方法,但在lambda内部设置一些标志,并在sessions控制器中使用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

我对路由约束和请求对象的工作方式不太熟悉,但有一个想法。这将仅在尝试访问“/”而不是其他页面时关闭闪存消息。

希望有人能提供一个好的解决方案!


我也不喜欢这种解决方案。 - Fabio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接