2008-10-10 3 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 변수 포함)를 controller.controller_name 또는 유사한 것을 기반으로 대체하고 싶습니다.

답변

2

이 코드를 모듈로 옮기고, 필요한 모든 컨트롤러에서이 모듈을 믹스하고 모듈 내에서 self.class 변수를 사용하여 구체적인 컨트롤러 이름을 알아낼 수 있습니다. 이 이름을 사용하면 표준 문자열 함수 (예 : capitalize)와 Kernel.const_get 함수를 사용하여 이름별로 클래스를 가져올 수 있습니다.

+0

Ahhh, Kernel.const_get은 내가 알아야 할 필요가 있다고 생각합니다. 감사! – Mike

2

좋아, 여기에 내가 뭘 했지. 결코 나에게 루비/레일 전문가를,하지만 그들이 비슷한하려는 경우 그래서 희망이 올바른 방향으로 사람을 가리킬 수, 나를 위해 작동 : 나는 그것을 포함하고있어

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 
관련 문제