2015-01-12 4 views
14

Rails 4.2のdeliver_laterメソッドを使用して連絡先フォームを設定しようとしています。しかし、deliver_laterはオブジェクトを直列化しようとするたびに失敗するため、deliver_nowを動作させることしかできません。ここでRails 4.2:テーブルレスモデルでdeliver_laterを使用する

は私の設定です:

messages_controller.rb

class MessagesController < ApplicationController 
    def new 
    @message = Message.new 
    end 

    def create 
    @message = Message.new(params[:message]) 
    if @message.valid? 
     ContactMailer.contact_form(@message).deliver_later 
     redirect_to root_path, notice: "Message sent! Thank you for contacting us." 
    else 
     render :new 
    end 
    end 
end 

contact_mailer.rb

class ContactMailer < ApplicationMailer 
    default :to => Rails.application.secrets['email'] 

    def contact_form(msg) 
    @message = msg 
    mail(:subject => msg.subject, from: msg.email) 
    end 
end 

message.rb

class Message 
    include ActiveModel::Model 
    include ActiveModel::Conversion 

    ## Not sure if this is needed ## 
    include ActiveModel::Serialization 

    extend ActiveModel::Naming 

    attr_accessor :name, :subject, :email, :body 

    validates_presence_of :email, :body 
    validates_format_of :email, with: /\A([^\s]+)((?:[-a-z0-9]\.)[a-z]{2,})\z/i 
    validates_length_of :body, :maximum => 1000 

    def initialize(attributes = {}) 
     attributes.each { |name, value| send("#{name}=", value) } 
    end 

    ## Not sure if this is needed ## 
    def attribtues 
     {'name' => nil, 'subject' => nil, 'email' => nil, 'body' => nil} 
    end 
end 

ContactMailer.contact_form(@message).deliver_laterを呼び出すときに私が得るエラーは次のとおりです。

ActiveJob::SerializationError in MessagesController#create 

Unsupported argument type: Message 
Extracted source (around line #10): 
if @message.valid? 
    ContactMailer.contact_form(@message).deliver_later 
    redirect_to root_path, notice: "Message sent! Thank you for contacting us." 
else 
    render :new 

は、理想的には私は、これはバックグラウンドプロセスようにしたいと思います。私はすぐにSidekiqのようなものを追加する予定ですが、私はこのシリアル化の問題をあらかじめ解決しておくのが最善だと思います。

ご協力いただきましてありがとうございます。ありがとう:)

答えて

10

ActiveJob(これはdeliver_laterが代理するものです)でクラスを使用するには、そのIDでオブジェクトを一意に識別できる必要があります。さらに、デシリアライズ時にはIDで後でそれを見つける必要があります(メーラ/ジョブでは手動のデシリアライズは必要ありません)。

class Message 
    ... 
    include GlobalID::Identification 
    ... 

    def id 
    ... 
    end 

    def self.find(id) 
    ... 
    end 
end 

ActiveRecordこれらのメソッドを提供していますが、それを使用していないので、あなたはそれを自分で実装する必要があります。レコードを保存する場所は決まっていますが、正直言ってActiveRecordとその下のテーブルを使用する方が良いと思います。

+0

私はちょうど 'ActiveRecord'とその基礎を使用して終了しました。 – DaniG2k

+1

@ DaniG2kどのようにテーブルレスモデルでActiveRecordを使用しましたか? – Marklar

+1

@ Markl彼は彼が基礎となるテーブルを使用したと言っていると思います。 – Nick

0

AJに渡す前にオブジェクトをシリアル化し、メーラーで逆シリアル化する必要があります。

8

不要テーブルのActiveRecordでオブジェクトをバックアップまたは作成する必要がなくなり、簡単なソリューション:CONTACT_FORMメソッドにメッセージオブジェクトを渡すのではなく

は、またCONTACT_FORM法およびその後PARAMSメッセージを渡すことができそのメソッド内のMessageオブジェクトを初期化します。

これは、遅れた職員のメモリ空間でオブジェクトを初期化するため、テーブルを作成せずに問題を解決します。例えば

messages_controller.rb

MessagesController < ApplicationController 
    def new 
     @message = Message.new 
    end 

    def create 
     @message = Message.new(params[:message]) 

     if @message.valid? 
      ContactMailer.contact_form(params[:message]).deliver_later 
      redirect_to root_path, notice: "Message sent! Thank you for contacting us." 
     else 
      render :new 
     end 
    end 
end 

contact_mailer.rb

class ContactMailer < ApplicationMailer 
    default :to => Rails.application.secrets['email'] 

    def contact_form(msg_params) 
     @message = Message.new(msg_params) 
     mail(:subject => msg.subject, from: msg.email) 
    end 
end 
+0

これはすばらしい解決策です。ありがとうございました! –

+0

これはRails 5では動作しません: 'サポートされていない引数型:ActionController :: Parameters' – Vadim

2

今日は同様の問題を抱えていたし、次のようにそれを解決しました。

    • のRailsを

環境をハッシュに変換メーラー

  • にJSON刺さにJSON文字列を
  • パス、それをテーブルレスオブジェクトを変換5.0.2
  • messages_controller.rb

    class MessagesController < ApplicationController 
    
        # ... 
    
        def create 
        @message = Message.new(message_params) 
        if @message.valid? 
         ContactMailer.contact_form(@message.serialize).deliver_later 
         redirect_to root_path, notice: "Message sent! Thank you for contacting us." 
        else 
         render :new 
        end 
        end 
    
        # ... 
    end 
    

    contact_mailer.rb

    class ContactMailer < ApplicationMailer 
        default :to => Rails.application.secrets['email'] 
    
        def contact_form(message_json) 
        @message = JSON.parse(message_json).with_indifferent_access 
    
        mail(subject: @message[:subject], from: @message[:email]) 
        end 
    end 
    

    message.rb

    class Message 
        include ActiveModel::Model 
    
        attr_accessor :name, :subject, :email, :body 
    
        validates_presence_of :email, :body 
        validates_format_of :email, with: /\A([^\s]+)((?:[-a-z0-9]\.)[a-z]{2,})\z/i 
        validates_length_of :body, :maximum => 1000 
    
        # Convert an object to a JSON string 
        def serialize 
        ActiveSupport::JSON.encode(self.as_json) 
        end 
    end 
    

    これは誰にも役立つことを願っています。

    関連する問題