1

ActiveRecordモデルにプログラムでaround_update/コールバックを追加するライブラリを作成しようとしています。around_destroy

したがって、通常のモデルは次のようになり、期待どおりに機能します。

class User < ActiveRecord::Base
  around_update :test_update

  def test_update
    Rails.logger.debug "test_update"
    yield
    Rails.logger.debug "Finished test_update"
  end
end

u=User.last
u.name = 'something'
u.save

######### output (as expected):
# test_update
# Finished test_update

私の小さなライブラリ(明らかにスケルトンだけ)は次のようになります。

# A module for creating around callbacks in a model
module Piddle
  module TimelineFor
    def self.included(klass)
      klass.send(:extend, ClassMethods)
    end

    module ClassMethods
      def timeline_for(event, opts={})
        method_name = :"timeline_for_#{event.to_s}"
        define_method(method_name) do |&block|
          Rails.logger.debug method_name.to_s
          yield block
          Rails.logger.debug "After yield in #{method_name.to_s}"
        end

        send(:around_update, method_name)
      end
    end
  end
end

これは、timeline_for_updateメソッドを追加し、それをaround_updateイベントのコールバックにするtimeline_forメソッドを定義しました。そして、私が使用したいユーザーモデルはこれです:

# second version of the User model using Piddle to create the callback
require 'piddle/piddle'

class User < ActiveRecord::Base
  include Piddle::TimelineFor

  timeline_for :update
end

u=User.last
u.name = 'gfgfhfhfgh'
u.save

出力で私は見る

timeline_for_update
LocalJumpError: no block given (yield)
from /vagrant/lib/piddle/piddle.rb:13:in `block in timeline_for'

最初の出力行は、メソッドが呼び出されているが、ブロックが渡されていないことを示しています。

アイデアや代替の実装はありますか?

4

2 に答える 2

3

yield問題は、から呼び出す場合、rubyは、レールが渡されたブロックではなく、define_method渡された(存在しない)ブロックに譲ろうとしていると解釈することです。timeline_fortimeline_for_foo

あなたはあなたblockに渡されているので、あなたはそれを呼び出すことができます:

def timeline_for event
  method_name = "timeline_for_#{event}"
  define_method method_name do |&block|
    ActiveRecord::Base.logger.debug "before #{method_name} yield" 
    block.call
    ActiveRecord::Base.logger.debug "after #{method_name} yield" 
  end
  send :around_update, method_name.to_sym #must use a symbol here
end
于 2012-09-05T21:08:34.113 に答える
0

そのようなものを定義したい場合。アクティブサポートの懸念事項をご覧ください。

定義自体でsendを使用する代わりに、クラスでaround-filterを呼び出す必要があると思います。

http://apidock.com/rails/ActiveSupport/Concern

于 2012-09-05T18:45:28.833 に答える