2014-08-27 38 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