DSL สำหรับการสร้างวัตถุการค้นหา
ออบเจ็กต์การค้นหาเริ่มต้นด้วยคอลเลกชันเริ่มต้น (ขอบเขต) และอนุญาตให้กรองตามตัวเลือกต่างๆ
ใช้:
เพิ่มบรรทัดนี้ลงใน Gemfile ของแอปพลิเคชันของคุณ:
gem 'search_object'
แล้วดำเนินการ:
$ bundle
หรือติดตั้งด้วยตัวเองเป็น:
$ gem install search_object
การเปลี่ยนแปลงมีอยู่ใน CHANGELOG.md
เพียงรวม SearchObject.module
และกำหนดตัวเลือกการค้นหาของคุณ:
class PostSearch
include SearchObject . module
scope { Post . all }
option ( :name ) { | scope , value | scope . where name : value }
option ( :created_at ) { | scope , dates | scope . created_after dates }
option ( :published , false ) { | scope , value | value ? scope . unopened : scope . opened }
end
จากนั้นคุณสามารถค้นหาขอบเขตที่กำหนดได้:
search = PostSearch . new ( filters : params [ :filters ] )
# accessing search options
search . name # => name option
search . created_at # => created at option
# accessing results
search . count # => number of found results
search . results? # => is there any results found
search . results # => found results
# params for url generations
search . params # => option values
search . params opened : false # => overwrites the 'opened' option
คุณสามารถดูตัวอย่างคุณลักษณะและปลั๊กอินที่สำคัญที่สุดได้ ที่นี่
ปลั๊กอินสนับสนุน SearchObject
ซึ่งถูกส่งผ่านไปยังเมธอด SearchObject.module
ปลั๊กอินเป็นเพียงโมดูล Ruby ธรรมดาซึ่งรวมอยู่ใน SearchObject.module
จะอยู่ภายใต้โมดูล SearchObject::Plugin
ปลั๊กอินแบ่งหน้าที่เรียบง่ายจริงๆ ซึ่งใช้วิธีการธรรมดา .limit
limit และ .offset
class ProductSearch
include SearchObject . module ( :paging )
scope { Product . all }
option :name
option :category_name
# per page defaults to 10
per_page 10
# range of values is also possible
min_per_page 5
max_per_page 100
end
search = ProductSearch . new ( filters : params [ :filters ] , page : params [ :page ] , per_page : params [ :per_page ] )
search . page # => page number
search . per_page # => per page (10)
search . results # => paginated page results
แน่นอนถ้าคุณต้องการปลั๊กอินการแบ่งหน้าที่ซับซ้อนมากขึ้นคุณสามารถใช้:
include SearchObject . module ( :will_paginate )
include SearchObject . module ( :kaminari )
ให้คุณกรองตัวเลือกที่กำหนดไว้ล่วงหน้า
class ProductSearch
include SearchObject . module ( :enum )
scope { Product . all }
option :order , enum : %w( popular date )
private
# Gets called when order with 'popular' is given
def apply_order_with_popular ( scope )
scope . by_popularity
end
# Gets called when order with 'date' is given
def apply_order_with_date ( scope )
scope . by_date
end
# (optional) Gets called when invalid enum is given
def handle_invalid_order ( scope , invalid_value )
scope
end
end
ขยายวัตถุการค้นหาของคุณด้วย ActiveModel
เพื่อให้คุณสามารถใช้ในรูปแบบ Rails ได้
class ProductSearch
include SearchObject . module ( :model )
scope { Product . all }
option :name
option :category_name
end
<%# in some view: %>
<%= form_for ProductSearch.new do |form| %>
<% form.label :name %>
<% form.text_field :name %>
<% form.label :category_name %>
<% form.text_field :category_name %>
<% end %>
ติดตั้งเป็นอัญมณีแยกต่างหาก โดยได้รับการออกแบบให้ทำงานกับ GraphQL:
gem 'search_object_graphql'
class PostResolver
include SearchObject . module ( :graphql )
type PostType
scope { Post . all }
option ( :name , type : types . String ) { | scope , value | scope . where name : value }
option ( :published , type : types . Boolean ) { | scope , value | value ? scope . published : scope . unpublished }
end
แก้ไขความเจ็บปวดในการจัดการกับคุณลักษณะและทิศทางการเรียงลำดับ
class ProductSearch
include SearchObject . module ( :sorting )
scope { Product . all }
sort_by :name , :price
end
search = ProductSearch . new ( filters : { sort : 'price desc' } )
search . results # => Product sorted my price DESC
search . sort_attribute # => 'price'
search . sort_direction # => 'desc'
# Smart sort checking
search . sort? ( 'price' ) # => true
search . sort? ( 'price desc' ) # => true
search . sort? ( 'price asc' ) # => false
# Helpers for dealing with reversing sort direction
search . reverted_sort_direction # => 'asc'
search . sort_direction_for ( 'price' ) # => 'asc'
search . sort_direction_for ( 'name' ) # => 'desc'
# Params for sorting links
search . sort_params_for ( 'name' )
บ่อยครั้งคุณจะต้องการผลการค้นหา:
ProductSearch . new ( params ) . results == ProductSearch . results ( params )
class ProductSearch
include SearchObject . module
end
# first arguments is treated as scope (if no scope option is provided)
search = ProductSearch . new ( scope : Product . visible , filters : params [ :f ] )
search . results # => includes only visible products
class ProductSearch
include SearchObject . module
scope { Product . all }
# nil values returned from option blocks are ignored
option ( :sold ) { | scope , value | scope . sold if value }
end
class ProductSearch
include SearchObject . module
scope { Product . all }
option :name # automaticly applies => { |scope, value| scope.where name: value unless value.blank? }
end
class ProductSearch
include SearchObject . module
scope { Product . all }
option ( :date ) { | scope , value | scope . by_date parse_dates ( value ) }
private
def parse_dates ( date_string )
# some "magic" method to parse dates
end
end
class ProductSearch
include SearchObject . module
scope { Product . all }
option :date , with : :parse_dates
private
def parse_dates ( scope , value )
# some "magic" method to parse dates
end
end
class ProductSearch
include SearchObject . module
scope { RemoteEndpoint . fetch_product_as_hashes }
option ( :name ) { | scope , value | scope . select { | product | product [ :name ] == value } }
option ( :category ) { | scope , value | scope . select { | product | product [ :category ] == value } }
end
คุณสามารถมีขอบเขตที่ละเอียดได้โดยการเขียนทับวิธี initialize
:
class ProductSearch
include SearchObject . module
option :name
option :category_name
def initialize ( user , options = { } )
super options . merge ( scope : Product . visible_to ( user ) )
end
end
หรือคุณสามารถเพิ่มการแบ่งหน้าแบบธรรมดาโดยเขียนทับทั้ง initialize
และ fetch_results
(ใช้สำหรับการดึงผลลัพธ์):
class ProductSearch
include SearchObject . module
scope { Product . all }
option :name
option :category_name
attr_reader :page
def initialize ( filters = { } , page = 0 )
super filters
@page = page . to_i . abs
end
def fetch_results
super . paginate page : @page
end
end
คุณสามารถแตกคลาสการค้นหาพื้นฐานสำหรับแอปพลิเคชันของคุณได้
class BaseSearch
include SearchObject . module
# ... options and configuration
end
จากนั้นใช้มันเหมือน:
class ProductSearch < BaseSearch
scope { Product }
end
git checkout -b my-new-feature
)git commit -am 'Add some feature'
)git push origin my-new-feature
)rake
)ดูรายชื่อผู้ร่วมให้ข้อมูลที่เข้าร่วมโครงการนี้ด้วย
ใบอนุญาตเอ็มไอที