【问题标题】:Two classes of users conflicting when trying to show profile pages尝试显示个人资料页面时发生冲突的两类用户
【发布时间】:2015-02-28 19:38:19
【问题描述】:

我创建了两种类型的用户——“用户”和“商店”。我的应用程序设置为当用户登录时,他们会被发送到主页,然后通过 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>

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

  def shop_logged_in?
    !current_shop.nil?
  end

然后是用于用户/驱动程序类的 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

【问题讨论】:

    标签: html ruby-on-rails ruby controllers helpers


    【解决方案1】:

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

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

    只检查一个或另一个,无法同时处理两者。因此,为了简单起见,我将取消 Shop Session Controller,并从单个 Sessions Controller 中处理 Shop Sessions 和 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
    

    现在,如果有一个商店登录,它将在用户登录时退出,从而防止两者同时发生。

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

    &lt;% elsif shop_logged_in? %&gt; // 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 都不是,那么您知道def current_shop 中的ifelsif 都不会评估为true。

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

    【讨论】:

    • 谢谢。我使用两个会话助手解决了这个问题,并且明白这不是现在最好的方法,并且有人可以同时以两者的身份登录。我有办法阻止这种情况发生吗?喜欢if "logged in as user" then "cannot be logged in as shop"
    • 谢谢。我收到了这样做的建议,但它变得非常复杂。我不明白我怎么能使用一个会话控制器。无论如何,我不必复制其中的每个方法来对应用户或商店吗?
    猜你喜欢
    • 1970-01-01
    • 2016-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多