sander6-enygma 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. data/README.markdown +186 -0
  2. metadata +53 -0
data/README.markdown ADDED
@@ -0,0 +1,186 @@
1
+ # Enygma: a Sphinx toolset #
2
+
3
+ *NOTE: Enygma is currently in a state of disarray, since I hacked it together just enough to work with ActiveRecord. The specs shouldn't run and coverage is inexcusable, which I feel bad about. I'll clean things up incrementally. Until then, consider it in alpha.*
4
+
5
+ Sphinx is awesome, but it's sometimes kind of unwieldly to use, requiring a bunch of moving parts just to see what a certain Sphinx query would yank out of your database. Some solutions for working with Sphinx exist, but it's hard to justify spinning up an entire new Rails project just to search through some HTML documents you've got lying on your hard drive.
6
+
7
+ For this reason, Enygma exists to be an awesome little Sphinx toolset usable just about anywhere.
8
+
9
+ ## Requirements ##
10
+
11
+ Eyngma requires the following things:
12
+ - Sphinx v.0.9.9rc1 or higher
13
+
14
+ For some types of geospatial searching, Enygma requires GeoRuby.
15
+
16
+ The Enygma database adapters require the related libraries. For example, the `Enygma::Adapters::ActiveRecordAdapter` requires the active_record gem, and the `Enygma::Adapters::SequelAdapter` requires the sequel gem.
17
+
18
+ ## Indexing ##
19
+
20
+ For the time being, Enygma doesn't build a conf file or help set up your indexes for you.
21
+
22
+ This is actually not that hard to do yourself, and you'll find you've got much more control over what gets indexed than a Sphinx solution such as, say, thinking_sphinx offers. Read [the Sphinx documentation](http://www.sphinxsearch.com/docs/manual-0.9.9.html) for information on writing your own conf file. Once you've done it yourself, you'll feel like a genius.
23
+
24
+ That being said, Enygma plans to eventually support guided Sphinx configuration.
25
+
26
+ ## Usage ##
27
+
28
+ #### Configuration ####
29
+
30
+ Take your favorite class and `include Enygma`. Then declare your global and class-specific configuration. For example:
31
+
32
+ Enygma::Configuration.global do
33
+ adapter :sequel
34
+ database "postgres://user@localhost/db"
35
+ end
36
+
37
+ class SearchyThing
38
+ include Enygma
39
+
40
+ configure_enygma do
41
+ sphinx[:host] = 'localhost'
42
+ sphinx[:port] = 3312
43
+
44
+ table :posts, :indexes => [ :posts_idx, :comments_idx ]
45
+ table :comments, :indexes => [ :comments_idx ]
46
+ end
47
+ end
48
+
49
+ This appends the `search` method to the included class.
50
+
51
+ #### Searching ####
52
+
53
+ To search all tables:
54
+
55
+ SearchyThing.search.for("funtimes")
56
+
57
+ This returns a hash of results for each table.
58
+
59
+ # => { :posts => [...], :comments => [...] }
60
+
61
+ To search a specific table:
62
+
63
+ SearchyThing.search(:posts).for("funtimes")
64
+
65
+ This just returns an array of posts (hashes or instances of a class, depending on your adapter).
66
+
67
+ # => [ { :id => 1, ... }, { :id => 2, ... }, ... ]
68
+
69
+ Adding filters:
70
+
71
+ SearchyThing.search(:comments).for("funtimes").filter("post_id", 1..10)
72
+ SearchyThing.search(:comments).for("funtimes").exclude("post_id", 50..100)
73
+
74
+ Returning only certain attributes from the matches records:
75
+
76
+ SearchyThing.search(:comments).for("funtimes").return(:author_id)
77
+
78
+ Iterating over the records:
79
+
80
+ SearchyThing.search(:posts).for("funtimes").each do |post|
81
+ post.tag!(Tag.new("funtimes!"))
82
+ end
83
+
84
+ #### Geospatial Searching ####
85
+
86
+ Enygma's geospatial searching abilities are naive at present.
87
+
88
+ To search in a given radius of a latitude/longitude pair:
89
+
90
+ SearchyThing.search(:places).within(500).of(40.747778, -73.985556)
91
+
92
+ Where `500` means 500 meters. You can set different units like so:
93
+
94
+ SearchyThing.search(:places).within(1000).feet.of(40.747778, -73.985556)
95
+
96
+ Latitudes and longitudes should be given in degrees, which will be converted to the radians required by Sphinx.
97
+
98
+ Instead of a lat/lng pair, you can pass a GeoRuby::SimpleFeatures::Point.
99
+
100
+ point = GeoRuby::SimpleFeatures::Point.from_lon_lat(-73.985556, 40.747778)
101
+ SearchyThing.search(:places).within(500).of(point)
102
+
103
+ Or you can pass any object which responds to `coordinates`, which should in turn respond to both `lat` and `lng` (good for, say, ActiveRecord models with a point attribute).
104
+
105
+ arbys = Place.filter(:name => "Arby's").first
106
+ SearchyThing.search(:places).within(500).of(arbys)
107
+
108
+ Should you want to, you can search within an annulus (the area between two concentric circles) by passing a range as the radius argument.
109
+
110
+ SearchyThing.search(:places).around(point, 500..1000)
111
+
112
+ #### Kicker Methods ####
113
+
114
+ An Engyma::Search instance (the things that's returned when you call `search`) will delay execution of the Sphinx query and database query until you call the 'kicker' method `run`. If you send the Search object a missing method, it will run the search and then pass the method on the the return value of the query (what's returned differs slightly based on your database adapter, see below).
115
+
116
+ For example:
117
+
118
+ Model.search.for("Arby's") # => returns an Enygma::Search object
119
+ Model.search.for("Arby's").run # => returns an array of Models
120
+ Model.search.for("Arby's").first # => returns the first Model found
121
+
122
+ A gotcha: if somehow you have, for example, an ActiveRecord::Base named\_scope that matches the name of a Search method, say `filter`, you should explicitly call `run` on the Search object.
123
+
124
+ Model.search.for("Arby's").filter(...) # => sets a Sphinx filter
125
+ Model.search.for("Arby's").run.filter(...) # => runs the filter named_scope
126
+
127
+ ### Resources ###
128
+
129
+ Subclasses of ActiveRecord::Base and Sequel::Model and classes including Datamapper::Resource can be extended using Enygma::Resource to give them searching superpowers.
130
+
131
+ Including Enygma::Resource in one of the above types of classes will relfect on the table associated with the class and automatically scope Enygma searches to that table and its related indexes.
132
+
133
+ class Post < ActiveRecord::Base
134
+ include Enygma::Resource
135
+ end
136
+
137
+ Post.search.for("turkey").each { |post| puts post.title }
138
+
139
+ If a class includes Enygma::Resource, it can only search on one table at a time (meaning that it can only return records of a single type), but can still search for those records using multiple indexes. For example:
140
+
141
+ class Post < ActiveRecord::Base
142
+ include Enygma::Resource
143
+
144
+ configure_enygma do
145
+ index :posts
146
+ index :posts_delta
147
+ end
148
+ end
149
+
150
+ More in-depth per-adapter documentation detailed below:
151
+
152
+ #### ActiveRecord::Base ####
153
+
154
+ An ActiveRecord::Base subclass that includes Enygma::Resource will, instead of returning the actual results of the database query, return an anonymous scope searching for record ids in the set of ids returned by Sphinx. This helps ease integration with will\_paginate, as well as allowing the appending of additional named\_scopes.
155
+
156
+ For example, to get all Models and their Associations in one go:
157
+
158
+ Model.search.for("turkey").all(:include => :association)
159
+
160
+ #### Sequel::Model ####
161
+
162
+ Like above, a Sequel::Model with Enygma::Resource will not automatically kick off the query, but just return a prepared Sequel::Query object for further filtering.
163
+
164
+ #### Datamapper ####
165
+
166
+ Nothing special about Datamapper so far.
167
+
168
+ ### Using Enygma in a controller ###
169
+
170
+ What follows is an example of using Enygma in an ActionController::Base subclass in a Rails project, but it should apply to most any controller (or any class, for that matter).
171
+
172
+ class PostsController < ApplicationController
173
+ include Enygma
174
+
175
+ configure_enygma do
176
+ adapter :active_record
177
+ database Post
178
+ table :posts
179
+ index :posts
180
+ index :posts_delta
181
+ end
182
+
183
+ def index
184
+ @posts = search(:posts).for(params[:search]).all(:include => :comments)
185
+ end
186
+ end
metadata ADDED
@@ -0,0 +1,53 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sander6-enygma
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.5
5
+ platform: ruby
6
+ authors:
7
+ - Sander Hartlage
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-04-08 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: sander6 at github dot com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.markdown
24
+ files:
25
+ - README.markdown
26
+ has_rdoc: true
27
+ homepage: http://github.com/sander6/enygma
28
+ post_install_message:
29
+ rdoc_options: []
30
+
31
+ require_paths:
32
+ - lib
33
+ required_ruby_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: "0"
38
+ version:
39
+ required_rubygems_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ requirements: []
46
+
47
+ rubyforge_project: ""
48
+ rubygems_version: 1.2.0
49
+ signing_key:
50
+ specification_version: 2
51
+ summary: A Sphinx search toolset
52
+ test_files: []
53
+