ruby-on-rails – Ruby:Mixin,它添加了动态实例方法,其名称是使
我有以下内容:
module Thing def self.included(base) base.send :extend,ClassMethods end module ClassMethods attr_reader :things def has_things(*args) options = args.extract_options! # Ruby on Rails: pops the last arg if it's a Hash # Get a list of the things (Symbols only) @things = args.select { |p| p.is_a?(Symbol) } include InstanceMethods end end module InstanceMethods self.class.things.each do |thing_name| # !!! Problem is here,explaination below define_method "foo_for_thing_#{thing_name}" do "bar for thing #{thing_name}" end end end end 在另一个混合了Thing模块的类中: class Group has_things :one,:two,:option => "something" end 在类中调用has_things时,我希望动态的“foo_for_thing_one”和“foo_for_thing_two”实例方法可用.例如: @group = Group.new @group.foo_for_thing_one # => "bar for thing one" @group.foo_for_thing_two # => "bar for thing two" 但是,我收到以下错误: `<module:InstanceMethods>': undefined method `things' for Module:Class (NoMethodError) 我意识到上面指出的问题行中的“self”(InstanceMethods模块的第一行)引用了InstanceMethods模块. 如何引用“things”类方法(在此示例中返回[:one,:two]),以便我可以遍历并为每个方法创建动态实例方法?谢谢.或者如果您有其他建议来完成此操作,请告诉我. 解决方法
快速回答:
将InstanceMethods的内容放在has_things方法定义中,然后删除InstanceMethods模块. 更好的答案: 您对InstanceMethods-ClassMethods反模式的使用在这里尤其没有根据,因此货物结果增加了您对范围和上下文的困惑.做最简单的事可能有用.没有批判性思维,不要复制别人的代码. 您需要的唯一模块是ClassMethods,它应该被赋予一个有用的名称,不应该包含在内,而是用于扩展您要授予has_things功能的类.这是最简单的事情: module HasThings def has_things(*args) args.each do |thing| define_method "thing_#{thing}" do "this is thing #{thing}" end end end end class ThingWithThings extend HasThings has_things :foo end ThingWithThings.new.thing_foo # => "this is thing foo" 只在需要时添加复杂性(选项提取,输入规范化等).代码及时,不仅仅是以防万一. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |