未定义的局部变量或方法`signin&#39; for#<class:0x31fa7f0> </class:0x31fa7f0>

时间:2014-04-14 09:56:24

标签: ruby-on-rails ruby devise

我在模型类中有以下错误。如何处理此类错误。

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  attr_accessor :signin
  validates :username, :uniqueness => {:case_sensitive => false}

  def self.find_first_by_auth_conditions(warden_conditions)
    puts warden_conditions
    conditions = warden_conditions.dup
    where(conditions).where(["lower(username) = :value OR 
            lower(email)= :value", { :value => signin.downcase }]).first
  end

end  

我是铁杆新手,通过做事来学习。如何debug此类问题。如果我在模型中出现这样的错误,我应该先在哪里看。

3 个答案:

答案 0 :(得分:1)

来自Devise的此方法,用于通过对用户名和电子邮件或其他方式进行身份验证。 您在signin变量中出现问题我使用login代替我的代码:

def self.find_first_by_auth_conditions(warden_conditions)
    conditions = warden_conditions.dup
    if login = conditions.delete(:login)
      if login.start_with?('+')
        where(["phone = :value AND phone_confirm = :phone_confirm", { value: login.downcase, phone_confirm: true }]).first
      else
        where(["lower(email) = :value", { value: login.downcase }]).first
      end
    else
      where(conditions).first
    end
  end

答案 1 :(得分:1)

attr_accessor :signin为您的班级实例定义了一个访问者。

问题是您尝试在类方法的范围内访问它,因此未定义。您需要的功能是基于两个部分执行查询:

  • the warden_conditions
  • 用户名的内容

我建议实施两个新范围(或一个)

scope :warden_stuff -> { |conditions| where(conditions) } # which can be omitted
scope :user_stuff -> do |user| 
  where(["lower(username) = :value OR lower(email)= :value",
         { :value => user.downcase }])
end

并将您的方法实现为

def self.find_first_by_auth_conditions(warden_conditions, user)
  warden_stuff(warden_conditions).user_stuff(user).first
  # or where(warden_conditions).user_stuff(user).first
end

以便它可以用作
user = User.find_first_by_auth_conditions(the_conditions.dup, a_user)

答案 2 :(得分:1)

通过&#34;学习设计Rails&#34;时,我遇到了完全相同的问题。电子书。

<强>问题

singin实际上是一个未定义的局部变量,即被调用的方式。

<强>解决方案

warden_conditions是包含登录密钥的哈希。使用此哈希而不是局部变量。正确的代码如下:

def self.find_first_by_auth_conditions(warden_conditions)
    where(["lower(username) = :value OR lower(email) = :value", { :value => warden_conditions[:signin].downcase }]).first
end

<强>通知: 我删除了第一个where方法,因为signin不是数据库中的列。所以,我认为调用第一个where方法是没有意义的。

我还删除了conditions = warden_conditions.dup,因为不需要.dup(复制) warden_conditions 哈希,因为在这种特殊情况下无需担心他的保留。 / p>

但要小心,如果通过warden_conditions哈希传递多个参数,则需要保留第一个参数,然后需要复制哈希,以便删除signin键。然后使用第二个位置备份signin密钥。

对我而言,这完美无缺。