私はそのようなクエリをしようとしています
def self.search(search, page = 1 )
paginate :per_page => 5, :page => page,
:conditions => ["name LIKE '%?%' OR postal_code like '%?%'", search, search], order => 'name'
end
しかし、実行されると、引用符が追加され、SQLステートメントが次のようになります。
SELECT COUNT(*)
FROM "schools"
WHERE (name LIKE '%'havard'%' OR postal_code like '%'havard'%')):
だからあなたは私の問題を見ることができます。私はRails 4とPostgres 9を使用していますが、どちらも使用したことがないので、それとactiverecordのものか、おそらくpostgresのものかどうかはわかりません。
終了クエリに'%my_search%'
のように設定するにはどうすればよいですか?
プレースホルダーは文字列に置き換えられ、正しく処理されていません。
交換
"name LIKE '%?%' OR postal_code LIKE '%?%'", search, search
と
"name LIKE ? OR postal_code LIKE ?", "%#{search}%", "%#{search}%"
Rails 2のconditions
構文を使用する代わりに、Rails 4のwhere
メソッドを代わりに使用します。
def self.search(search, page = 1 )
wildcard_search = "%#{search}%"
where("name ILIKE :search OR postal_code LIKE :search", search: wildcard_search)
.page(page)
.per_page(5)
end
注:上記では、?ではなくパラメーター構文を使用しています。プレースホルダー:これらは両方とも同じSQLを生成する必要があります。
def self.search(search, page = 1 )
wildcard_search = "%#{search}%"
where("name ILIKE ? OR postal_code LIKE ?", wildcard_search, wildcard_search)
.page(page)
.per_page(5)
end
注:名前にILIKE
を使用-postgresの大文字と小文字を区別しないLIKEのバージョン
文字列補間は機能しますが、質問でRails 4と指定されているため、これにArelを使用し、アプリデータベースに依存しないようにすることができます。
def self.search(query, page=1)
query = "%#{query}%"
name_match = arel_table[:name].matches(query)
postal_match = arel_table[:postal_code].matches(query)
where(name_match.or(postal_match)).page(page).per_page(5)
end
ActiveRecordは、?
によって参照されるパラメーターが文字列であることを認識するのに十分賢いので、単一引用符で囲みます。 couldある投稿が示唆するように、Ruby文字列補間を使用して、必要な%
記号で文字列を埋めます。ただし、これによりSQLインジェクションにさらされる可能性があります(これは悪いことです)。 SQL CONCAT()
関数を使用して、次のような文字列を準備することをお勧めします。
"name LIKE CONCAT('%',?,'%') OR postal_code LIKE CONCAT('%',?,'%')", search, search)
試して
def self.search(search, page = 1 )
paginate :per_page => 5, :page => page,
:conditions => ["name LIKE ? OR postal_code like ?", "%#{search}%","%#{search}%"], order => 'name'
end
詳細については、AREL条件に関する docs を参照してください。