This is a follow up question to: ruby variable scoping across classes. The solution makes sense to me conceptually, but I can’t get it to work. Thought maybe with more code someone could help me.
I have a class Login that declares a new IMAP class, authenticates, and picks a mailbox.
I then am trying to create a separate class that will “do stuff” in the mailbox. For example, calculate the number of emails received. The problem is that the @imap instance of Net::IMAP doesn’t pass from the Login class to the Stat class — I’m getting no method errors for imap.search in the new class. I don’t want to re-log in and re-authenticate each time I need to “do some stuff” with the mailbox. I’m trying to implement the solution in the other thread, but can’t seem to get it to work.
Here’s the Login class:
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
I want to be able to say:
Login.new("user", "domain", "pass").mailbox("in")
and then something like:
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
And be able to call
Stat.new.received_today and have it not throw a “no method search” error. Again, the other question contains pseudo_code and a high level explanation of how to use an accessor method to do this, but I can’t implement it regardless of how many hours I’ve tried (been up all night)…
All I can think is that I am doing this wrong at a high level, and the stat calculation needs to be a method for the Login class, not a separate class. I really wanted to make it a separate class, however, so I could more easily compartmentalize…
Thanks!
OK — After much head banging on the wall, I got this to work.
Added these three methods to class Login:
Changed class Stat to:
Now this actually works, and doesn’t say undefined method
searchorimap:I’m pretty sure there is a way to use attr_accessor to do this as well, but couldn’t figure out the syntax. Anyway, this works and enables me to use the @imap var from class Login in class Stat so I can write methods to “do_stuff” with it. Thanks for the help and please don’t hesitate to tell me this is horrible Ruby or not best practices. I’d love to hear the Ruby way to accomplish this.
Edit for
attr_accessororattr_readeruse:Just add it to class Login and then can say
login.imap.search#stuffinclass Statwith no problem.