5

I'm working with ActiveAttr which gives you that nice initialize via block option:

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

However, in a specific class that include ActiveAttr::Model, I want to bypass this functionality since I want to use the block for something else. So here we go:

class Imperator::Command
 include ActiveAttr::Model
end


class MyCommand < Imperator::Command

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

    super(*args)
  end
end

This fails miserably, because the block still gets passed up the chain, and eventually inside of ActiveAttr, this code gets run:

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

So if my call looks like so:

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

it fails as follows:

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

since MyCommand has no method :advance it the call to MyCommand obviously fails.

So my question is this, is there a way that I can remove the block from the method signature before I call super again, so that the block travels no further than my overridden initializer?

user229044
  • 232,980
  • 40
  • 330
  • 338
TheDelChop
  • 7,938
  • 4
  • 48
  • 70

2 Answers2

12

Try

super(*args,&nil)

The & makes ruby use nil as the block and ruby seems smart enough to realise this means no block.

Frederick Cheung
  • 83,189
  • 8
  • 152
  • 174
0

That is certainly a neat trick, but a better approach would be to not use ActiveAttr::Model module directly and instead include only the modules you need.

Rather than

class Imperator::Command
  include ActiveAttr::Model
end

Do

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

Once you see the exploded view of ActiveAttr::Model is doing there may be other things you really don't want. In that case just simply omit the includes. The intention was to provide an à la carte approach to model constructing.

bpoweski
  • 56
  • 1
  • 4