2012-03-02 1 views
1

Это следующий вопрос: ruby variable scoping across classes. Решение имеет смысл для меня концептуально, но я не могу заставить его работать. Думал, может быть, с большим количеством кода кто-то мог бы мне помочь.Реализация методов доступа в Ruby

У меня есть класс Login, который объявляет новый класс IMAP, аутентифицирует и выбирает почтовый ящик.

Я пытаюсь создать отдельный класс, который будет «делать вещи» в почтовом ящике. Например, подсчитайте количество полученных электронных писем. Проблема в том, что экземпляр @imapNet::IMAP не переходит из класса Login в класс Stat - я не получаю ошибок метода для imap.search в новом классе. Я не хочу повторно регистрироваться и повторно аутентифицироваться каждый раз, когда мне нужно «делать что-то» с почтовым ящиком. Я пытаюсь реализовать решение в другом потоке, но не могу заставить его работать.

Вот Login класс:

class Login 
    def initialize(user, domain, pass) 
    @username = user 
    @domain = domain 
    @pass = pass 

    #check if gmail or other domain 
    gmail_test = @domain.include? "gmail.com" 
    if gmail_test == true 
     @imap = Net::IMAP.new('imap.gmail.com',993,true,nil,false) 
     @imap.login(@username + "@" + @domain, @pass) 
    else 
     @imap = Net::IMAP.new("mail." + @domain) 
     @imap.authenticate('LOGIN', @username + "@" + @domain, @pass) 
    end 
    return self 
    end 

    #enable mailbox select  
    def mailbox(box) 
    @mailbox = box 
    @mailbox_array = @imap.list('','*').collect{ |mailbox| mailbox.name } #create array of mailboxes 
    @matching_mailbox = @mailbox_array.grep(/#{@mailbox}/i) #search for mailbox along list 
    if @matching_mailbox.empty? == true #if no results open INBOX 
     @mailbox = "INBOX" 
     @imap.examine(@mailbox) 
    else 
     @imap.examine(@matching_mailbox.first.to_s) #if multiple results, select first and examine 
     @mailbox = @matching_mailbox.first.to_s 
    end 
    return self 
    end  
end 

Я хочу, чтобы иметь возможность сказать:

Login.new("user", "domain", "pass").mailbox("in") 

и затем что-то вроде:

class Stat 
    def received_today() 
    #emails received today 
    @today = Date.today 
    @received_today = @imap.search(["SINCE", @today.strftime("%d-%b-%Y")]).count.to_s 
    puts @domain + " " + @mailbox.to_s + ": " + @received_today + " -- Today\n\n" #(" + @today.strftime("%d-%b-%Y") + ") 
    end 
end 

И быть в состоянии назвать

Stat.new.received_today и не вызывать ошибку «поиск метода». Опять же, другой вопрос содержит pseudo_code и объяснение на высоком уровне о том, как использовать метод доступа для этого, но я не могу его реализовать независимо от того, сколько часов я пробовал (всю ночь) ...

Все, что я могу думать, это то, что я делаю это неправильно на высоком уровне, а вычисление stat должно быть методом для класса Login, а не для отдельного класса. Я действительно хотел сделать это отдельным классом, тем не менее, поэтому я мог бы более легко разделять ... Спасибо!

+0

Я думаю, что у вас есть достаточно фундаментальное непонимание того, что переменная экземпляра. Каждый экземпляр объекта имеет совершенно отдельный набор переменных экземпляра. –

+1

Итак, нет способа передать экземпляр класса Login в метод класса Stat в качестве аргумента? Я согласен, что это похоже на фундаментальное недоразумение на моей стороне. Похоже, у меня должен быть только один класс, с методом входа в систему, методом почтового ящика и buch методов «делать вещи». Это лучшая практика? – krapdagn

ответ

0

OK --- После многого удара головой на стене, я получил это, чтобы работать.

Добавлен эти три метода в классе Логин:

def get_imap 
    @imap 
    end 
    def get_domain 
    @domain 
    end 
    def get_mailbox 
    @mailbox 
    end 

Изменен класс Stat к:

class Stat 
     def received_today(login) 
      #emails received today 
     @today = Date.today 
     @received_today = login.get_imap.search(["SINCE", @today.strftime("%d-%b-%Y")]).count.to_s 
     # puts @received_today 
     puts login.get_domain + " " + login.get_mailbox.to_s + ": " + @received_today + " -- Today\n\n" 
     end 
     end 

Теперь это на самом деле работает, и не говорит, не определено методом search или imap:

b = Login.new("user", "domain", "pass").mailbox("box") 
c = Stat.new 
c.received_today(b) 

Я уверен, что есть способ использования attr_accessor чтобы сделать это, но не смог понять синтаксис. В любом случае, это работает и позволяет мне использовать @imap var из класса Login в классе Stat, чтобы я мог писать с ним методы do_stuff. Спасибо за помощь и, пожалуйста, не стесняйтесь сказать мне, что это ужасно Ruby или не лучшие практики. Я бы хотел услышать рубиновый способ добиться этого.

Edit для attr_accessor или attr_reader использования:

Просто добавьте его в класс Логин и тогда можно сказать, login.imap.search#stuff в class Stat без проблем.

0

Другой подход, который работает и не требует определения методов get_var:

b.instance_variable_get("@imap") # where b = class instance of login