나는 탐조등이 "완료"되었다고 생각합니다 . 프로덕션 종속성이 없으므로 무기한으로 작동하지 않을 이유가 없습니다. 나는 또한 다른 것들로 넘어갔습니다.
버그를 발견하면 다른 사람들이 찾아서 토론할 수 있도록 자유롭게 문제를 공개하세요. 하지만 개인적으로 답변을 드릴 수는 없습니다. Searchlight가 더 이상 귀하의 요구 사항을 충족하지 못한다면, 포크해 보세요! :)
Searchlight는 ORM을 사용하여 데이터베이스 검색을 구축하는 간단한 방법입니다.
Searchlight는 연결된 메서드 호출 (예: ActiveRecord의 .where(...).where(...).limit(...)
또는 Sequel, Mongoid의 유사한 체인을 사용하여 쿼리를 작성할 수 있는 모든 ORM 또는 개체와 함께 작동할 수 있습니다. , 등).
시작하는 데 도움이 되는 데모 앱과 해당 앱의 코드가 제공됩니다.
Searchlight의 주요 용도는 웹 애플리케이션에서 검색 양식을 지원하는 것입니다.
Searchlight는 사용자를 위해 쿼리를 작성하지 않습니다. 그것이 하는 일은:
form_for
사용).WHERE first_name =
부분을 수행하지 않음) 예를 들어 YetiSearch
라는 Searchlight 검색 클래스가 있고 다음과 같이 인스턴스화하는 경우:
search = YetiSearch . new (
# or params[:yeti_search]
"active" => true , "name" => "Jimmy" , "location_in" => %w[ NY LA ]
)
... search.results
호출하면 YetiSearch
에서 search_active
, search_name
및 search_location_in
메소드를 호출하여 검색이 작성됩니다. (다시 수행하고 "name"
생략하면 search_name
호출하지 않습니다.)
그런 다음 results
메소드는 마지막 검색 메소드의 반환 값을 반환합니다. ActiveRecord를 사용하는 경우 이는 ActiveRecord::Relation
되며 each
호출하여 결과를 반복하고 to_sql
호출하여 생성된 쿼리 등을 가져올 수 있습니다.
검색 클래스는 두 가지 주요 부분, 즉 base_query
와 일부 search_
메소드로 구성됩니다. 예를 들어:
class PersonSearch < Searchlight :: Search
# This is the starting point for any chaining we do, and it's what
# will be returned if no search options are passed.
# In this case, it's an ActiveRecord model.
def base_query
Person . all # or `.scoped` for ActiveRecord 3
end
# A search method.
def search_first_name
# If `"first_name"` was the first key in the options_hash,
# `query` here will be the base query, namely, `Person.all`.
query . where ( first_name : options [ :first_name ] )
end
# Another search method.
def search_last_name
# If `"last_name"` was the second key in the options_hash,
# `query` here will be whatever `search_first_name` returned.
query . where ( last_name : last_name )
end
end
PersonSearch.new("first_name" => "Gregor", "last_name" => "Mendel").results
호출하면 Person.all.where(first_name: "Gregor").where(last_name: "Mendel")
실행되고 반환됩니다. 결과 ActiveRecord::Relation
. last_name
옵션을 생략하거나 "last_name" => ""
제공한 경우 두 번째 where
추가되지 않습니다.
다음은 더 완전한 예제 검색 클래스입니다. Searchlight는 쿼리를 작성하지 않으므로 ORM이 지원하는 모든 작업을 자유롭게 수행할 수 있습니다 . (더 멋진 내용은 spec/support/book_search.rb
참조하세요.)
# app/searches/city_search.rb
class CitySearch < Searchlight :: Search
# `City` here is an ActiveRecord model
def base_query
City . includes ( :country )
end
# Reach into other tables
def search_continent
query . where ( '`countries`.`continent` = ?' , continent )
end
# Other kinds of queries
def search_country_name_like
query . where ( "`countries`.`name` LIKE ?" , "% #{ country_name_like } %" )
end
# .checked? considers "false", 0 and "0" to be false
def search_is_megacity
query . where ( "`cities`.`population` #{ checked? ( is_megacity ) ? '>=' : '<' } ?" , 10_000_000 )
end
end
다음은 몇 가지 검색 예시입니다.
CitySearch . new . results . to_sql
# => "SELECT `cities`.* FROM `cities` "
CitySearch . new ( "name" => "Nairobi" ) . results . to_sql
# => "SELECT `cities`.* FROM `cities` WHERE `cities`.`name` = 'Nairobi'"
CitySearch . new ( "country_name_like" => "aust" , "continent" => "Europe" ) . results . count # => 6
non_megas = CitySearch . new ( "is_megacity" => "false" )
non_megas . results . to_sql
# => "SELECT `cities`.* FROM `cities` WHERE (`cities`.`population` < 10000000"
non_megas . results . each do | city |
# ...
end
정의한 각 검색 방법에 대해 Searchlight는 해당 옵션 리더 방법을 정의합니다. 예를 들어 def search_first_name
추가하면 검색 클래스는 options["first_name"]
반환하거나 해당 키가 없으면 options[:first_name]
반환하는 .first_name
메서드를 얻습니다. 이는 주로 양식을 작성할 때 유용합니다.
"first_name"
및 :first_name
키를 서로 바꿔 사용할 수 있다고 간주하므로 둘 다 제공하면 Searchlight에서 오류가 발생합니다.
Searchlight는 검색에 제공된 옵션을 검토하기 위한 몇 가지 방법을 제공합니다.
raw_options
에는 인스턴스화된 내용이 정확히 포함되어 있습니다.options
비어 있지 않은 모든 raw_options
포함되어 있습니까 empty?
. 예를 들어 raw_options
가 categories: nil, tags: ["a", ""]
인 경우 옵션은 tags: ["a"]
입니다.empty?(value)
nil
, 공백 전용 문자열 또는 value.empty?
에서 true를 반환하는 모든 항목에 대해 true를 반환합니다. (예: 빈 배열)checked?(value)
부울을 반환합니다. 이는 대부분 !!value
처럼 작동하지만 0
, "0"
및 "false"
false
로 간주합니다. 마지막으로 Searchlight가 옵션을 어떻게 해석했는지 explain
하겠습니다. 예를 들어 book_search.explain
다음을 출력할 수 있습니다.
Initialized with `raw_options`: ["title_like", "author_name_like", "category_in",
"tags", "book_thickness", "parts_about_lolcats"]
Of those, the non-blank ones are available as `options`: ["title_like",
"author_name_like", "tags", "book_thickness", "in_print"]
Of those, the following have corresponding `search_` methods: ["title_like",
"author_name_like", "in_print"]. These would be used to build the query.
Blank options are: ["category_in", "parts_about_lolcats"]
Non-blank options with no corresponding `search_` method are: ["tags",
"book_thickness"]
때로는 기본 검색 옵션을 사용하는 것이 유용할 수 있습니다(예: "완료되지 않은 주문" 또는 "지난 달에 나열된 주택").
이는 options
재정의하여 수행할 수 있습니다. 예:
class BookSearch < SearchlightSearch
# def base_query...
def options
super . tap { | opts |
opts [ "in_print" ] ||= "either"
}
end
def search_in_print
return query if options [ "in_print" ] . to_s == "either"
query . where ( in_print : checked? ( options [ "in_print" ] ) )
end
end
기존 검색 클래스를 하위 클래스로 분류하고 다른 기본 쿼리를 사용하여 동일한 옵션을 모두 지원할 수 있습니다. 예를 들어 이는 단일 테이블 상속에 유용할 수 있습니다.
class VillageSearch < CitySearch
def base_query
Village . all
end
end
또는 super
사용하여 슈퍼클래스의 base_query
값을 가져와 수정할 수 있습니다.
class SmallTownSearch < CitySearch
def base_query
super . where ( "`cities`.`population` < ?" , 1_000 )
end
end
원하는 옵션을 서치라이트 검색에 제공할 수 있습니다. 일치하는 search_
메소드가 있는 메소드만 실행되는 메소드를 결정합니다. 예를 들어 AccountSearch.new("super_user" => true)
수행하여 제한된 결과를 찾으려면 쿼리를 작성할 때 options["super_user"]
선택했는지 확인하세요.
Searchlight는 Rails 양식과 잘 작동합니다. 다음과 같이 ActionView
어댑터를 포함하면 됩니다.
require "searchlight/adapters/action_view"
class MySearch < Searchlight :: Search
include Searchlight :: Adapters :: ActionView
# ...etc
end
그러면 form_for
와 함께 Searchlight::Search
사용이 활성화됩니다.
# app/views/cities/index.html.haml
...
= form_for ( @search , url : search_cities_path ) do | f |
% fieldset
= f . label :name , "Name"
= f . text_field :name
% fieldset
= f . label :country_name_like , "Country Name Like"
= f . text_field :country_name_like
% fieldset
= f . label :is_megacity , "Megacity?"
= f . select :is_megacity , [ [ 'Yes' , true ] , [ 'No' , false ] , [ 'Either' , '' ] ]
% fieldset
= f . label :continent , "Continent"
= f . select :continent , [ 'Africa' , 'Asia' , 'Europe' ] , include_blank : true
= f . submit "Search"
- @results . each do | city |
= render partial : 'city' , locals : { city : city }
양식에서 검색이 이해할 수 있는 옵션을 제출하는 한 컨트롤러에서 쉽게 연결할 수 있습니다.
# app/controllers/orders_controller.rb
class OrdersController < ApplicationController
def index
@search = OrderSearch . new ( search_params ) # For use in a form
@results = @search . results # For display along with form
end
protected
def search_params
# Ensure the user can only browse or search their own orders
( params [ :order_search ] || { } ) . merge ( user_id : current_user . id )
end
end
특정 버전에 대해 .travis.yml
확인하여 호환성 테스트를 진행 중인 Ruby 버전을 확인하세요.
애플리케이션의 Gemfile에 다음 줄을 추가하세요.
gem 'searchlight'
그런 다음 다음을 실행합니다.
$ bundle
또는 다음과 같이 직접 설치하십시오.
$ gem install searchlight
rake
테스트를 실행합니다. rake mutant
돌연변이를 이용한 돌연변이 테스트를 진행합니다.
git checkout -b my-new-feature
).git commit -am 'Add some feature'
)git push origin my-new-feature
)