Tag: 元编程

我如何使用class_eval?

我不懂class_eval 。 class Module def attr_ (*syms) syms.each do |sym| class_eval %{def #{sym}= (val) @#{sym} = val end} end end end %是什么意思? class_eval做什么? (val)来自哪里?

在Ruby中使用yield_method中的yield

是否可以在给定于define_method的块中生成yield关键字? 简单的例子: class Test define_method :test do |&b| puts b # => # yield end end Test.new.test { puts “Hi!” } 此代码在Ruby 1.8.7和1.9.0中都会产生以下错误: test.rb:4:在`test’中:没有来自test.rb的块(LocalJumpError):8 奇怪的是b块变量!= nil但是block_given? 返回false。 有意的Ruby行为是不是通过Proc对象识别块? 编辑:关于Beerlington的回答: b.call()不是我想要的。 块变量仅用于指示实际给出块,并且在define_method中未检测到。 我需要使用yield而不是block.call 我愿意为Ruby中定义新类的方式编写一些扩展,因此当我使用扩展时,你可以接受任何用纯Ruby编写的代码。 因此,不能考虑类似的语​​义,因为这会强制我的库的用户只使用一种正确的方法来传递块。 这会破坏TIMTOWTDI规则,并且不会使我的库透明。 真实的例子 由于my_def使用define_method下面的代码可以简化为上面的代码: require ‘my_library’ class Test # client can write ‘my_def’ instead of ‘def’ since # my_library extends Class class […]

如何获取Ruby中已经“必需”的文件列表?

这纯粹是一个实验,但我想知道是否有可能通过某种元编程在运行时获得require的gem列表。 例如,说我有: require ‘rubygems’ require ‘sinatra’ require ‘nokogiri’ # don’t know what to do here 如何在运行时打印出以下内容? this app needs rubygems, sinatra, nokogiri

如何列出Ruby类中包含的模块?

您如何列出Ruby中类层次结构中特定类中包含的模块? 像这样的东西: module SomeModule end class ParentModel < Object include SomeModule end class ChildModel [SomeModule] p ChildModel.included_modules(false) #=> [] 列出祖先会使模块在树中显得更高: p ChildModel.ancestors #=> [ChildModel, ParentModel, SomeModule, Object, Kernel]

定义“method_called”..如何调用每次调用类的任何函数时调用的钩子方法?

我想创建一个钩子方法,每次调用类的任何函数时都会调用它。 我已经尝试过method_added,但它只在类定义时执行一次, class Base def self.method_added(name) p “#{name.to_s.capitalize} Method’s been called!!” end def a p “a called.” end def b p “b called.” end end t1 = Base.new t1.a t1.b t1.a t1.b Output: “A Method’s been called!!” “B Method’s been called!!” “a called.” “b called.” “a called.” “b called.” 但我的要求是在程序中的任何地方调用的类的任何函数都会触发“method_called”,hook方法。 Expected Output: “A Method’s been […]

如何使用Ruby元编程将回调添加到Rails模型?

我编写了一个简单的Cacheable模块,可以很容易地在父模型中缓存聚合字段。 该模块要求父对象为需要在父级别进行缓存的每个字段实现cacheable方法和calc_方法。 module Cacheable def cache!(fields, *objects) objects.each do |object| if object.cacheable? calc(fields, objects) save!(objects) end end end def calc(fields, objects) fields.each { |field| objects.each(&:”calc_#{field}”) } end def save!(objects) objects.each(&:save!) end end 我想将回调添加到包含此模块的ActiveRecord模型中。 此方法要求模型实现父模型的哈希值和需要缓存的字段名称。 def cachebacks(klass, parents) [:after_save, :after_destroy].each do |callback| self.send(callback, proc { cache!(CACHEABLE[klass], self.send(parents)) }) end end 如果我使用以下方法手动添加两个回调,这种方法很有效: after_save proc { cache!(CACHEABLE[Quote], *quotes.all) […]

rubylambda语境

假设我在最顶层有以下ruby定义 callable = lambda {“#{hi}”} 并且假设稍后我创建了一个名为temp的对象,该对象具有一个名为hi的方法。 现在我想做的是在temp的上下文中调用callable 。 我试过了 temp.instance_eval do callable.call end 但这给了我错误“ NameError: undefined local variable or method ‘hi’ for main:Object ”。 我想知道是否有任何方法可以将callable的上下文重新绑定到temp以便我不会收到错误消息? 我知道我可以在main:Object上定义method_missing并将所有方法调用重新路由到temp但这似乎太糟糕了,无法实现我想要的东西。

是否可以在Ruby中的每一行之后运行代码?

我知道有可能在ruby中使用挂钩之前和之后修饰方法,但是可以为给定方法的每一行执行此操作吗? 例如,我有一个自动化测试,我想validation每个步骤后页面上没有显示错误。 错误显示为红色div,并且对于Ruby不可见或者类似的东西,因此我必须手动检查它(还有其他几个用例)。 我知道可能使用set_trace_func 。 但我认为这可能会带来更多问题而不是好处,因为它可以在整个调用树上运行(并且需要我自己过滤它)。 更新(澄清) : 我有兴趣拦截在给定方法中执行的所有操作(或调用)。 这意味着调用了未指定数量的类,因此我不能只截取任何给定的类/方法集。

Ruby String#to_class

从上一篇文章中做了一些修改以回应sepp2k关于命名空间的评论,我已经实现了String#to_class方法。 我在这里分享代码,我相信它可能会被重构,特别是“i”计数器。 您的意见表示赞赏。 class String def to_class chain = self.split “::” i=0 res = chain.inject(Module) do |ans,obj| break if ans.nil? i+=1 klass = ans.const_get(obj) # Make sure the current obj is a valid class # Or it’s a module but not the last element, # as the last element should be a class klass.is_a?(Class) || […]

将现有类添加到模块中

我在app / classes文件夹中有一些现有的ruby类: class A … end class B … end 我想在模块MyModule中对这些类进行分组 我知道我可以这样做: module MyModule class A … end class B … end end 但是有一个元编程快捷方式可以做同样的事情,所以我可以“导入”所有现有的类? 谢谢,吕克