2012-01-25 13 views
1

Привет У меня есть что-то вроде: на следующиеРуби 1.9.2: Как изменить масштаб/связывание блока

class TrialRequest 

    attr_accessor :trial_email 

    def initialize(email) 
    @trial_email = email 
    puts "Trial_email: #{trial_email}" 
    end 

    def create 
    @email = ::Gmail.connect!(gmail_name, gmail_password) do |gmail| 
     email = gmail.compose do 
     to '[email protected]' 
     from trial_email 
     subject trial_email 
     text_part do 
      content_type 'text/html; charset=UTF-8' 
      body 'Sign me up.' 
     end 
     end 
     #binding.pry 
     gmail.deliver!(email) 
    end 
    end 
end 

Проблема заключается в том, что внутри блока создания сообщения trial_email не определен:

NameError: undefined local variable or method `trial_email' for #<Mail::Message:0x0000000431b830> 

Является ли это проблемой Ruby 1.9 или проблемой gmail gem?

Как мне сделать этот метод «видимым»/в рамках блока компоновки?

Обновление: Это проблема/особенность gmail gem - ruby ​​1.9 блоков изменились, но это не так! В дополнении к принятому ответу, еще один обходной путь, чтобы передать данные в качестве параметра метода:

def create(trial_email) 
    ... 
end 

ответ

4

Похож вопросом GMail мне. Внутри блоков, self будет какой-то объект из драгоценного камня GMail, так что вы можете иметь to, from и аналогичные DSL-тонкости. Вы должны быть в состоянии поставить self.trial_email в локальную переменную, а затем получить доступ, что внутри блоков:

email_address = self.trial_email 
@email = ::Gmail.connect!(gmail_name, gmail_password) do |gmail| 
    email = gmail.compose do 
    to '[email protected]' 
    from email_address 
    subject email_address 
    #... 
+0

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

+0

Это не проблема, это ограничение 'instance_eval', не так ли? –

+0

@Hedgehog: Более или менее да, параметр заменяет локальную переменную 'email_address'. –

0

Вы ожидаете (как вы имеете право), что блок должен сохранять значение себе, как это обычно делает. Похоже, что gmail gem использует здесь instance_exec, что позволяет изменять значение self для блока на экземпляр Mail::Message (поэтому вы можете звонить to и from в этот блок, хотя вы не определяете такие методы)

В то время как instance_exec удобен для создания прекрасных DSL, это не без его недостатков. Локальная переменная область не влияет, так что вы можете хранить либо trial_email или self в локальной переменной до блока, а затем использовать эту локальную переменную внутри блока

0

Проблема в том, что блок вы передаете compose метод позже принят в Mail.new и, наконец, к Message.new (если я проследил цепь правильно), а затем этот блок оценивается как тот here:

instance_eval(&block) 

Как это выполняется внутри initialize метода другого объекта (экземпляр Message класса), вы не иметь доступ к атрибутам вашего TrialRequest объект.

Вы можете сделать то же самое, не имея каких-либо проблем, как, что:

email = gmail.compose 
email.to = '[email protected]' 
email.from = trial_email 
email.subject = trial_email 

email.text_part do 
    content_type 'text/html; charset=UTF-8' 
    body 'Sign me up.' 
end 
Смежные вопросы