Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

コントローラを膨らませることなくRailsモデルを検索およびフィルタリングする

Railsコントローラーでの検索、並べ替え、フィルタリングは面倒な場合があります。 ElasticSearchとSolrは優れた強力なソリューションですが、小さなアプリにとっては非常に大きな依存関係です。

幸い、Railsにはスコープが含まれており、単純な検索、フィルタリング、および並べ替えに必要な多くのものを提供できます。スコープチェーンを利用すると、大きな依存関係を引き受けたり、繰り返し検索コードを自分で作成したりすることなく、必要な機能を構築できます。

スコープで検索

#indexを想像してみてください 製品のテーブルを表示するRESTfulコントローラーのメソッド。製品は、アクティブ、保留中、または非アクティブにすることができ、1つの場所で利用でき、名前が付けられています。

これらの製品をフィルタリングできるようにする場合は、いくつかのスコープを作成できます。

app / models / product.rb
class Product < ActiveRecord::Base
  scope :filter_by_status, -> (status) { where status: status }
  scope :filter_by_location, -> (location_id) { where location_id: location_id }
  scope :filter_by_starts_with, -> (name) { where("name like ?", "#{name}%")}
end

これらの各スコープは、返される結果を制限するために使用できるProductのクラスメソッドを定義します。

@products = Product.filter_by_status("active").filter_by_starts_with("Ruby") # => All active products whose names start with 'Ruby'

コントローラはこれらのスコープを使用して結果をフィルタリングできます:

app / controllers / product_controller.rb
def index
  @products = Product.where(nil) # creates an anonymous scope
  @products = @products.filter_by_status(params[:status]) if params[:status].present?
  @products = @products.filter_by_location(params[:location]) if params[:location].present?
  @products = @products.filter_by_starts_with(params[:starts_with]) if params[:starts_with].present?
end

これで、「Ruby」で始まる名前のアクティブな商品だけを表示できます。

https://example.com/products?status=active&starts_with=Ruby

明らかに、これにはクリーンアップが必要です

このコードがどのように扱いにくく反復的になり始めるかを見ることができます!もちろん、Rubyを使用しているので、これをループに詰め込むことができます:

app / controllers / product_controller.rb
def index
  @products = Product.where(nil)
  filtering_params(params).each do |key, value|
    @products = @products.public_send("filter_by_#{key}", value) if value.present?
  end
end

private

# A list of the param names that can be used for filtering the Product list
def filtering_params(params)
  params.slice(:status, :location, :starts_with)
end
より再利用可能なソリューション

このコードをモジュールに移動して、フィルタリングをサポートする任意のモデルに含めることができます。

app / models / concerns / filterable.rb
module Filterable
  extend ActiveSupport::Concern

  module ClassMethods
    def filter(filtering_params)
      results = self.where(nil)
      filtering_params.each do |key, value|
        results = results.public_send("filter_by_#{key}", value) if value.present?
      end
      results
    end
  end
end
app / models / product.rb
class Product
  include Filterable
  ...
end
app / controllers / product_controller.rb
def index
  @products = Product.filter(params.slice(:status, :location, :starts_with))
end

これで、コントローラーに1行、モデルに1行を使用して、モデルのフィルター処理と検索を行うことができます。それはどれくらい簡単ですか?組み込みのorderを使用して、組み込みの並べ替えを取得することもできます。 クラスメソッドですが、並べ替え用に独自のスコープを作成することをお勧めします。そうすれば、入力を健全性チェックできます。

手間を省くために、Filterableを配置しました 要旨に。自分のプロジェクトで試してみてください。時間とコードを大幅に節約できました。

更新: 何かを指摘してくれたJanSandbrinkに感謝します。filtering_paramsでパラメータをホワイトリストに登録するのを忘れがちです。 。忘れた場合は、アプリを深刻なまで開く可能性があります。 セキュリティの問題。

これをすべて回避するには、statusという名前のスコープを使用する代わりに 、location 、およびstarts_with 、この記事を更新して、スコープの名前をfilter_by_statusにしました。 、filter_by_location 、およびfilter_by_starts_with 。そうすれば、より明確で安全になります。

重要な警告

スコープにパラメータを送信することは、Webアプリで基本的な検索とフィルタリングを行う簡単な方法です。 ただし、注意を怠り、ユーザーからの送信をすべて受け入れると、アプリにかなり厄介なセキュリティバグが発生する可能性があります。

特に、order SQLインジェクションに対して脆弱です。したがって、パラメータを使用して並べ替え順序を定義する場合は、常に ユーザーから送信された列名を確認し、安全であることがわかっている値のみを許可してください。

Rails SQLインジェクションサイトは、どのActiveRecordメソッドが脆弱であるかを知るのに役立つため、アプリを安全に保つことができます。

動画でもっとよく学びますか?

コンパニオンスクリーンキャストで、新しいアプリの起動から検索やフィルタリングの追加まで、すべてのステップを見ることができます。 アプリを作成し、サンプルデータを入力し、検索フォームを追加して、接続します。また、動画と一緒にソースを入手できるので、独自のRailsアプリに簡単な検索とフィルタリングを追加するときに参照できます。

スクリーンキャストの詳細については、こちらをご覧ください!


  1. Elasticsearchを利用した検索と視覚化をSQLデータに追加します

    新しいNoSQLデータストアに焦点を当てた話題にもかかわらず、リレーショナルデータベースとSQLベースのデータベースはまだ健在です。実際、私たちが協力しているほとんどすべての顧客は、MongoDB、Redis、またはElasticsearchと並んで、環境内にMySQL、PostgreSQL、またはMSSQLServerを持っています。移行として、または単に全文検索や視覚化などの機能をリレーショナルデータに追加するために、リレーショナルデータベースから別のデータストアにデータを複製する最も簡単な方法に関するリクエストを受け取ることは珍しくありません。幸い、Elasticsearchを使用すると

  2. Bing の検索履歴を表示および削除する方法

    Bing は、Microsoft アカウントにログインしているときに行うすべての検索を追跡します。その履歴は、過去に行ったことに戻る必要がある場合に役立ちます。また、検索履歴は本質的に非常に個人的な情報を明らかにする可能性があるため、プライバシーの問題になる可能性もあります。コントロールを取り戻す方法は次のとおりです。 検索履歴を確認する最も簡単な方法は、Bing 自体にアクセスすることです。ホームページから、右上のハンバーガー メニューをクリックします。表示されるドロップダウンの上部にある [検索履歴] リンクをクリックします。 Bing の検索履歴インターフェイスはシンプルですが機