Tag: 元编程

元编程有副作用时如何重构?

我正在使用Ruby on Rails 3.2.9和Ruby 1.9.3-p125。 在我之前的问题之后,我最终得到了一个关于元编程自编码的acts_as_customizable插件的问题,因为相关的代码对其他类有副作用 ,而不是“充当可自定义的”。 总结一下这个问题:为Article模型“内部”(通过元编程)声明的acts_as_customizable方法为Comment模型添加了一个customize方法,为了节省时间,Rails不会在启动时加载所有这些类,使应用程序引发NoMethodError – undefined method ‘customize’ for # 直到加载Article类。 建议的解决方案是在Comment模型中的require_dependency ‘article’ ,但我正在寻找另一种方式(也许,更好的建议的方式)让应用程序正常工作,但没有任何问题像在这个问题中解释。 也就是说,我想保留一个*短代码**和相同的行为,但使用更“合适”的方式来制作东西,可能会改变类的加载过程或计划对整个代码进行大量重构,如果有必要的话。 我应该如何处理这种情况? 你有什么想法? 更新 :经过一些研究,我发现问题仅出现在开发模式中,因为config.cache_classes设置为false使得每个请求都要重新加载类。 注意 :我想指出元编程在我的案例中非常有用, Article和Comment类在我的“定制”概念方面彼此高度相关。 所以我想找到一个解决方案来缓解对基础行为的改变 。 *就我而言,元编程(即使它有副作用)使我避免了很多代码语句。

在代码的eval之间维护局部变量

考虑以下Ruby代码: class Foo def bar; 42; end def run(code1,code2) binding.eval(code1,’c1′) binding.eval(code2,’c2′) end end Foo.new.run “x=bar ; px”, “px” 目的是动态评估一些代码 – 它创建局部变量 – 然后运行可以访问这些变量的其他代码。 结果是: c2:1:in `run’: undefined local variable or method `x’ for # (NameError) 请注意,上述内容仅在eval突变绑定时才有效,只有在修改现有局部变量时才会这样做,而不会创建新变量。 我不一定需要(或想要)每次运行来改变外部绑定,我只需要能够访问先前的绑定以进行后续的代码评估。 我如何评估两个代码块并在它们之间维护局部变量? 对于好奇的,这个实际应用程序是一个自定义工具 ,可以执行脚本文件,然后放入REPL。 我希望REPL能够访问脚本文件创建的所有局部变量。

如何更改lambda的上下文?

如果您运行以下代码,则会出现错误。 class C def self.filter_clause param_1 puts param_1 yield # context of this param is class B end def hi “hello” end end class B def self.filter(value, lambda) code = lambda { filter_clause(value, &lambda) } C.instance_exec(&code) end filter(:name, ->{ hi }) end 错误是 NameError: undefined local variable or method `hi’ for B:Class from (pry):17:in `block […]

传递&:方法和:方法作为ruby中的函数参数之间的区别

我正在努力理解何时使用&符号将符号传递给表示方法的函数。 例如,如果我想计算范围1..10的总和,我可以执行以下操作: (1..10).inject(:+) 这最初让我相信,如果你想传递一个符号来定义一个方法,以便在函数中使用“Magically”,你可以将函数名称作为符号传递。 但后来我在rails中看到了这样的东西: total = Product.find(product_list).sum(&:price) 如果我理解正确,&:price与调用:price.to_proc相同。 我不明白上面的工作原理。

Ruby元编程:无法向模块发送方法

例如,我有以下自定义类和模块: module SimpleModule def hello_world puts ‘i am a SimpleModule method’ end def self.class_hello_world puts ‘i am a SimpleModule class method’ end end class SimpleClass def hello_world puts ‘i am SimpleClass method’ end def self.class_hello_world puts ‘i am a SimpleClass class method’ end end 我尝试使用方法send调用类和模块中的那些方法 SimpleClass.send(class_hello_world) # work SimpleClass.new.send(hello_world) # work SimpleModule.send(class_hello_world) # work SimpleModule.new.send(hello_world) […]

在别名实例方法时理解单例类

我正在使用Ruby 1.9.2和Ruby on Rails v3.2.2 gem。 我正在尝试以“正确的方式”学习元编程,此时我在RoR ActiveSupport::Concern模块提供的included do … end块中对实例方法进行别名: module MyModule extend ActiveSupport::Concern included do # Builds the instance method name. my_method_name = build_method_name.to_sym # => :my_method # Defines the :my_method instance method in the including class of MyModule. define_singleton_method(my_method_name) do |*args| # … end # Aliases the :my_method instance method in the […]

在Ruby模块中动态创建访问器

我在Ruby中有一个Config模块,我希望能够添加任意变量。 我使用method_missing和instance_variable_set创建了它,如下所示: module Conf #add arbitrary methods to config array def self.method_missing(m, *args) args = args.pop if args.length==1 instance_variable_set(“@#{m}”, args) end end 但是,我在动态创建访问器时遇到了麻烦。 当我尝试使用attr_accessor时如下: module Conf #add arbitrary methods to config array def self.method_missing(m, *args) args = args.pop if args.length==1 instance_variable_set(“@#{m}”, args) module_eval(“attr_accessor :#{m}”) end end 我得到以下内容: Conf :: s3_key(’1234ABC’)#Conf :: s3_key = nil 如果我尝试单独创建访问器: […]

在课堂上产生<<自我在课堂上的方法

我想创建一个类方法,它接受一个方法定义块并将其注入到类中。 现在, self确实是Tom对象,所以class << self这个class << self确实打开它,但是yield似乎不起作用。 我的理论知识不是很深,所以我不确定为什么这不起作用。 我可能会完全错误,所以请随意讨论替代方案。 class Tom < Person mega_methods do def hiya! puts 'hiYA!' end end end class Person def self.mega_methods … class << self yield end end end Tom.hiya! 我知道我可以使用class << self来定义Tom的方法,或者我可以在块中包含class << self 。 我也想出了这个替代方案: def self.mega_methods &block if block_given? extension = Module.new(&Proc.new) self.extend(extension) end end 这个问题更多的是帮助我理解Ruby的工作而不是解决特定的问题。

Ruby:const_set在块之外?

我想用Ruby模拟一个类 。 如何编写一个处理样板代码的方法? 以下代码: module Mailgun end module Acani def self.mock_mailgun(mock) temp = Mailgun const_set(:Mailgun, mock) p Mailgun yield ensure const_set(:Mailgun, temp) end end Acani.mock_mailgun(‘mock’) { p Mailgun } 打印: “mock” Mailgun 这里发生了什么? 为什么Mailgun在块内部具有原始值? 这与Ruby绑定有关吗? Ruby版本:2.1.1p76

元编程访问局部变量

class Foo def initialize bar = 10 end fiz = 5 end 是否有可能获得这些本地值(课外)?