两个 类 用户在尝试显示个人资料页面时发生冲突

Two classes of users conflicting when trying to show profile pages

我创建了两种类型的用户 - "users" 和 "shops"。我的应用程序设置为当用户登录时,他们会被发送到主页,然后通过 ruby if-elsif-else 逻辑显示他们的个人资料。

我的问题是逻辑的第二部分 elsif 无法正常工作,它正在呈现主页而不是商店资料页面。

home.html.erb

<% if logged_in? %> // corresponds to "user" model
<div>
  <aside class="col-md-4">
    <div>
      <h1>My Profile</h1>
    </div>
    <div class="hero-unit user_info">
      <%= render 'shared/user_info' %>
    </div>
    <section class="hero-unit car_form">
      <%= render 'shared/car_form' %>
    </section>
  </aside>

  <div class="col-md-8">
    <h1>My Cars</h1>
  </div>
  <div class="col-md-8">
    <%= render 'shared/feed' %>
  </div>
</div>

<% elsif shop_logged_in? %>  // checks if a shop has logged in

<div class="col-md-8">
    <%= render 'shared/shop_info' %>
</div>

<% else %>                //If no one is logged in, home page is shown
<div class="broke col-md-12">
  <div class="alive">
  <h1>Keep your car on the road<%= link_to "Sign up now!", signup_path, class: "btn btn-lg btn-primary" %></h1>
  </div>
</div>

我需要 <% elsif shop_logged_in? %> 部分才能正常工作。这是在 ShopSessionHelper 中定义的:

  def shop_logged_in?
    !current_shop.nil?
  end

然后是 user/driver class 的 SessionHelper。我有点担心两者之间的一些重叠,但它似乎工作正常(欢迎在这里提出建议)。

 def logged_in?
    !current_user.nil?
  end

这两个应该判断登录的是用户还是商店,并使用上述逻辑呈现正确的页面。为什么它不起作用?

为了完整起见,这里是我的控制器和助手的完整信息:

sessions_controller.rb

class SessionsController < ApplicationController

  def new
  end

  def create
    user = User.find_by(email: params[:session][:email].downcase)
    if user && user.authenticate(params[:session][:password])
      log_in user
      params[:session][:remember_me] == '1' ? remember(user) : forget(user)
      redirect_to root_path
    else
      #Show error message
      flash.now[:danger] = 'Invalid email/password combination'
      render 'new'
    end
  end

  def destroy
    log_out if logged_in?
    redirect_to root_url
  end
end

sessions_helper.rb

module SessionsHelper

  # Logs in the given user.
  def log_in(user)
    session[:user_id] = user.id
  end

  # Remembers a user in a persistent session.
  def remember(user)
    user.remember
    cookies.permanent.signed[:user_id] = user.id
    cookies.permanent[:remember_token] = user.remember_token
  end

  def current_user?(user)
    user == current_user
  end

  # Returns the user corresponding to the remember token cookie.
  def current_user
    if (user_id = session[:user_id])
      @current_user ||= User.find_by(id: user_id)
    elsif (user_id = cookies.signed[:user_id])
      user = User.find_by(id: user_id)
      if user && user.authenticated?(cookies[:remember_token])
        log_in user
        @current_user = user
      end
    end
  end

  # Returns true if the user is logged in, false otherwise.
  def logged_in?
    !current_user.nil?
  end

  def forget(user)
    user.forget
    cookies.delete(:user_id)
    cookies.delete(:remember_token)
  end

  # Logs out the current user.
  def log_out
    forget(current_user)
    session.delete(:user_id)
    @current_user = nil
  end

  # Redirects to stored location (or to the default).
  def redirect_back_or(default)
    redirect_to(root_url)
    session.delete(:forwarding_url)
  end

  # Stores the URL trying to be accessed.
  def store_location
    session[:forwarding_url] = request.url if request.get?
  end
end

shop_sessions_controller.rb

    class ShopSessionsController < ApplicationController
      def new
      end

  def create
    shop = Shop.find_by(email: params[:session][:email].downcase)
    if shop && shop.authenticate(params[:session][:password])
      log_in shop
      params[:session][:remember_me] == '1' ? remember(shop) : forget(shop)
      redirect_to root_path
    else
      flash.now[:danger] = 'Invalid email/password combination'
      render 'new'
    end
  end

shop_sessions_helper.rb

module ShopSessionsHelper

  # Logs in the given shop.
  def log_in(shop)
    session[:shop_id] = shop.id
  end

  # Remembers a shop in a persistent session.
  def remember(shop)
    shop.remember
    cookies.permanent.signed[:shop_id] = shop.id
    cookies.permanent[:remember_token] = shop.remember_token
  end

  def current_shop?(shop)
    shop == current_shop
  end

  # Returns the shop corresponding to the remember token cookie.
  def current_shop
    if (shop_id = session[:shop_id])
      @current_shop ||= Shop.find_by(id: shop_id)
    elsif (shop_id = cookies.signed[:shop_id])
      shop = Shop.find_by(id: shop_id)
      if shop && shop.authenticated?(cookies[:remember_token])
        log_in shop
        @current_shop = shop
      end
    end
  end

  # Returns true if the shop is logged in, false otherwise.
  def shop_logged_in?
    !current_shop.nil?
  end

  def forget(shop)
    shop.forget
    cookies.delete(:shop_id)
    cookies.delete(:remember_token)
  end

  # Logs out the current shop.
  def log_out
    forget(current_shop)
    session.delete(:shop_id)
    @current_shop = nil
  end

  # Redirects to stored location (or to the default).
  def redirect_back_or(default)
    redirect_to(root_url)
    session.delete(:forwarding_url)
  end

  # Stores the URL trying to be accessed.
  def store_location
    session[:forwarding_url] = request.url if request.get?
  end
end

1st 一些建设性的批评。真的需要一个用户会话控制器和一个商店会话控制器吗?我能想到答案是肯定的唯一原因是,如果您的应用程序允许在同一会话中同时登录用户和登录商店。而且我认为这不会发生,因为您的主页逻辑:

<% if logged_in? %> // corresponds to "user" model
<% elsif shop_logged_in? %> // corresponds to "user" model

只检查其中之一,无法处理同时发生的两者。因此,为了简单起见,我将取消 Shop Session Controller,并在单个 Sessions Controller 中同时处理 Shop Session 和 User Sessions。

根据您在下面的评论,当用户登录时,为了处理不允许商店登录的问题,我会这样做: 在 Shop Sessions Helper 中将 def log_out 修改为 def shop_log_out,并在 User Sessions Helper 中将其添加到 log_in

商店会话助手:

def shop_log_out
  #your same code from before
end

用户会话助手:

def log_in(user)
  session[:user_id] = user.id
  if shop_logged_in? #check if a shop is logged in
    shop_log_out     #and log shop out if true
  end
end

现在,如果有商店登录,则每当用户登录时,它将被注销,防止两者同时发生。

如果您选择忽略我关于只使用一个会话控制器的建议,我会这样做:

<% elsif shop_logged_in? %> // checks if a shop has logged in 失败了。尝试使用 puts 追溯您的方法,找出失败的地方。我一次只退回一种方法,从:

开始
def shop_logged_in?
  puts "-------------------------"      #add this code
  puts "current_shop = #{current_shop}" #this code
  puts "-------------------------"      #and this code
  !current_shop.nil?
end

然后保存代码并导航到您的主页。 您很可能会收到一条错误消息,指出 current_shop 为 nil。

现在从 shop_logged_in? 中删除那些 puts 并转到 def current_shop:

def current_shop
  if (shop_id = session[:shop_id])
    puts "---------------------"   #add this
    puts "inside current_shop if"  #and this
    @current_shop ||= Shop.find_by(id: shop_id)
  elsif (shop_id = cookies.signed[:shop_id])
    shop = Shop.find_by(id: shop_id)
    if shop && shop.authenticated?(cookies[:remember_token])
      log_in shop
      @current_shop = shop
    end
  end
end

如果上面修改后的代码在终端中没有任何内容,那么我会将 puts 向下移动到 elsif 中以找出您正在流经的逻辑部分。如果这些 puts 都不是,那么您就知道 ifdef current_shop 内部的 elsif 都不为真。

如果是这样,那么我会说您的 routes.rb 文件有误。您的商店登录路径是否指向 shopsession#new? 我能想到的另一件事是您忘记在应用程序控制器中添加 include ShopSessionsHelper