3

やや複雑なクエリを処理しようとしています。これにアプローチする方法についていくつかの方法を読んだことがありますが、ここでは実際には適用されません。 「カテゴリ」別 (未発表、人気、最新) および「時間」別 (すべての時間、先月、先週、今日)

以下のコードが非常に悪いことに気づきました。私の目標は、それを機能させ、後でリファクタリングすることだけでした。言うまでもなく、カテゴリと時間の両方を考慮していないため、実際には機能しませんが、このスレッドでそれを処理すると考えました.

また、この SO コードの貼り付けでこれをより明確にするために、すべての行から を除外しましたが.page(params[:page]).per(30)、すべての行に適用する必要があります。

それで、私がこれを行う方法を知っている人はいますか?私はしばらくそれについて熟考してきましたが、ちょっと困惑しています

def index
  case params[:category]
  when "latest"
    @books = Book.all.page(params[:page]).per(30)   
  when "downloads"
    @books = Book.order('downloads DESC')
  when "top100"
    @books = Book.order('downloads DESC').limit(100)
  when "unreleased"
    @books = Book.unreleased
  else
    @books = Book.all.page(params[:page]).per(30)   
  end

  case params[:time]
  when "today"
    @books = Book.days_old(1)
  when "week"
    @books = Book.days_old(7)
  when "month"
    @books = Book.days_old(30)
  when "all-time"
    @books = Book.all
  else
    @books = Book.all.page(params[:page]).per(30)   
  end
end  

ルート:

# Books
get 'book/:id', to: 'books#show', as: 'book'

resources :books, only: [:index] do
  get ':category/:time(/:page)', action: 'index', on: :collection
end
4

2 に答える 2

8
  1. すべてのクエリをスコープとしてモデルに移動します

    class Book < ActiveRecord::Base
      scope :downloads,  -> { order('downloads DESC') }
      scope :top100,     -> { order('downloads DESC').limit(100) }
      scope :unreleased, -> { unreleased }
      scope :today,      -> { days_old(1) }
      scope :week,       -> { days_old(7) }
      scope :month,      -> { days_old(30) }
      scope :latest,     -> { }
      scope :all_time,   -> { }
    end
    
  2. 補助メソッドを作成してパラメータをフィルタリングし、データの不一致を回避します

    class BooksController < ApplicationController
      private
    
      def category_params
        %w(downloads top100 unreleased).include?(params[:category]) ? params[:category].to_sym : nil
      end
    
      def time_params
        %w(today week month latest all_time).include?(params[:time]) ? params[:time].to_sym : nil
      end
    end
    
  3. caseパラメータと同じ名前のスコープを適用して、ステートメントを削除します

    def index
      query = Book.all
      query = query.send(category_params) if category_params
      query = query.send(time_params) if time_params
      @books = query.page(params[:page]).per(30)
    end
    

4 行では、まだSandi Metz のガイドラインの範囲内です。:)

于 2013-09-29T04:38:38.367 に答える