RuNubie点击此处。我有一个类Login
,它使用net/IMAP
库登录到gmail。正在发生的事情是,我创建了该类的一个新实例,例如:
a = Login.new("username", "gmail.com", "passw")
然后,我正在学习其他课程,这些课程将对邮箱做一些"事情"。问题是我在Login中定义的@imap
变量似乎已经消失了(我认为是由于作用域)。
以下是在Login类中声明@imap
的方式:@imap = Net::IMAP.new('imap.gmail.com',993,true,nil,false)
所以这个:
@today = Date.today
@received_today = imap.search(["SINCE", @today.strftime("%d-%b-%Y")]).count.to_s
返回一个错误。这是我在玩这个游戏时犯的两个错误。第一个是我使用imap
时,第二个是我尝试@imap
:时
NameError: undefined local variable or method `imap' for #<Object:0x10718d2a8>
NoMethodError: undefined method `search' for nil:NilClass
处理这种情况的最佳做法是什么?唯一的解决方案是在创建Net::IMAP的新实例的同一类中定义做"事情"的方法吗?将@imap
声明为全局变量$imap
是一种糟糕的做法吗?太困惑了,我敢打赌答案也很简单明了,但我就是看不出来。谢谢!
这:
@received_today = imap.search(["SINCE", @today.strftime("%d-%b-%Y")]).count.to_s
不会起作用,因为此时作用域中没有imap
,因此会得到NameError。当你这样尝试时:
@received_today = @imap.search(["SINCE", @today.strftime("%d-%b-%Y")]).count.to_s
您会得到一个NoMethodError,因为实例变量(如@imap
)在首次使用时会自动创建并初始化为nil
。你真正的@imap
在另一个对象中,所以你不能在其他地方把它称为@imap
。
我想你想要一个更像这样的结构:
class User
def imap
if(!@imap)
@imap = Net::IMAP.new('imap.gmail.com', 993, true, nil, false)
# and presumably an @imap.authenticate too...
end
@imap
end
end
class OtherOne
def some_method(user)
@today = Date.today
@received_today = user.imap.search(["SINCE", @today.strftime("%d-%b-%Y")]).count.to_s
end
end
将Net::IMAP
本地化到User中,并通过提供一个简单的访问器方法让其他对象使用它。
哦,还有全局$imap
的想法,我只是假装我没有看到,因为全局几乎总是一个非常糟糕的想法。
在User类中定义imap变量的一种较短方法,与mu发布的内容基本相同:
class User
def imap
@imap ||= Net::IMAP.new...
end
end