首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >插件内部的混叠激活方法

插件内部的混叠激活方法
EN

Stack Overflow用户
提问于 2009-09-03 10:00:06
回答 1查看 286关注 0票数 2

我试图用以下方式编写一个插件,在ActiveRecord中对某些方法进行别名:

代码语言:javascript
复制
class Foo < ActiveRecord::Base
  include MyOwnPlugin
  acts_as_my_own_plugin :methods => [:bar]

  def bar
    puts 'do something'
  end
end

插件内部:

代码语言:javascript
复制
module MyOwnPlugin
  def self.included(base)    
    base.class_eval do
      extend ClassMethods
    end
  end
  module ClassMethods
    def acts_as_my_own_plugin(options)
      options[:methods].each do |m|
        self.class_eval <<-END
          alias_method :origin_#{m}, :#{m}
        END
      end
    end
  end
end

这种方法无法工作,因为在运行#acts_as_my_own_plugin时,还没有定义Foo#bar,因为它还没有运行。

bar acts_as_my_own_plugin:=> :bar 之后,bar函数声明将起作用。然而,这并不好看。

我希望能够像大多数插件一样将acts_as_my_own_plugin放在类定义的顶部。

是否有其他方法来满足这一条件?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2009-09-03 12:16:12

永远记住: Ruby中几乎所有的东西都有回调。

尝试以下几点:

代码语言:javascript
复制
module MyOwnPlugin
  def self.included(base)
    base.extend(ClassMethods)
  end

  module ClassMethods
    # gets called from within the models
    def acts_as_my_own_plugin(options)
      # store the list of methods in a class variable and symbolize them
      @@methods = []
      options[:methods].each { |method| @@methods << method.to_sym }
    end

    # callback method. gets called by ruby if a new method is added.
    def method_added(name_of_method)
      if @@methods.include?(name_of_method)
        # delete the current method from our @@methods array
        # in order to avoid infinite loops
        @@methods.delete(name_of_method)
        #puts "DEBUG: #{name_of_method.to_s} has been added!"

        # code from your original plugin
        self.class_eval <<-END
          alias_method :origin_#{name_of_method}, :#{name_of_method}
          def #{name_of_method}
            puts "Called #{name_of_method}"
            origin_#{name_of_method}
          end
        END

      end
    end
  end
end

# include the plugin module in ActiveRecord::Base
# in order to make acts_as_my_own_plugin available in all models 
ActiveRecord::Base.class_eval do
  include MyOwnPlugin
end

# just call acts_as_my_own_plugin and define your methods afterwards
class Foo < ActiveRecord::Base
  acts_as_my_own_plugin :methods => [:bar]

  def bar
    puts 'do something'
  end
end

我希望这是有用的。你可以用Ruby做的疯狂的事情就是太酷了;)

如果希望在调用acts_as_my_own_plugin之前和之后定义方法,则需要再次更改代码以允许此操作。然而,困难的部分已经完成。

免责声明:这已经用Ruby1.8.7进行了测试。可能不适用于Ruby1.9.*。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1372515

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档