область видимости переменной ruby ​​по классам - PullRequest
1 голос
/ 02 марта 2012

RuNubie здесь. У меня есть класс Login, который входит в Gmail, используя библиотеку net/IMAP. Происходит следующее: я создаю новый экземпляр этого класса, например:

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

Затем я работаю над другими классами, которые будут делать "вещи" с почтовым ящиком. Проблема в том, что переменная @imap, которую я определил при входе в систему, кажется, исчезла (из-за предполагаемой области видимости).

Вот как @imap объявляется в классе Login: @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 плохой практикой? Так запутанно, держу пари, что ответ очень простой и очевидный, но я просто не вижу его. Спасибо!

Ответы [ 2 ]

1 голос
/ 02 марта 2012

более короткий способ определить переменную imap в классе User, который в значительной степени совпадает с тем, что выложил mu:

class User
   def imap
      @imap ||= Net::IMAP.new...
   end
end
1 голос
/ 02 марта 2012

Это:

@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

KeepВаш Net::IMAP локализован внутри вашего Пользователя и позволяет другим объектам использовать его, предоставляя простой метод доступа.

О, и эта глобальная идея $imap, я просто притворюсь, что не видел этого, поскольку глобальныепочти всегда очень плохая идея.

...