2008-10-10 81 views
1

我一直在重构我的模型和控制器,努力消除代码重复,到目前为止,它似乎都是桃色奶油状。目前,我有一些代码是共同的我的两个控制器,就像这样:如何根据控制器名称查询模型

def process_filters 
# Filter hash we're going to pass to the model 
    filter_to_use = {} 

    # To process filters, we first query the model to find out what filters 
    # we should be looking for, as the model knows what we can filter. 
    Iso.available_filters.each do |filter| 
    # We should have our array with our filter listing. 
    # Check the purchase order model for a description 
    filter_name = filter[0][:filter_name] 

    # Filters are stored in a session variable, this way filters survive 
    # page reloads, etc. First thing we do, is set the session if new filters 
    # have been set for the filter. 
    session_name = session_filter_name(filter_name) 
    if params[session_name] 
     if params[session_name] == 'All' 
     session[session_name] = nil 
     else 
     session[session_name] = params[session_name] 
     filter_to_use[filter_name] = params[session_name] 
     end 
    elsif session[session_name] 
     # If params aren't read, we still need to filter based off the users 
     # session 
     filter_to_use[filter_name] = session[session_name] 
    end 
    end 

    # Just using this variable for now until I can refactor the helper code 
    # so that this is passed in. 
    @current_filter_values = filter_to_use 

    filter_to_use[:page] = @current_page 

    @isos = Iso.find_filtered(filter_to_use) 

    if @isos.out_of_bounds? 
    filter_to_use[:page] = session[:previous_page] = @current_page = 1 
    @isos = Iso.find_filtered(filter_to_use) 
    end 
end 

下面这段代码是完全一样的另一控制器代码,除了参考模型(在这种情况下, ISO)。有什么我可以让模型参考动态?

基本上我想将Iso引用(包括@iso变量)替换为基于controller.controller_name或类似名称的内容。

回答

2

您可以将此代码移入模块,在您需要的所有控制器中混入此模块,并使用模块内部的self.class变量来计算出具体的控制器名称。使用这个名字,你可以使用标准的字符串函数(例如大写)和Kernel.const_get函数来获取类名。

+0

唉唉,我觉得Kernel.const_get是我需要知道些什么。谢谢! – Mike 2008-10-10 04:28:29

2

好吧,这就是我最终的结果。绝不是我一个Ruby/Rails的大师,但它为我工作,所以希望它可能会,如果他们试图类似的东西有人指出了正确的方向:

module Filtered 
    module Controller 
    module InstanceMethods 
     def process_filters 
     # Filter hash we're going to pass to the model 
     filter_to_use = {} 

     # To process filters, we first query the model to find out what filters 
     # we should be looking for, as the model knows what we can filter. 
     Kernel.const_get( 
      self.controller_name.singularize.camelize).available_filters.each do |filter| 
      # We should have our array with our filter listing. 
      # Check the purchase order model for a description 
      filter_name = filter[0][:filter_name] 

      # Filters are stored in a session variable, this way filters survive 
      # page reloads, etc. First thing we do, is set the session if new filters 
      # have been set for the filter. 
      session_name = session_filter_name(filter_name) 
      if params[session_name] 
      if params[session_name] == 'All' 
       session[session_name] = nil 
      else 
       session[session_name] = params[session_name] 
       filter_to_use[filter_name] = params[session_name] 
      end 
      elsif session[session_name] 
      # If params aren't read, we still need to filter based off the users 
      # session 
      filter_to_use[filter_name] = session[session_name] 
      end 
     end 

     # Just using this variable for now until I can refactor the helper code 
     # so that this is passed in. 
     self.instance_variable_set('@current_filter_values', filter_to_use) 

     filter_to_use[:page] = self.instance_variable_get('@current_page') 

     self.instance_variable_set("@#{self.controller_name}", 
      Kernel.const_get(self.controller_name.singularize.camelize).find_filtered(
      filter_to_use)) 

     if self.instance_variable_get("@#{self.controller_name}").out_of_bounds? 
      filter_to_use[:page] = session[:previous_page] = 1 
      self.instance_variable_set("@#{self.controller_name}", 
      Kernel.const_get(self.controller_name.singularize.camelize).find_filtered(
       filter_to_use)) 
     end 
     end 

     private 

     # Quick helper function for generating session variable names 
     def session_filter_name(name) 
     "#{self.controller_name}_#{name}_filter".to_sym 
     end 

    end 
    end 
end 

我包括它在我所有的通过插件,init.rb文件控制器像这样:

# Include hook for controllers 
ActionController::Base.class_eval do 
    include Filtered::Controller::InstanceMethods 
end