2011-05-12 66 views
2

我想序列化一個Mail::Message對象以便將其存儲在數據庫中並稍後發送。 我第一次嘗試是使用內置的ActiveRecord的serialize方法是這樣的:Rails 3:郵件::郵件不能在序列化後傳遞

class Email < ActiveRecord::Base 
    serialize :mail 

    # ... 

end 

不幸的是,試圖保存記錄導致異常

> foo.save 
ArgumentError: wrong number of arguments (1 for 0) 
from /home/akrueger/.rvm/gems/ruby-1.9.2-p180/gems/mail-2.2.19/lib/mail/message.rb:1714:in `to_yaml' 
from /home/akrueger/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:55:in `accept' 
from /home/akrueger/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:36:in `<<' 
from /home/akrueger/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/psych.rb:165:in `dump' 
from /home/akrueger/.rvm/gems/ruby-1.9.2-p180/gems/activerecord-3.0.7/lib/active_record/base.rb:1720:in `block in arel_attributes_values' 
    (...) 

所以我乾脆創建一個自定義訪問使用Mail::Messageto_yaml/from_yaml功能。但現在我經歷了這種奇怪的行爲:

mail_original = UserMailer.user_welcome_email(@user) 
=> #<Mail::Message:93415800, Multipart: false, Headers: <From: (...) >, <To: (...) >, <Subject: (...) >, <Mime-Version: 1.0>, <Content-Type: text/plain>> 
mail_clone = Mail::Message.from_yaml mail_original.to_yaml 
=> #<Mail::Message:92940980, Multipart: false, Headers: <Date: (...) >, <From: (...) >, <To: (...) >, <Message-ID: (...) >, <Subject: (...) >, <Mime-Version: 1.0>, <Content-Type: text/plain>, <Content-Transfer-Encoding: quoted-printable>> 
mail_original.deliver 
=> #<Mail::Message:93415800, Multipart: false, Headers: <Date: (...) >, <From: (...) >, <To: (...) >, <Message-ID: (...) >, <Subject: (...) >, <Mime-Version: 1.0>, <Content-Type: text/plain>, <Content-Transfer-Encoding: quoted-printable>> 
mail_clone.deliver 
Errno::ECONNREFUSED: Connection refused - connect(2) 
from /home/akrueger/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/net/smtp.rb:546:in `initialize' 
from /home/akrueger/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/net/smtp.rb:546:in `open' 
from /home/akrueger/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/net/smtp.rb:546:in `tcp_socket' 
from /home/akrueger/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/net/smtp.rb:555:in `block in do_start' 
from /home/akrueger/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/timeout.rb:57:in `timeout' 
from /home/akrueger/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/timeout.rb:87:in `timeout' 
from /home/akrueger/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/net/smtp.rb:555:in `do_start' 
from /home/akrueger/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/net/smtp.rb:525:in `start' 
from /home/akrueger/.rvm/gems/ruby-1.9.2-p180/gems/mail-2.2.19/lib/mail/network/delivery_methods/smtp.rb:128:in `deliver!' 
from /home/akrueger/.rvm/gems/ruby-1.9.2-p180/gems/mail-2.2.19/lib/mail/message.rb:1989:in `do_delivery' 
from /home/akrueger/.rvm/gems/ruby-1.9.2-p180/gems/mail-2.2.19/lib/mail/message.rb:232:in `deliver' 
from (irb):68 
from /home/akrueger/.rvm/gems/ruby-1.9.2-p180/gems/railties-3.0.7/lib/rails/commands/console.rb:44:in `start' 
from /home/akrueger/.rvm/gems/ruby-1.9.2-p180/gems/railties-3.0.7/lib/rails/commands/console.rb:8:in `start' 
from /home/akrueger/.rvm/gems/ruby-1.9.2-p180/gems/railties-3.0.7/lib/rails/commands.rb:23:in `<top (required)>' 
from script/rails:6:in `require' 
from script/rails:6:in `<main>' 

任何想法如何解決這個問題?爲什麼將對象序列化爲yaml使Message對象無法投遞?有沒有其他方法可以正確序列化Message對象以便稍後發送它?

+0

找到了解決辦法:增加'的ActionMailer :: Base.wrap_delivery_behavior mail_clone '確保'mail_clone'的傳遞設置是正確的。我會盡快將它作爲答案發布。 – Andreas 2011-05-12 23:49:51

回答

0

指定類名幫助嗎?

serialize :mail, 'Mail::Message' 
+0

不幸的不是。我不得不將它改成'serialize:mail,Mail :: Message',並將列的默認值設置爲NULL,但是它只是引發了與第一個描述相同的異常('ArgumentError:錯誤的參數數量(1代表0)',在'to_yaml'中) – Andreas 2011-05-12 18:58:31

+0

如果我是你(不知道你的業務需求),我只需將郵件對象的屬性存儲爲一個序列化數組,然後在需要稍後實際發送郵件時創建一個新的郵件對象。 – twmills 2011-05-12 19:05:05

+0

感謝您的建議。如果沒有其他的幫助,我可能會聽從你的建議。不過,我想知道是否會有更多的「有問題的」解決方案。 – Andreas 2011-05-12 20:32:46

3

我意識到mail_clone對象沒有適當的傳送設置,這引起了deliver調用失敗。通過Rails源代碼瀏覽,我發現了以下解決方案:

mail_clone = Mail::Message.from_yaml mail_original.to_yaml 
ActionMailer::Base.wrap_delivery_behavior mail_clone 
mail_clone.deliver 

所以這可能是一個辦法來序列化對象Mail::Message

class Email < ActiveRecord::Base 
    def mail 
    @mail_cached || begin 
     m = Mail::Message.from_yaml(self.read_attribute :mail) 
     ActionMailer::Base.wrap_delivery_behavior m 
     m 
    rescue 
     nil 
    end 
    end 

    def mail=(val) 
    @mail_cached = val 
    write_attribute :mail, val.to_yaml 
    end 

    # ... 
end 
+0

這幫助我序列化Mail :: Message。只用'serialize:mail,Mail :: Message',我得到錯誤'TypeError:allocator undefined for Encoding'。我使用Rails 4.1 – Mika 2014-04-09 05:21:12