Tag: 元编程

Ruby有未定义的实例变量的method_missing等价物吗?

当我调用一个不存在的方法时, method_missing会告诉我该方法的名称。 当我尝试访问尚未设置的变量时,该值只是nil 。 我试图动态拦截对nil实例变量的访问,并根据被访问变量的名称返回一个值。 最接近的等价物是PHP的__get 。 Ruby中有没有相同的function?

如何检索class级名称?

我正在使用Ruby on Rails 3.0.7,我想检索类名,如果它是命名空间的话。 例如,如果我有一个名为User::Profile::Manager我将使用一些未知的Ruby或Ruby on Rails方法并以安全的方式从中检索Manager字符串。 顺便说一句 :我可以获得哪些“常用”的“有用”信息?

创建用于引发特定于类的错误的模块

在我的rails项目中,我经常在我的类和模型中使用这种行为: class Whatever class WhateverError < StandardError; end def initialize(params={}) raise WhateverError.new("Bad params: #{params}") if condition # actual class code to follow end end 麻烦的是,这是非常重复和相当冗长的。 如果我能在每次需要引发特定于类的错误时执行此操作,我会喜欢它: class ErrorRaiser include ClassErrors def initialize(params={}) error(“Bad params: #{params}”) if condition error if other_condition # has default message # actual class code to follow end def self.class_method error if […]

Ruby – 在Ruby中扩展内置变量

我想在Ruby中扩展变量的function。 原因是我正在研究类似系统或值检查器的东西(这听起来有点疯狂,但整个想法是长期解释,只是我想扩展默认变量的原因)。 我已经读到在Ruby中,一切都是对象; 所以变量就是对象。 对于可以通过元编程改变的东西,Ruby应该是相当自由的。 是否有某种与我可以扩展的局部变量相关联的“类”? 我想为每个包含类型的字符串表示forms的变量关联一个字符串变量。 此外,我想拦截变量赋值,并在每次为变量赋值新值时执行方法。 这是我可以检查,如果新值根据类型是正确的(存储为变量中的字符串)。 如果Ruby中的局部变量被定义为类的对象,我可以扩展该类或通过ruby mixin修改它。 解决方法是为我的变量创建一个新类(而不是使用Ruby的局部变量中的构建)。 该类可以具有值属性,类型的属性(存储为字符串)以及get和set方法。 这样我可以解决我的问题,但我想在ruby中扩展内置变量,如果可能的话。 目前的工作正在进行中 class Fixnum attr_accessor :tp @tp def mytype ( type ) @tp = type end def typecheck #call typechecker puts “checked” end end 测试代码: a = 3 a.mytype(“nat”) puts a.tp a.typecheck 还有两个问题。 首先 ,我认为不可能向Fixnum添加新的构造函数。 其次 ,我想拦截变量访问,即“b = a”调用a的方法’typecheck’。 但这需要类似于面向方面编程的东西,我不确定这是否可以通过Ruby的元编程方便解决。

Ruby中的动态validation和元编程

我正在尝试开发一个应用程序,该应用程序可以向不同的用户提供相同的资源,并且资源可能具有基于用户的不同validation行为。 我曾尝试使用Ruby元编程以简单的方式解决这个问题,但看起来我缺少一些关于此事的关键知识。 我可以通过诸如此类的模型来举例说明 class Profile < ActiveRecord::Base # validates_presence_of :string1 end 该模型有一个属性’string1’,有时是必需的,有时不是。 我想为每个用户创建子类(由于此简化中不明显的原因)并创建了一个我想要包含的模块: module ExtendProfile def self.included(base) base.extend(ClassMethods) end module ClassMethods def configure_validation(required) if required class_eval(“ActiveRecord::Base.validates_presence_of :string1”) end end end end 它的唯一目的是添加一个方法,根据给定的参数添加条件validation。 当使用一个为true的参数调用时,它会添加validation,但它不会干净地执行。 看起来它并没有像我想象的那样分离子类。 它可以通过以下测试来说明: profile = Profile.new profile.save; profile.errors => [] 默认情况下,配置文件可以保存而不会出错。 Object::const_set(‘FirstExtendedProfile’.intern, Class::new(Profile) { include ExtendProfile }) FirstExtendedProfile.configure_validation(true) fep = FirstExtendedProfile.new; fep.save; fep.errors […]

限制在Rails中访问用户提交的代码

我正在开发一个rails应用程序,它将ruby代码作为输入并执行它。 由于提交的代码来自不受信任的域,我想限制对某些方法和模块的访问。 例如,我不希望用户访问File.read或open() 。 此外,是否可以限制只访问几个模块? 用户提交的代码只能要求白名单中的模块。 我可以对用户代码进行validation,但我想检查ruby语言或任何模块是否已具备此function。 Codeschool.com有互动教程。 我想知道他们是否限制访问用户代码或进行任何validation。

什么时候模块包含在运行在rails中的Ruby类中?

我正在尝试编写一个方法,告诉我包含特定模块的每个类。 它看起来像这样 – def Rating.rateable_objects rateable_objects = [] ObjectSpace.each_object(Class) do |c| next unless c.include? Rateable rateable_objects << c end rateable_objects end “Rateable”是我的模块,我将其包含在几个模型中。 我发现如果我在启动rails console或运行服务器之后立即调用它,则此方法返回[]。 但是,如果我首先实例化其中一个消费模型的实例,它将在结果中返回该模型。 那么什么时候包含模块? 我猜这个过程的后期比他应用启动的时候要多。 如果我不能在这个过程的早期以这种方式获得这些信息,那么无论如何都要实现这一目标吗?

变量如何绑定到define_method的主体?

在尝试提高我的Ruby技能时,我一直在讨论这个案例,我只能通过阅读API文档找不到解释。 非常感谢您的解释。 这是示例代码: for name in [ :new, :create, :destroy ] define_method(“test_#{name}”) do puts name end end 我希望/期望发生的是name变量将绑定到给定于define_method的块,并且当#test_new时它将输出“new”。 而是每个定义的方法输出“destroy” – 分配给name变量的最后一个值。 我对define_method及其块有什么误解? 谢谢!

何时使用`method_missing`

在下面的代码中,方法roar没有在Lion类中定义,但仍然可以使用method_missing调用。 class Lion def method_missing(name, *args) puts “Lion will #{name}: #{args[0]}” end end lion = Lion.new lion.roar(“ROAR!!!”) # => Lion will roar: ROAR!!! 在哪些情况下我应该如何使用此method_missing ? 使用安全吗?

动态替换Ruby中对象的方法实现

我想用一个用户指定的块替换对象的方法的实现。 在JavaScript中,这很容易实现: function Foo() { this.bar = function(x) { console.log(x) } } foo = new Foo() foo.bar(“baz”) foo.bar = function(x) { console.error(x) } foo.bar(“baz”) 在C#中它也很容易 class Foo { public Action Bar { get; set; } public Foo() { Bar = x => Console.WriteLine(x); } } var foo = Foo.new(); foo.Bar(“baz”); foo.Bar = x => Console.Error.WriteLine(x); […]