從超

2012-05-10 27 views
5

一個電話我與ActiveAttr工作,讓你擦洗塊通過塊選擇好的初始化:從超

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

然而,在一個特定的類,包括ActiveAttr ::型號,我想繞過這個功能,因爲我想用塊來做別的事情。所以在這裏,我們去:

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沒有方法:提前調用MyCommand顯然失敗。

所以我的問題是,有沒有一種方法可以在我再次調用super之前從方法簽名中刪除塊,以便該塊不會比我的重寫初始化程序更遠?

回答

12

嘗試

super(*args,&nil) 

的&,使紅寶石使用零作爲塊和紅寶石似乎足夠聰明,知道這意味着沒有塊。

+0

完美,我不知道爲什麼我沒有想到這一點。謝謝! – TheDelChop

+1

這一定是個紅寶石bug,雖然它仍然存在於ruby 2.0中 – Mikey

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 ::模型的分解圖做有可能是你真的不想其他的事情。在這種情況下,只需簡單地省略包含即可。目的是提供一種點菜方式來建模。