3

ActiveRecord と Rails 3.2.3 で遅延ジョブ 3.0.2 を使用しています。has_secure_password mixin を使用する User モデルがあるため、パスワードは暗号化されてのみ保存されます。ここで、遅延ジョブを使用して、暗号化されていないパスワードのコピーを含むウェルカム メールを送信したいと考えています。

レコードを作成するとき、平文のパスワードは User#password にあります。しかし、遅延ジョブは、レコードの ID のみをシリアル化/逆シリアル化し、User.find(X) を実行してモデルの新しいインスタンスを作成するようです。このようにして、プレーンテキストのパスワードが失われ、ユーザーはメールで空のパスワードを受け取ります。

データベースに保存されていないカスタムの「仮想」属性もシリアル化/逆シリアル化するようにdelayed-jobに指示するにはどうすればよいですか?

これは遅延ジョブ 2.x のモンキー パッチで、問題なく動作しました。

class ActiveRecord::Base
  def self.yaml_new(klass, tag, val)
    klass.find(val['attributes']['id']).tap do |m|
      val.except("attributes").each_pair{ |k, v| m.send("#{k}=", v) }
    end
  rescue ActiveRecord::RecordNotFound
    raise Delayed::DeserializationError
  end
end

遅延ジョブ 3.x では機能しません。これに対する適切な解決策があることを願っているので、モンキー パッチを修正することにもあまり興味がありません。

4

1 に答える 1

2

遅延ジョブ 3.x でこれを行う最善の方法は、ActiveRecord クラスのいくつかのメソッドをオーバーライドしてから、Psych YAML デシリアライザーにシリアライズされたデータから ActiveRecord オブジェクトをロードさせることです。デフォルトでは、遅延ジョブは逆シリアル化された ID のみを使用し、DB から ActiveRecord オブジェクトをロードします。たとえば、ShipmentImport という ActiveRecord クラスがあり、'user_id' という名前の attr_accessor を遅延ジョブのシリアライゼーション/デシリアライゼーションで動作させたいとします。これが私がすることです。

ShipmentImport ActiveRecord クラスで、これを追加します。

def encode_with(coder)
  super
  coder['user_id'] = @user_id
end

def init_with(coder)
 super
  @user_id = coder['user_id']
  self
end

アプリケーションのイニシャライザで、ActiveRecord クラスにこれを追加します。

Psych.load_tags[['!ruby/ActiveRecord', ShipmentImport.name].join(':')] = ShipmentImport
于 2013-03-26T00:13:49.163 に答える