5

私は ActiveAttr を使用しています。これにより、ブロックオプションを使用して初期化することができます。

person = Person.new() do |p|
  p.first_name = 'test'
  p.last_name = 'man'
end

ただし、ActiveAttr::Model を含む特定のクラスでは、ブロックを別の用途に使用したいので、この機能をバイパスしたいと考えています。だからここに行きます:

class Imperator::Command
 include ActiveAttr::Model
end


class MyCommand < Imperator::Command

  def initialize(*args, &block)
    @my_block = block

    super(*args)
  end
end

ブロックがまだチェーンを通過し、最終的に ActiveAttr 内で次のコードが実行されるため、これは惨めに失敗します。

def initialize(*)
  super
  yield self if block_given?
end

したがって、私の呼び出しが次のようになっている場合:

MyCommand.new() { |date| date.advance(month: 1) }

次のように失敗します。

NoMethodError: undefined method `advance' for #<MyCommand:0x007fe432c4fb80>

MyCommand にはメソッド :advance がないため、MyCommand の呼び出しは明らかに失敗します。

superだから私の質問はこれです.ブロックがオーバーライドされたイニシャライザより先に移動しないように、再度呼び出す前にメソッドシグネチャからブロックを削除する方法はありますか?

4

2 に答える 2

12

試す

super(*args,&nil)

&はrubyにブロックとしてnilを使用させ、rubyはこれがブロックなしを意味することを理解するのに十分賢いようです。

于 2012-05-10T20:07:43.457 に答える
0

これは確かに巧妙なトリックですが、ActiveAttr::Model モジュールを直接使用せず、代わりに必要なモジュールのみを含めることをお勧めします。

それよりも

class Imperator::Command
  include ActiveAttr::Model
end

行う

class Imperator::Command
  include BasicModel
  # include BlockInitialization
  include Logger
  include MassAssignmentSecurity
  include AttributeDefaults
  include QueryAttributes
  include TypecastedAttributes

  def initialize(*args, &block)
    @my_block = block
    super(*args)
  end
end

ActiveAttr::Model の分解ビューが実行されていることを確認したら、実際には望ましくないことが他にもある可能性があります。その場合は、単純にインクルードを省略してください。その意図は、モデル構築へのアラカルト アプローチを提供することでした。

于 2012-05-28T20:01:17.373 に答える