DRY Rails控制器避免重复多次相同的方法

时间:2016-03-18 10:27:52

标签: ruby-on-rails ruby ruby-on-rails-3

我想干掉我的控制器,因为我在同一个控制器内多次使用一些片段/代码块(我删除了一些,因为它太长了但是这已经给出了重复的想法)。以下是我不断重复的方块:

  • @deal = search_deal

  • @next_deal = find_next_deal

  • @userdeal = find_or_create_userdeal_participation

  • @user_credits = calculate_user_credits_in_deal

我很新秀并且不知道如何做到这一点,但我觉得这段代码应该被分解。

class DealsController < ApplicationController

  before_filter :find_deal,
    :only => [  :showcase ]
  before_filter :ensure_canonical_deal_path!,
    :only => [  :showcase ]   

  def showcase    
    # find appropriate deal
    @deal = search_deal 

    respond_to do |format|
      format.html # showcase.html.erb
      format.json { render json: @deal }
    end      

  end  

  def buy_stuff
    @deal = search_deal 
    # bring 'next deal' url to the view
    @next_deal                   = find_next_deal

    # USER IS SIGNED-IN
    if user_signed_in?

      @userdeal                     = find_or_create_userdeal_participation
      @user_credits = calculate_user_credits_in_deal

      # if: user still has credits available
      if @user_credits >= 1 
        #do this
        respond_to do |format|
          format.js 
        end

      else
        respond_to do |format|
          # do that
        end
      end  

    # USER IS NOT SIGNED-IN 

    else  
      respond_to do |format|
        format.js { render :template => "deals/call_to_sign_in.js.erb" }
      end
    end
  end


  def show_discounts
    @deal = search_deal 
    respond_to do |format|
      #do that
    end
  end

  def pending_deals
    @deal = search_deal 
    # bring 'next deal' url to the view
    @next_deal                   = find_next_deal
    if user_signed_in?

      @userdeal                     = find_or_create_userdeal_participation
      @user_credits = calculate_user_credits_in_deal
    end

    respond_to do |format|
      #do this
    end
  end

  def ask_question
    @deal = search_deal 
    respond_to do |format|
      #do that
    end
  end


  protected  


    def ensure_canonical_deal_path!
      if request.path != actual_deal_page_path(@deal)
        redirect_to actual_deal_page_path(@deal, :format => params[:format]), :status => :moved_permanently
        return false
      end
    end



  private
    # DRY file as this is used multiple times 
    # trick source - http://blog.rstankov.com/rails-anti-pattern-setting-view-variables-in-before-actions/
    def search_deal
      Deal.friendly.find(params[:id])
    end

    def find_or_create_userdeal_participation
      UserDeal.where('user_id = ? AND deal_id = ?', current_user.id, @deal.id).take ||
      UserDeal.create(user_id: current_user.id, deal_id: @deal.id)
    end

    def calculate_user_credits_in_deal
      current_user.credit_nb + @userdeal.history
    end

    def find_next_deal
      Deal.order_next_deal_at(@deal).next
    end

end

2 个答案:

答案 0 :(得分:1)

我认为最好的方法就是为那些调用重复代码的方法添加before_filters,如:

before_filter :search_deal, :only => [:showcase, :buy_stuff, ...]

答案 1 :(得分:0)

class DealsController < ApplicationController
  before_filter :find_deal, only: [:showcase]
  before_filter :ensure_canonical_deal_path!, only: [:showcase]

  def showcase
    search_deal
    respond_to do |format|
      format.html
      format.json{render json: @deal}
    end      
  end  
  def buy_stuff
    search_deal 
    find_next_deal
    if user_signed_in?
      find_or_create_userdeal_participation
      calculate_user_credits_in_deal
      if @user_credits >= 1
        respond_to(&:js)
      else
        respond_to{|format| }
      end  
    else  
      respond_to{|format| format.js{render template: "deals/call_to_sign_in.js.erb"}}
    end
  end
  def show_discounts
    search_deal 
    respond_to{|format|}
  end
  def pending_deals
    search_deal 
    find_next_deal
    if user_signed_in?
      find_or_create_userdeal_participation
      calculate_user_credits_in_deal
    end
    respond_to{|format| }
  end
  def ask_question
    search_deal 
    respond_to{|format| }
  end
  protected def ensure_canonical_deal_path!
    if request.path != actual_deal_page_path(@deal)
      redirect_to actual_deal_page_path(@deal, format: params[:format]), status: :moved_permanently
      return false
    end
  end
  private def search_deal
    @deal = Deal.friendly.find(params[:id])
  end
  private def find_or_create_userdeal_participation
    @user_deal =
    UserDeal.where('user_id = ? AND deal_id = ?', current_user.id, @deal.id).take ||
    UserDeal.create(user_id: current_user.id, deal_id: @deal.id)
  end
  private def calculate_user_credits_in_deal
    @user_credits = current_user.credit_nb + @userdeal.history
  end
  private def find_next_deal
    @next_deal = Deal.order_next_deal_at(@deal).next
  end
end