2014-08-27 33 views
0

我是ruby/rails世界的新手,我面对的问题看起来很琐碎,但对我来说并不那么容易。如何使用元编程为ruby中的类的所有实例创建实例变量?

我想要做的是写一个简单的辅助方法,以帮助保持控制器清洁。此方法将接收符号/字符串,并使用camelized接收的字符串创建一个实例变量,该字符串将评估为常量/类。

我试图恢复自己的:

class ApplicationController < ActionController::Base 

    ... 

    protected 

    def self.service(name) 
    instance_eval do 
     instance_variable_set("@#{name.to_s.pluralize}", name.to_s.camelize.constantize) 
    end 
    end 

而且,在我的控制器:

class UserController < ApplicationController 

    service :user 

但是当我这样做,它在UserController,不UserController.new创建实例变量。所以,我知道什么是错的,但我无法找到我该怎么做的权利。

任何人都可以帮助我吗?

+0

您是否尝试过不使用'self.'来定义此方法,并用'service:user'替代'before_action:service'来调用它? – 2014-08-27 13:54:44

+0

我想我可以做到这一点,但这种“服务”方法不会创建一个服务。我希望每个控制器都能指定它需要的服务。我可以用'before_action'做到吗? – 2014-08-27 13:57:00

+0

正如我想的那样,你不需要所有控制器来处理一个请求,所以像这样: 'before_action - > {| c | c.service(:user)}'并且设置里面的实例变量就够了。什么是类变量? (例如@@ my_var) – 2014-08-27 14:05:30

回答

1

麻烦的是,这种方法是在类范围:

def self.service(name) 
    instance_eval do 
     instance_variable_set("@#{name.to_s.pluralize}", name.to_s.camelize.constantize) 
    end 
    end 

这意味着它会被设置一流水平的实例变量 - 或者类变量(有点)。

如果您想遵循这种方法,您需要将这些全部存储在类级别的数组或类似数据中,在类实例化时可以读出并转换为实例变量。

但是,我不喜欢弄乱控制器上的初始化方法。这不是做事的方式,所以在更改版本时可以改变课堂行为,破坏事情或变得脆弱。

在你的ApplicationController,是这样的:

class << self 
    def service(name) 
    @services ||= [] 
    return @services += name.map(&:to_sym) if name.is_a?(Array) 
    @services << name.to_sym 
    end 

    def service_names 
    @services 
    end 
end 

before_action :services 

def services 
    self.class.service_names.each do |name| 
    instance_eval do 
     instance_variable_set("@#{name.to_s.pluralize}", name.to_s.camelize.constantize) 
    end 
    end 
end 

这是未经测试。

+0

编辑修复类作用域切割和粘贴问题。请让我知道,如果它因任何原因失败或如果你想要解释任何东西。 – 2014-08-27 16:46:45