红宝石变量跨范围 [英] ruby variable scoping across classes

查看:68
本文介绍了红宝石变量跨范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

RuNubie在这里.我有一个使用net/IMAP库登录gmail的类Login.发生的事情是我创建了该类的新实例,例如:

RuNubie here. I've got a class Login that logs into gmail using the net/IMAP library. What is happening is that I create a new instance of that class, such as:

a = Login.new("username", "gmail.com", "passw")

然后,我正在研究将对邮箱进行一些填充"的其他类.问题在于,我在登录"中定义的@imap变量似乎已经消失了(由于我认为是范围界定).

Then, I'm working on other classes that will do some "stuff" with the mailbox. The problem is that the @imap variable I've defined in Login seems to have disappeared (due to scoping I assume).

这是在登录类中声明@imap的方式: @imap = Net::IMAP.new('imap.gmail.com',993,true,nil,false)

This is how @imap is declared in Login class: @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时:

...returns an error. These are the two errors I've gotten while playing around with this. The first one is when I use imap, the second one is when I try @imap:

NameError: undefined local variable or method `imap' for #<Object:0x10718d2a8>
NoMethodError: undefined method `search' for nil:NilClass

处理这种情况的最佳实践是什么?是在创建Net :: IMAP的新实例的同一类中定义执行填充"的方法的唯一解决方案吗?将@imap声明为全局变量$imap是不好的做法吗?如此困惑,我敢打赌答案也非常简单和明显,但我只是没有看到它.谢谢!

What are the best practices for dealing with a situation like this? Is the only solution to define my methods that do "stuff" in the same class where I'm creating the new instance of Net::IMAP? Is declaring @imap as a global variable $imap a bad practice? So confused, I bet the answer is very simple and obvious too, but I'm just not seeing it. Thanks!

推荐答案

此:

@received_today = imap.search(["SINCE", @today.strftime("%d-%b-%Y")]).count.to_s

无效,因为那时候范围内没有imap,因此您会收到NameError.像这样尝试时:

won't work because, well, there is no imap in scope at that point and so you get a NameError. When you try it like this:

@received_today = @imap.search(["SINCE", @today.strftime("%d-%b-%Y")]).count.to_s

之所以会出现NoMethodError,是因为实例变量(例如@imap)在首次使用时会自动创建并初始化为nil.您真正的@imap在另一个对象中,因此您无法在其他任何地方将其称为@imap.

You get a NoMethodError because instance variables, such as @imap, are automatically created at first use and initialized as nil. Your real @imap is in another object so you can't refer to it as @imap anywhere else.

我认为您想要一个更像这样的结构:

I think you want a structure more like this:

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保留在用户内部,并通过提供简单的访问器方法让其他对象使用它.

Keep your Net::IMAP localized inside your User and let other objects use it by providing a simple accessor method.

哦,这个全球性的$imap想法,我只是假装我没有看到,因为全球性几乎总是一个非常糟糕的想法.

Oh and that global $imap idea, I'll just pretend I didn't see that as globals are almost always a really bad idea.

这篇关于红宝石变量跨范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆