Refactor Helper

Hi,

I have the below code which forms the bulk of a helper. I use it to take a set of URL query parameters and to filter down a Model to only return the stuff the user has chosen to see.

I feel like the code is getting rather “spaghetti-ish” and wanted to post here to see if anyone could suggest ways of refactoring this or simplifying it.

I am also getting an N+1 alert from the Bullet gem which is asking me to add .includes(:park). I have done this as you can see below but the N+1 alert is not going away.

I have thought about turning this into a whole load of scopes but some of the parts do a bit more than what I thought scopes should manage.

Any suggestions?

def filter_coasters
        unless params[:sort]
            params[:sort] = 'order'
        end

        if params[:sort] == 'order'
            #Added .includes(:park) on the lines below to try to solve N+1 but it doesn't appear to work
            @coasters = Coaster.includes(:park).originals
        else
            @coasters = Coaster.includes(:park).latest
        end

        if params[:material]
            @coasters = @coasters.where("material LIKE ?", params[:material])
        end

        # if params[:letters]
        # params[:sort] = 'alphabetically' unless params[:sort]
        # else
        # params[:sort] = 'order' unless params[:sort]
        # end


        if params[:letter]
        letter = params[:letter]

        if letter == "numbers"
            conditions = (0..9).to_a.map{ |number| " coaster_sort = '#{number}' " }.join('OR')
        else
            # If single letter
            if params[:letter] =~ /^[a-zA-Z]$/
            letter = params[:letter]
            conditions = " coaster_sort = '#{letter}' "

            # If range of letters
            else
            letter = letter.split('-')
            letter = (letter[0]..letter[1]).to_a
            conditions = letter.map{ |letter| " coaster_sort = '#{letter}' " }.join('OR')
            end
        end
        @coasters = @coasters.where(conditions)

        if params[:type]
            params[:sort] = 'park' unless params[:sort]
        else
            params[:sort] = 'alphabetically' unless params[:sort]
        end
        end

        if params[:milestones]
        @coasters = @coasters.where(is_milestone: true)
        end

        if params[:soundtracks]
        @coasters = @coasters.where(soundtrack: true)
        end

        if params[:country]
        @coasters = @coasters.where("country = ?", params[:country].upcase).references(:park)
        end

        if params[:manufacturer]
        @coasters = @coasters.where(manufacturer: params[:manufacturer])
        end

        if params[:position]
        @coasters = @coasters.where("position <> ''")
        end

        if params[:ridden_in]
        year = params[:ridden_in].to_s

        if params[:new_in_riy]
            cycles_in_year = Cycle.where(first_time: :true).where("EXTRACT(year FROM date) = ?", year).map(&:cyclable_id)
            @coasters = @coasters.where(id: cycles_in_year)
        else
            @coasters = @coasters.joins(:cycles).where("EXTRACT(year FROM date) = ?", year)
        end
        end

        if params[:sort] == 'order'
            @coasters = @coasters.except(:order).order('coasters.order_ridden ASC')

        elsif params[:sort] == 'park'
        @coasters = @coasters.except(:order).order('parks.name ASC').order('coasters.name ASC')

        elsif params[:sort] == 'alphabetical'
        @coasters = @coasters.except(:order).order('coasters.coaster_sort ASC, coasters.name ASC')

        elsif params[:sort] == 'random'
        @coasters = @coasters.except(:order).order("RAND()")

        elsif params[:sort] == 'date_opened'
        @coasters = @coasters.except(:order).order('coasters.date_opened ASC')

        elsif params[:sort] == 'speed'
        @coasters = @coasters.except(:order).order('coasters.speed DESC')

        elsif params[:sort] == 'length'
        @coasters = @coasters.except(:order).order('coasters.length DESC')

        elsif params[:sort] == 'height'
        @coasters = @coasters.except(:order).order('coasters.height DESC')

        elsif params[:sort] == 'inversions'
        @coasters = @coasters.except(:order).order('coasters.inversions DESC')

        elsif params[:sort] == 'vertical_angle'
        @coasters = @coasters.except(:order).order('coasters.vertical_angle DESC')

        else
        params[:sort] = 'park'
        @coasters = @coasters.except(:order).order('parks.name ASC').order('coasters.name ASC')
        end

        if params[:reverse]
        @coasters = @coasters.reverse_order
        end

        if params[:stat]
        # if params[:year].blank?
        #   year = 2017
        # else
            year = params[:year].to_i
        # end

        if params[:stat] == 'new_coasters'
            @coasters = @coasters.to_a

            @coasters_in_year = Coaster.new_coasters_in_year(year)
            intersection = (@coasters & @coasters_in_year)

            @coasters = Kaminari.paginate_array(intersection, { total_count: intersection.count })
        end

        if params[:stat] == 'unique_coasters'
            @coasters = @coasters.to_a

            @unique_coasters_in_year = Coaster.unique_coasters(year: year)
            intersection = (@coasters & @unique_coasters_in_year)

            @coasters = Kaminari.paginate_array(intersection, { total_count: intersection.count })
        end
        end

        if params[:coaster_attributes]
            unless params[:coaster_attributes] == ''
                atts = params[:coaster_attributes].split("|")
                @coasters = @coasters.tagged_with(atts, on: :coaster_attributes)
            end
        end

        if params[:coaster_styles]
            @coasters = @coasters.tagged_with(params[:coaster_styles], on: :coaster_styles)
        end

        # Split and recombine to put nil values at end
        if params[:sort] == 'speed'
        nils, not_nils = @coasters.partition { |c| c.speed.nil? }
        not_nils.each do |c|
            c.misc = c.speed.to_s + ' mph'
        end
        @coasters = not_nils + nils
        end

        if params[:sort] == 'length'
        nils, not_nils = @coasters.partition { |c| c.length.nil? }
        not_nils.each do |c|
            c.misc = c.length.to_s + ' feet'
        end
        @coasters = not_nils + nils
        end

        if params[:sort] == 'height'
        nils, not_nils = @coasters.partition { |c| c.height.nil? }
        not_nils.each do |c|
            c.misc = c.height.to_s + ' feet'
        end
        @coasters = not_nils + nils
        end

        if params[:sort] == 'inversions'
        nils, not_nils = @coasters.partition { |c| c.inversions.nil? }
        not_nils.each do |c|
            c.misc = helpers.pluralize(c.inversions, 'inversion')
        end
        @coasters = not_nils + nils
        end

        if params[:sort] == 'vertical_angle'
        nils, not_nils = @coasters.partition { |c| c.vertical_angle.nil? }
        not_nils.each do |c|
            c.misc = c.vertical_angle.to_s + '°'
        end
        @coasters = not_nils + nils
        end
end

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.