重构这个Rails控制器的最佳方法是什么?

时间:2009-08-12 23:49:42

标签: ruby-on-rails ruby model-view-controller controller

我想就如何最好地重构这个控制器提出一些建议。控制器构建一个区域和模块页面。页面has_many区域,区域has_many模块。因此,区域只是包含在容器中的模块集群。

我遇到的问题是某些模块可能有一些我不希望在每个页面上执行的特定查询,所以我不得不添加条件。条件只测试模块是否在页面上,如果是执行查询。其中一个问题是,如果我添加一百个特殊模块查询,控制器必须遍历每个查询。

我想我希望看到这些模块条件移出控制器以及所有其他自定义操作。我可以将所有内容保存在这个控制器中,但我打算使用这个控制器有很多应用程序,因此它可能会变得混乱。

class PagesController < ApplicationController
  # GET /pages/1
  # GET /pages/1.xml
  # Show is the main page rendering action, page routes are aliased in routes.rb

  def show
    #-+-+-+-+-Core Page Queries-+-+-+-+-
    @page = Page.find(params[:id])
    @zones = @page.zones.find(:all, :order => 'zones.list_order ASC')
    @mods = @page.mods.find(:all)
    @columns = Page.columns

    # restful params to influence page rendering, see routes.rb
    @fragment = params[:fragment]   # render single module
    @cluster = params[:cluster]     # render single zone
    @head = params[:head]           # render html, body and head

    #-+-+-+-+-Page Level Json Conversions-+-+-+-+-
    @metas = @page.metas ? ActiveSupport::JSON.decode(@page.metas) : nil
    @javascripts = @page.javascripts ? ActiveSupport::JSON.decode(@page.javascripts) : nil

    #-+-+-+-+-Module Specific Queries-+-+-+-+-  
    # would like to refactor this process

    @mods.each do |mod|
      # Reps Module Custom Queries
      if mod.name == "reps"
        @reps = User.find(:all, :joins => :roles, :conditions => { :roles => { :name => 'rep' } })
      end
      # Listing-poc Module Custom Queries
      if mod.name == "listing-poc"
        limit = params[:limit].to_i < 1 ? 10 : params[:limit] 
        PropertyEntry.update_from_listing(mod.service_url)
        @properties = PropertyEntry.all(:limit => limit, :order => "city desc")
      end      
      # Talents-index Module Custom Queries
      if mod.name == "talents-index"
        @talent = params[:type]
        @reps = User.find(:all, :joins => :talents, :conditions => { :talents => { :name => @talent } })
      end
    end    

    respond_to do |format|
      format.html # show.html.erb
      format.xml { render :xml => @page.to_xml( :include => { :zones => { :include => :mods } } ) }
      format.json { render :json => @page.to_json }
      format.css # show.css.erb, CSS dependency manager template
    end
  end

  # for property listing ajax request
  def update_properties
    limit = params[:limit].to_i < 1 ? 10 : params[:limit]
    offset = params[:offset]
    @properties = PropertyEntry.all(:limit => limit, :offset => offset, :order => "city desc")
    #render :nothing => true
  end   
end

因此想象一个拥有一百个模块和大量额外控制器操作的站点。我想大多数人都会同意,如果我可以将代码移出并重构它以使其更像配置,那将会更加清晰。

2 个答案:

答案 0 :(得分:0)

你应该看看这个宝石:

http://github.com/josevalim/inherited_resources/tree/master

非常优雅,解决了你遇到的所有问题。

答案 1 :(得分:0)

我将特定于代码段的查询移动到辅助方法中并将它们从控制器中移出,这样片段本身就可以通过erb执行查询并保持DRY并通过帮助程序读取。因此,不是在模块中引用@refs,而是可以在模块中引用find_all_refs或类似的东西,并执行并可能记住响应。