2016-04-11 5 views
0

私は単純なWebフォームを作成しました。ここでユーザーは会場を探すための検索条件を入力できます。価格帯。ユーザーが「検索」をクリックすると、アクティブなレコードを使用してデータベースを照会します。 1つ以上のフィールドが開いたままになっているために値がNULLの場合に問題が発生します。アクティブなレコードでnullのパラメータを無視するRails 4

コントローラでこれを回避するにはどうすればよいですか?最初に値がnullであるかどうかをチェックし、それに基づいてクエリを作成する必要がありますか?私は多くの異なるクエリと多くのコードで終わると想像することができます。これを達成するためのより速い方法が必要でしょうか?

コントローラー:

def search 
    @venues = Venue.where("price >= ? AND price <= ? AND romance = ? AND firstdate = ?", params[:minPrice], params[:maxPrice], params[:romance], params[:firstdate]) 
end 

答えて

7

あなたが空白のすべてをフィルタリングすることもできますリクエストと共に送信されたパラメータ。

空白の値をフィルタリングし、データベースの1つのクエリのみをトリガし、RailsのActiveRecord ORMを使用してwhere句を作成するDRYソリューションです。

このアプローチは、@DanBrookingによって指摘されているように、SQLインジェクションを防ぎます。 Rails 4.0+は「強力なパラメータ」を提供します。この機能を使用する必要があります。コードの下

class VenuesController < ActiveRecord::Base 

    def search 
    # Pass a hash to your query 
    @venues = Venue.where(search_params) 
    end 

    private 

    def search_params 
     params. 
     # Optionally, whitelist your search parameters with permit 
     permit(:min_price, :max_price, :romance, :first_date). 
     # Delete any passed params that are nil or empty string 
     delete_if {|key, value| value.blank? } 
    end 
end 
+2

これは正解であり、受け入れられる回答である必要があります。受け入れられた答えはSQLインジェクションに対して脆弱です。 –

0

私は会場

def self.find_by_price(min_price, max_price) 
    if min_price && max_price 
    where("price between ? and ?", min_price, max_price) 
    else 
    all 
    end 
end 

def self.find_by_romance(romance) 
    if romance 
    where("romance = ?", romance) 
    else 
    all 
    end 
end 

def self.find_by_firstdate(firstdate) 
    if firstdate 
    where("firstdate = ?", firstdate) 
    else 
    all 
    end 
end 

方法を作り、あなたのコントローラでそれを使用することをお勧めします Venue .find_by_price(params[:minPrice], params[:maxPrice]) .find_by_romance(params[:romance]) .find_by_firstdate(params[:firstdate])

1

てみてください、それはそれらが

conditions = [] 
conditions << "price >= '#{params[:minPrice]}'" if params[:minPrice].present? 
conditions << "price <= '#{params[:maxPrice]}'" if params[:maxPrice].present? 
conditions << "romance = '#{params[:romance]}'" if params[:romance].present? 
conditions << "firstdate = '#{params[:firstdate]}'" if params[:firstdate].present? 

@venues = Venue.where(conditions.join(" AND ")) 
+0

ありがとうございました!それは本当にうまくいく! :) – Plaksel

+0

btwはこのメソッドはSQLインジェクションに脆弱ではありませんか? "price> =?{query}"ではなく、 "price> =?{query}"ではなく、 "price> =#{query}" – Plaksel

0

この問題に対する別の解決策は存在しない、と私は条件にスコープを使用している、よりエレガントなものを考えるのパラメータを無視します。 あなたが

class Venue < ActiveRecord::Base 
    scope :romance, ->(genre) { where("romance = ?", genre) if genre.present? } 
end 

ような何かを行うことができます。次にとして機能するであろうものを、チェーンことができ、引数が存在しない場合、それはチェーンの一部ではありません。

http://guides.rubyonrails.org/active_record_querying.html#scopes

関連する問題