vendredi 18 mars 2016

DRY Rails controller to avoid repeating multiple times same method

I would like to DRY my controller as I use some snippets/blocks of code many times inside the same controller (I have removed some as it was too long but this already gives an idea of the repetition). Here are the blocks I keep repeating :

  • @deal = search_deal

  • @next_deal = find_next_deal

  • @userdeal = find_or_create_userdeal_participation

  • @user_credits = calculate_user_credits_in_deal

I'm quite rookie and don't know how to do this but I feel this code should be factorized.

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://ift.tt/1RowOjy
    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

Aucun commentaire:

Enregistrer un commentaire