2014-11-16 16 views
7

Bir yakut modülünü eklerken argüman kullanmanın bir yolu var mı? Birçok sınıfta bulunan bir modül Assetable var. Ben anında attr_accessor's üretmek mümkün olmak istiyorum.Ruby on Rails, argümanlar olan bir modül de dahil olmak üzere

module Assetable 
    extend ActiveSupport::Concern 

    included do 
    (argument).times do |i| 
     attr_accessor "asset_#{i}".to_sym 
     attr_accessible "asset_#{i}".to_sym 
    end 
    end 
end 

cevap

13

Modülü eklerken argümanları iletmenin bir yolu yoktur. o da ActiveSupport::Concern tarafından kullanıldığından bir endişe içinde included yöntemi geçersiz kılmak için

module Assetable 
    extend ActiveSupport::Concern 
    module ClassMethods 
    def total_assets(number) 
     number.times do |i| 
     attr_accessor "asset_#{i}" 
     attr_accessible "asset_#{i}" 
     end 
    end 
    end 
end 

class C 
    include Assetable 
    total_assets 3 
end 

o = C.new 
o.asset_2 = "Some value." 
o.asset_2 #=> "Some value." 

Ayrıca dikkatli olun: iyi gelecek şey sonradan gerekenleri oluşturmanıza olanak sağlayan bir sınıf yöntemi tanımlamak olacaktır. Doğru başlatmayı sağlamak için super'u geçersiz kılma yöntemiyle çağırmalısınız.

+0

Teşekkürler, nereye süper diyorsunuz? – user3868832

+0

Sadece söz konusu uygulamada bir "dahil" kanca tanımlarsanız, bu uygulamada geçerli değildir. –

4

Bağımsız değişkenleri bir modüle iletemezsiniz. Aslında, bir iletinin gönderilmesi dışında bağımsız değişkenleri iletemezsiniz.

Yani, bir mesaj göndermeyi kullanmak zorunda:

module Kernel 
    private def Assetable(num) 
    @__assetable_cache__ ||= [] 
    @__assetable_cache__[num] ||= Module.new do 
     num.times do |i| 
     attr_accessor :"asset_#{i}" 
     attr_accessible :"asset_#{i}" 
     end 
    end 
    end 
end 

class Foo 
    include Assetable 3 
end 

Not:. Zaten burada ActiveSupport::Concern gerekir neden görmedim, ama geri eklemek kolaydır Orada

+1

Teşekkürler, ben Gabriel de Oliveira'nın yanıtını uygulamıştım. Her çözümün profesyonelleri nelerdir? – user3868832

13

bir hiledir: bir modülden miras alan bir sınıf oluşturmak, böylece herhangi bir argümanı sınıf gibi bir modüle iletebilirsiniz.

class Assetable < Module 
    def initialize(num) 
    @num = num 
    end 

    def included(base) 
    num = @num 

    base.class_eval do 
     num.times do |i| 
     attr_accessor "asset_#{i}" 
     end 
    end 
    end 
end 

class A 
    include Assetable.new(3) 
end 

a = A.new 
a.asset_0 = 123 
a.asset_0 # => 123 

bilgilerini http://kinopyo.com/en/blog/ruby-include-module-with-arguments de blogged bunu yararlı bulacağınızı umuyoruz.

+0

Lanet olsun, evlat! Güzel çözüm. – henrebotha