From 86e980ea03a29727f7a97ea131edb35cda3f1b2f Mon Sep 17 00:00:00 2001 From: Douglas F Shearer Date: Fri, 25 Aug 2023 18:54:26 +0100 Subject: [PATCH 1/4] Modernise Readme * Make markdown * Remove begging * Remove hashrockets * Light reformatting --- README.md | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++ README.rdoc | 200 --------------------------------------------------- 2 files changed, 201 insertions(+), 200 deletions(-) create mode 100644 README.md delete mode 100644 README.rdoc diff --git a/README.md b/README.md new file mode 100644 index 0000000..2c1f5c0 --- /dev/null +++ b/README.md @@ -0,0 +1,201 @@ +# Acts As Indexed + +This plugin allows boolean-queried fulltext search to be added to any Rails +app with no dependencies and minimal setup. + +## Installation + +1. Add the gem to your Gemfile: + +```ruby +gem 'acts_as_indexed' +``` + +2. Run bundle install. + +## Upgrading + +When upgrading it is recommended you delete the index directory and allow it to +be rebuilt. + +## Usage + +### Setup + +Add `acts_as_indexed` to the top of any models you want to index, along with a +list of the fields you wish to be indexed. + +```ruby +class Post < ActiveRecord::Base + acts_as_indexed fields: [:title, :body] + + # ... +end +``` + +The fields are not limited to model fields, but can be any instance method of +the current model. + +```ruby +class User < ActiveRecord::Base + acts_as_indexed fields: [:address, :fullname] + + def fullname + self.firstname + ' ' + self.lastname + end + + ... +end +``` + +Any of the configuration options in the "Further Configuration" section can be +added as to the `acts_as_indexed` method call. these will override any defaults +or global configuration. + +you can specify a proc that needs to evaluate to true before the item gets +indexed. this is useful if you only want items with a certain state to be +included. the proc is passed the current object's instance so you are able to +test against that. + +for example, if you have a visible column that is false if the post is hidden, +or true if it is visible, you can filter the index by doing: + +class post < activerecord::base +acts_as_indexed fields: [:title, :body], if: proc.new { |post| post.visible? } +... +end + +### Searching + +#### With Relevance + +to search with the most relevant matches appearing first, call the +`find_with_index` method on your model, passing a query as the first argument. +the optional `ids_only` parameter, when set to true, will return only the ids +of any matching records. + +```ruby +# returns array of post objects ordered by relevance. +my_search_results = post.find_with_index('my search query') + +# pass any of the activerecord find options to the search. +my_search_results = post.find_with_index('my search query', { limit: 10}) # return the first 10 matches. + +# returns array of ids ordered by relevance. +my_search_results = post.find_with_index('my search query', {}, { ids_only: true }) # => [12,19,33... +``` + +#### Without Relevance (Scope) + +If the relevance of the results is not important, call the `with_query` named +scope on your model, passing a query as an argument. + +```ruby +# Returns array of Post objects. +my_search_results = Post.with_query('my search query') + +# Chain it with any number of ActiveRecord methods and named_scopes. +my_search_results = Post.public.with_query('my search query').find(:all, limit: 10) # return the first 10 matches which are public. +``` + +### Query Options + +The following query operators are supported: + +- AND :: This is the default option. 'cat dog' will find records matching 'cat' + AND 'dog'. +- NOT :: 'cat -dog' will find records matching 'cat' AND NOT 'dog' +- INCLUDE :: 'cat +me' will find records matching 'cat' and 'me', even if 'me' + is smaller than the `min_word_size` +- "" :: Quoted terms are matched as phrases. '"cat dog"' will find records + matching the whole phrase. Quoted terms can be preceded by the NOT operator; + 'cat -"big dog"' etc. Quoted terms can include words shorter than the + `min_word_size`. +- ^ :: Terms that begin with ^ will match records that contain a word starting + with the term. '^cat' will find matches containing 'cat', 'catapult', + 'caterpillar' etc. +- ^"" :: A quoted term that begins with ^ matches any phrase that begin with + this phrase. '^"cat d"' will find records matching the whole phrases "cat + dog" and "cat dinner". This type of search is useful for autocomplete inputs. + +### Pagination + +#### With Relevance + +Pagination is supported via the `paginate_search` method whose first argument +is the search query, followed by all the standard will_paginate arguments. + +```ruby +@images = Image.paginate_search('girl', page: 1, per_page: 5) +``` + +#### Without Relevance (Scope) + +Since `with_query` is a named scope, WillPaginate can be used in the normal +fashion. + +```ruby +@images = Image.with_query('girl').paginate(page: 1, per_page: 5) +``` + +### Further Configuration + +A config block can be provided in your environment files or initializers. +Example showing changing the min word size: + +```ruby +ActsAsIndexed.configure do |config| + config.min_word_size = 3 + # More config as required... +end +``` + +A full rundown of the available configuration options can be found in +`lib/acts_as_indexed/configuration.rb` + +## Caveats + +Acts as Indexed is intended to provide a simple solution to full text search +for modest-sized application setups. As a result it comes with some operational +caveats: + +- Only works with ASCII characters as does not fold/normalise UTF-8 characters. + A workaround for this is [described in this + Gist](https://gist.github.com/193903bb4e0d6e5debe1) +- Is not multi-process safe. If two processes write to the index at the same + time, the index will likely end up in an inconsistent state. +- Multiple servers (containers, Heroku Dynos, etc) will maintain their own copy + of the index. These will get out of sync as write operations occur. Use of a + shared filesystem prevents this. + +## RDoc Documentation + +View the rdoc documentation +online at [Rdoc.info](http://rdoc.info/projects/dougal/acts_as_indexed/). + +## Problems, Comments, Suggestions? + +Open a Github issue. If you have contribution you would like to make, please +discuss in a Github Issue prior to submitting a pull request. + +## Contributors + +A huge thanks to all the contributors to this library. Without them many +bugfixes and features wouldn't have happened. + +- Douglas F Shearer - http://douglasfshearer.com +- Thomas Pomfret +- Philip Arndt +- Fernanda Lopes +- Alex Coles +- Myles Eftos +- Edward Anderson +- Florent Guilleux +- Ben Anderson +- Theron Toomey +- Uģis Ozols +- Gabriel Namiman +- Roman Samoilov +- David Turner +- Pascal Hurni +- Ryan Kopf diff --git a/README.rdoc b/README.rdoc deleted file mode 100644 index 2a21bda..0000000 --- a/README.rdoc +++ /dev/null @@ -1,200 +0,0 @@ -= acts_as_indexed - -If you find this plugin useful, please consider a donation to show your -support! - -http://www.paypal.com/cgi-bin/webscr?cmd=_send-money - -Paypal address: mailto:dougal.s@gmail.com - - -== Instructions - -This plugin allows boolean-queried fulltext search to be added to any Rails -app with no dependencies and minimal setup. - - -== Resources - -=== Installation - -==== Add to your Gemfile - - gem 'acts_as_indexed' - -Run bundle install. Done. - -==== Still on Rails 2.x.x without Bundler? - - ./script/plugin install git://github.com/dougal/acts_as_indexed.git - -If you don't have git installed, but still want the plugin, you can download -the plugin from the GitHub page (http://github.com/dougal/acts_as_indexed) and -unpack it into the vendor/plugins directory of your rails app. - -=== Upgrading - -When upgrading to a new version of acts_as_indexed it is recommended you -delete the index directory and allow it to be rebuilt. - - -== Usage - -=== Setup - -Add +acts_as_indexed+ to the top of any models you want to index, along with a -list of the fields you wish to be indexed. - - class Post < ActiveRecord::Base - acts_as_indexed :fields => [:title, :body] - - ... - end - -The fields are not limited to model fields, but can be any instance method of -the current model. - - class User < ActiveRecord::Base - acts_as_indexed :fields => [:address, :fullname] - - def fullname - self.firstname + ' ' + self.lastname - end - - ... - end - -Any of the configuration options in the Further Configuration section can be -added as to the acts_as_indexed method call. These will override any defaults -or global configuration. - -You can specify proc that needs to evaluate to true before the item gets -indexed. This is useful if you only want items with a certain state to be -included. The Proc is passed the current object's instance so you are able to -test against that. - -For example, if you have a visible column that is false if the post is hidden, -or true if it is visible, you can filter the index by doing: - - class Post < ActiveRecord::Base - acts_as_indexed :fields => [:title, :body], :if => Proc.new { |post| post.visible? } - ... - end - -=== Searching - -==== With Relevance - -To search with the most relevant matches appearing first, call the -+find_with_index+ method on your model, passing a query as the first argument. -The optional +ids_only+ parameter, when set to true, will return only the IDs -of any matching records. - - # Returns array of Post objects ordered by relevance. - my_search_results = Post.find_with_index('my search query') - - # Pass any of the ActiveRecord find options to the search. - my_search_results = Post.find_with_index('my search query',{:limit => 10}) # return the first 10 matches. - - # Returns array of IDs ordered by relevance. - my_search_results = Post.find_with_index('my search query',{},{:ids_only => true}) # => [12,19,33... - -==== Without Relevance (Scope) - -If the relevance of the results is not important, call the +with_query+ named -scope on your model, passing a query as an argument. - - # Returns array of Post objects. - my_search_results = Post.with_query('my search query') - - # Chain it with any number of ActiveRecord methods and named_scopes. - my_search_results = Post.public.with_query('my search query').find(:all, :limit => 10) # return the first 10 matches which are public. - -=== Query Options - -The following query operators are supported: - -AND :: This is the default option. 'cat dog' will find records matching 'cat' AND 'dog'. -NOT :: 'cat -dog' will find records matching 'cat' AND NOT 'dog' -INCLUDE :: 'cat +me' will find records matching 'cat' and 'me', even if 'me' is smaller than the +min_word_size+ -"" :: Quoted terms are matched as phrases. '"cat dog"' will find records matching the whole phrase. Quoted terms can be preceded by the NOT operator; 'cat -"big dog"' etc. Quoted terms can include words shorter than the +min_word_size+. -^ :: Terms that begin with ^ will match records that contain a word starting with the term. '^cat' will find matches containing 'cat', 'catapult', 'caterpillar' etc. -^"" :: A quoted term that begins with ^ matches any phrase that begin with this phrase. '^"cat d"' will find records matching the whole phrases "cat dog" and "cat dinner". This type of search is useful for autocomplete inputs. - -=== Pagination - -==== With Relevance - -Pagination is supported via the +paginate_search+ method whose first argument is the search query, followed by all the standard will_paginate arguments. - - @images = Image.paginate_search('girl', :page => 1, :per_page => 5) - -==== Without Relevance (Scope) - -Since +with_query+ is a named scope, WillPaginate can be used in the normal -fashion. - - @images = Image.with_query('girl').paginate(:page => 1, :per_page => 5) - -=== Further Configuration - -A config block can be provided in your environment files or initializers. -Example showing changing the min word size: - - ActsAsIndexed.configure do |config| - config.min_word_size = 3 - # More config as required... - end - -A full rundown of the available configuration options can be found in -lib/acts_as_indexed/configuration.rb - -=== Heroku Support - -Acts As Indexed supports Heroku out-of-the-box. The index is created in the -tmp directory, which is the only writeable part of the Heroku dyno filesystem. -Please read Heroku's documentation( -https://devcenter.heroku.com/articles/read-only-filesystem) regarding their file-system. - -== RDoc Documentation - -View the rdoc documentation -online[http://rdoc.info/projects/dougal/acts_as_indexed/]. - - -== Problems, Comments, Suggestions? - -All of the above are most welcome. mailto:dougal.s@gmail.com - - -== Contributors - -A huge thanks to all the contributors to this library. Without them many -bugfixes and features wouldn't have happened. - -* Douglas F Shearer - http://douglasfshearer.com -* Thomas Pomfret -* Philip Arndt -* Fernanda Lopes -* Alex Coles -* Myles Eftos -* Edward Anderson -* Florent Guilleux -* Ben Anderson -* Theron Toomey -* Uģis Ozols -* Gabriel Namiman -* Roman Samoilov -* David Turner -* Pascal Hurni -* Ryan Kopf - - -== Unicode (UTF8) Support - -At the moment acts_as_indexed only works with Unicode characters when used in -the following way: - - https://gist.github.com/193903bb4e0d6e5debe1 - -I have rewritten the tokenization process to allow easier handling of this in the future. From 74024f5a5e3a7ce1d97b29de7891ebda243abda9 Mon Sep 17 00:00:00 2001 From: Douglas F Shearer Date: Fri, 25 Aug 2023 19:25:41 +0100 Subject: [PATCH 2/4] More formatting and wording improvements. --- README.md | 82 +++++++++++++++++++++++++++---------------------------- 1 file changed, 40 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 2c1f5c0..834c581 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Acts As Indexed This plugin allows boolean-queried fulltext search to be added to any Rails -app with no dependencies and minimal setup. +app with no additional dependencies and minimal setup. ## Installation @@ -11,7 +11,7 @@ app with no dependencies and minimal setup. gem 'acts_as_indexed' ``` -2. Run bundle install. +2. Run `bundle install`. ## Upgrading @@ -38,32 +38,30 @@ the current model. ```ruby class User < ActiveRecord::Base - acts_as_indexed fields: [:address, :fullname] + acts_as_indexed fields: [:address, :full_name] - def fullname - self.firstname + ' ' + self.lastname + def full_name + [forename, surname].join(' ') end - ... + # ... end ``` -Any of the configuration options in the "Further Configuration" section can be -added as to the `acts_as_indexed` method call. these will override any defaults -or global configuration. +Any of the configuration options in the [Further +Configuration](#further-configuration) section can be added as to the +`acts_as_indexed` method call. these will override any defaults or global +configuration. -you can specify a proc that needs to evaluate to true before the item gets -indexed. this is useful if you only want items with a certain state to be -included. the proc is passed the current object's instance so you are able to -test against that. +A `proc` can be assigned to the `if` key which determines whether a record is +added to the index. -for example, if you have a visible column that is false if the post is hidden, +For example, if you have a `is_visible` column that is false if the post is hidden, or true if it is visible, you can filter the index by doing: -class post < activerecord::base -acts_as_indexed fields: [:title, :body], if: proc.new { |post| post.visible? } -... -end +```ruby +acts_as_indexed fields: [:title, :body], if: proc.new { |post| post.is_visible? } +``` ### Searching @@ -76,13 +74,13 @@ of any matching records. ```ruby # returns array of post objects ordered by relevance. -my_search_results = post.find_with_index('my search query') +post.find_with_index('my search query') # pass any of the activerecord find options to the search. -my_search_results = post.find_with_index('my search query', { limit: 10}) # return the first 10 matches. +post.find_with_index('my search query', { limit: 10 }) # returns array of ids ordered by relevance. -my_search_results = post.find_with_index('my search query', {}, { ids_only: true }) # => [12,19,33... +post.find_with_index('my search query', {}, { ids_only: true }) # => [12,19,33... ``` #### Without Relevance (Scope) @@ -92,31 +90,31 @@ scope on your model, passing a query as an argument. ```ruby # Returns array of Post objects. -my_search_results = Post.with_query('my search query') +Post.with_query('my search query') # Chain it with any number of ActiveRecord methods and named_scopes. -my_search_results = Post.public.with_query('my search query').find(:all, limit: 10) # return the first 10 matches which are public. +Post.public.with_query('my search query').find(:all, limit: 10) # return the first 10 matches which are public. ``` ### Query Options The following query operators are supported: -- AND :: This is the default option. 'cat dog' will find records matching 'cat' - AND 'dog'. -- NOT :: 'cat -dog' will find records matching 'cat' AND NOT 'dog' -- INCLUDE :: 'cat +me' will find records matching 'cat' and 'me', even if 'me' - is smaller than the `min_word_size` -- "" :: Quoted terms are matched as phrases. '"cat dog"' will find records - matching the whole phrase. Quoted terms can be preceded by the NOT operator; - 'cat -"big dog"' etc. Quoted terms can include words shorter than the +- This is the default option. `cat dog` will find records matching `cat` AND + `dog`. +- `cat -dog` will find records matching `cat` AND NOT `dog` +- 'cat +me' will find records matching `cat` and `me`, even if `me` is smaller + than the `min_word_size` +- Quoted terms are matched as phrases. `"cat dog"` will find records matching + the whole phrase. Quoted terms can be preceded by the NOT operator; `cat +-"big dog"` etc. Quoted terms can include words shorter than the `min_word_size`. -- ^ :: Terms that begin with ^ will match records that contain a word starting - with the term. '^cat' will find matches containing 'cat', 'catapult', - 'caterpillar' etc. -- ^"" :: A quoted term that begins with ^ matches any phrase that begin with - this phrase. '^"cat d"' will find records matching the whole phrases "cat - dog" and "cat dinner". This type of search is useful for autocomplete inputs. +- Terms that begin with `^` will match records that contain a word starting + with the term. `^cat` will find matches containing `cat`, `catapult`, + `caterpillar` etc. +- A quoted term that begins with `^` matches any phrase that begin with + this phrase. `^"cat d"` will find records matching the whole phrases 'cat + dog' and `cat dinner`. This type of search is useful for autocomplete inputs. ### Pagination @@ -126,16 +124,16 @@ Pagination is supported via the `paginate_search` method whose first argument is the search query, followed by all the standard will_paginate arguments. ```ruby -@images = Image.paginate_search('girl', page: 1, per_page: 5) +Image.paginate_search('girl', page: 1, per_page: 5) ``` #### Without Relevance (Scope) -Since `with_query` is a named scope, WillPaginate can be used in the normal +Since `with_query` is an ActiveRecord scope, WillPaginate can be used in the normal fashion. ```ruby -@images = Image.with_query('girl').paginate(page: 1, per_page: 5) +Image.with_query('girl').paginate(page: 1, per_page: 5) ``` ### Further Configuration @@ -151,7 +149,7 @@ end ``` A full rundown of the available configuration options can be found in -`lib/acts_as_indexed/configuration.rb` +`lib/acts_as_indexed/configuration.rb`. ## Caveats @@ -159,7 +157,7 @@ Acts as Indexed is intended to provide a simple solution to full text search for modest-sized application setups. As a result it comes with some operational caveats: -- Only works with ASCII characters as does not fold/normalise UTF-8 characters. +- Only works with ASCII characters as does not fold/normali`e UTF-8 characters. A workaround for this is [described in this Gist](https://gist.github.com/193903bb4e0d6e5debe1) - Is not multi-process safe. If two processes write to the index at the same From 269944c5a10b47ff169e33f571adfbe7c29a0e34 Mon Sep 17 00:00:00 2001 From: Douglas F Shearer Date: Fri, 25 Aug 2023 20:24:48 +0100 Subject: [PATCH 3/4] More formatting and wording. --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 834c581..22c34bc 100644 --- a/README.md +++ b/README.md @@ -15,15 +15,15 @@ gem 'acts_as_indexed' ## Upgrading -When upgrading it is recommended you delete the index directory and allow it to +When upgrading it is recommended to delete the index directory and allow it to be rebuilt. ## Usage ### Setup -Add `acts_as_indexed` to the top of any models you want to index, along with a -list of the fields you wish to be indexed. +Add `acts_as_indexed` to any models to be indexed, along with a list of the +fields to be indexed. ```ruby class Post < ActiveRecord::Base @@ -56,8 +56,8 @@ configuration. A `proc` can be assigned to the `if` key which determines whether a record is added to the index. -For example, if you have a `is_visible` column that is false if the post is hidden, -or true if it is visible, you can filter the index by doing: +For example, if you have a `is_visible` column then non-visible records can be +excluded from the index with: ```ruby acts_as_indexed fields: [:title, :body], if: proc.new { |post| post.is_visible? } @@ -67,7 +67,7 @@ acts_as_indexed fields: [:title, :body], if: proc.new { |post| post.is_visible? #### With Relevance -to search with the most relevant matches appearing first, call the +To search with the most relevant matches appearing first, call the `find_with_index` method on your model, passing a query as the first argument. the optional `ids_only` parameter, when set to true, will return only the ids of any matching records. @@ -100,10 +100,10 @@ Post.public.with_query('my search query').find(:all, limit: 10) # return the fir The following query operators are supported: -- This is the default option. `cat dog` will find records matching `cat` AND +- `cat dog` will find records matching `cat` AND `dog`. - `cat -dog` will find records matching `cat` AND NOT `dog` -- 'cat +me' will find records matching `cat` and `me`, even if `me` is smaller +- `cat +me` will find records matching `cat` and `me`, even if `me` is smaller than the `min_word_size` - Quoted terms are matched as phrases. `"cat dog"` will find records matching the whole phrase. Quoted terms can be preceded by the NOT operator; `cat From d9c2af828ac02c32a48f8659a2bb590d02552a30 Mon Sep 17 00:00:00 2001 From: Douglas F Shearer Date: Sat, 26 Aug 2023 13:31:41 +0100 Subject: [PATCH 4/4] Generate rdoc with markdown files. --- Rakefile | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Rakefile b/Rakefile index 06ee952..42b3a68 100644 --- a/Rakefile +++ b/Rakefile @@ -51,9 +51,11 @@ begin RDoc::Task.new(:rdoc) do |rdoc| rdoc.rdoc_dir = 'rdoc' rdoc.title = 'ActsAsIndexed' - rdoc.options << '--line-numbers' << '--inline-source' - rdoc.rdoc_files.include('README.rdoc') - rdoc.rdoc_files.include('CHANGELOG') + rdoc.main = "README.md" + rdoc.options << "--line-numbers" + + rdoc.rdoc_files.include('README.md') + rdoc.rdoc_files.include('CHANGELOG.md') rdoc.rdoc_files.include('lib/**/*.rb') end rescue LoadError