【问题标题】:Devise helpers return nil设计助手返回零
【发布时间】:2015-02-07 23:03:41
【问题描述】:

我在<...>/layouts/application.html.erb 中有这一行:

<% if client_signed_in? %>

为未签名/已签名的客户端呈现不同的 html。起初我使用 SQLite3 并且一切正常,直到我尝试改用 MySQL。因此,我运行迁移文件,使用 rake db:seed 插入相同的数据并使用 Devise API 进行注册,然后检查数据是否已插入数据库。然后我尝试使用相同的 API 登录,并在上面的行中收到以下错误:

nil:NilClass 的未定义方法 `to_sym'

或者日志中更具体的版本:

ActionView::Template::Error (undefined method `to_sym' for nil:NilClass):
    11: <div class="navbar navbar-default navbar-fixed-top" role="navigation">
    12:   <div class="container">
    13:     <ul class="nav navbar-nav navbar-right">
    14:       <% if client_signed_in? %>
    15:           <li class="dropdown">
    16:             <a href="#" class="dropdown-toggle" data-toggle="dropdown">
    17:               <span class="glyphicon glyphicon-user"></span> 
  app/views/layouts/application.html.erb:14:in `_app_views_layouts_application_html_erb___3350269212856659822_70353324331380'

我对所有的 Devise 助手都是一样的,比如current_client(对应的模型是Client)等等。

database.yml:

development:
  adapter: mysql2
  encoding: utf8
  database: development
  pool: 5
  username: root
  password:
  socket: /tmp/mysql.sock

ApplicationHelper

module ApplicationHelper
    def resource_name
        :client
    end

    def resource
        @resource ||= Client.new
    end

    def devise_mapping
        @devise_mapping ||= Devise.mappings[:client]
    end 
end

Client 型号:

class Client < ActiveRecord::Base
    devise :database_authenticatable, :registerable
end

会话转储:

_csrf_token: "YYUINrP+2synbq2bayWVozyo3nfGVtzkxDd9QJn9S4k=" flash: {"discard"=>[], "flashes"=>{"notice"=>"登录成功。"}} session_id:“6ab5a131dc9300e2a3c0dbd4e00218f0” warden.user.client.key: [[2], "$2a$10$bqpnIBKi4XCy64TH1zzhB."]

所以,如你所见,session不是空的,它从model/db中获取了正确的id,登录过程也是成功的。

环境转储:

GATEWAY_INTERFACE: "CGI/1.1"
HTTP_ACCEPT:"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"
HTTP_ACCEPT_ENCODING: "gzip,deflate,sdch"
HTTP_ACCEPT_LANGUAGE: "ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4"
HTTP_CACHE_CONTROL: "max-age=0"
REMOTE_ADDR: "::1"
REMOTE_HOST: "::1"

【问题讨论】:

  • 请发布您的整个错误信息。
  • @joelparkerhenderson:你能说得更具体点吗?我只收到上面的消息。你需要框架跟踪吗?
  • 很好,有帮助。你可以发布你的方法的代码client_signed_in?好吗?而且,您确定这是一个长方法名称,而不应该是两个带点的方法,即client.signed_in?
  • @joelparkerhenderson :我没有任何代码,它是一个设计方法。有一些信息here。我也试过signed_in?(:client),同样的问题。

标签: mysql ruby-on-rails ruby ruby-on-rails-4 devise


【解决方案1】:

感谢您发布所有详细信息。这是调试它的建议。

设计自动生成方法,例如您的 client_signed_in? 不起作用。

您可以通过编辑 Devise 源代码来拦截此方法,并找出发生了什么。

Devise 有一个文件 helper.rb,其中包含自动生成代码:

def #{mapping}_signed_in?
  !!current_#{mapping}
end

def current_#{mapping}
  @current_#{mapping} ||= warden.authenticate(scope: :#{mapping})
end

要拦截方法,可以使用调试器,或者打印,或者引发:

def current_#{mapping}
  raise "Devise current mapping #{__method__} symbol is " + (:{mapping}).to_s
  @current_#{mapping} ||= warden.authenticate(scope: :#{mapping})
end

如果您使用 pry,或者想学习 pry,因为这种调试方式太棒了:http://www.jackkinsella.ie/2014/06/06/debugging-rails-with-pry-debugger.html

def current_#{mapping}
  binding.pry
  @current_#{mapping} ||= warden.authenticate(scope: :#{mapping})
end

我的猜测是这个方法是你的错误发生的地方,并且“映射”变量可能是 nil。

【讨论】:

  • 不知何故它没有给出任何结果(raiseprint)——它只是抛出了同样的错误。(我是 ruby​​ 和 RoR 的新手,顺便说一句)。真正让我失望的是,它在 SQLite 数据库中运行良好,所以可能是排序规则或编码问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-18
  • 2014-06-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多