search_generator 0.4
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.
- data/LICENSE +30 -0
- data/USAGE +50 -0
- data/search_generator.rb +97 -0
- data/templates/README +81 -0
- data/templates/app/controllers/controller.rb +48 -0
- data/templates/app/views/layouts/layout.rhtml +25 -0
- data/templates/app/views/opensearch/_generic.rhtml +11 -0
- data/templates/app/views/opensearch/description.rxml +9 -0
- data/templates/app/views/opensearch/rss.rhtml +23 -0
- data/templates/app/views/search/_generic.rhtml +7 -0
- data/templates/app/views/search/index.rhtml +14 -0
- data/templates/lib/search_system.rb +20 -0
- data/templates/script/indexer +82 -0
- data/templates/script/searcher +38 -0
- metadata +78 -0
data/LICENSE
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
Copyright (c) 2005 Jeremy Hinegardner <jeremy@hinegardner.org>
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are
|
6
|
+
met:
|
7
|
+
|
8
|
+
* Redistributions of source code must retain the above copyright
|
9
|
+
notice, this list of conditions and the following disclaimer.
|
10
|
+
|
11
|
+
* Redistributions in binary form must reproduce the above copyright
|
12
|
+
notice, this list of conditions and the following disclaimer in
|
13
|
+
the documentation and/or other materials provided with the
|
14
|
+
distribution.
|
15
|
+
|
16
|
+
* The name of the author may not be used to endorse or promote
|
17
|
+
products derived from this software without specific prior written
|
18
|
+
permission from the author.
|
19
|
+
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
21
|
+
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
22
|
+
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
23
|
+
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
24
|
+
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
25
|
+
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
26
|
+
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
27
|
+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
28
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
29
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
30
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/USAGE
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
NAME
|
2
|
+
|
3
|
+
search - a search engine that can be added to any Rails application
|
4
|
+
|
5
|
+
SYNOPSIS
|
6
|
+
|
7
|
+
search [Search name] [options]
|
8
|
+
|
9
|
+
Good names, anything that means search would be good. Search,
|
10
|
+
Forage, Frisk or Shakedown.
|
11
|
+
|
12
|
+
search has an additional option --inspect which will travers your
|
13
|
+
Model objects and tell you which ones could be made searchable
|
14
|
+
|
15
|
+
DESCRIPTION
|
16
|
+
|
17
|
+
This generator integrates the SimpleSearch search engine into a
|
18
|
+
rails applicaiton. In addition, once configured for you site, it
|
19
|
+
provides an Open Search (http://opensearch.a9.com/) compatible
|
20
|
+
interface.
|
21
|
+
|
22
|
+
Included:
|
23
|
+
|
24
|
+
* a Controller to manage search request
|
25
|
+
* Views to customize for your Model objects
|
26
|
+
- regular html results
|
27
|
+
- Open Search RSS style results
|
28
|
+
* an indexer to run periodically against your data to keep the
|
29
|
+
search indexes up to date.
|
30
|
+
* a README on the additional hand coded tasks to intgerate
|
31
|
+
the search engine with your application
|
32
|
+
|
33
|
+
EXAMPLE
|
34
|
+
|
35
|
+
./script/generate search Search
|
36
|
+
|
37
|
+
This will create a basic search engine framework for you to
|
38
|
+
customize for your site.
|
39
|
+
|
40
|
+
./script/generate search Search --inspect
|
41
|
+
|
42
|
+
This will report which ones of your Model classes could be made
|
43
|
+
searchable.
|
44
|
+
|
45
|
+
DEPENDENCIES
|
46
|
+
|
47
|
+
- SimpleSearch (http://www.chadfowler.com/SimpleSearch)
|
48
|
+
Install : gem install SimpleSearch
|
49
|
+
|
50
|
+
|
data/search_generator.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
class SearchGenerator < Rails::Generator::NamedBase
|
2
|
+
|
3
|
+
def add_options!(opt)
|
4
|
+
opt.on('-i', '--inspect','Inspect models to see which ones can be searchable') { |value| options[:inspect] = true }
|
5
|
+
end
|
6
|
+
|
7
|
+
def inspect
|
8
|
+
puts <<howto_make_searchable
|
9
|
+
The following Models, and their associated fields,
|
10
|
+
in your application can be made searchable. Just copy
|
11
|
+
and paste the 'make_searchable' line from the report below
|
12
|
+
into the approrpaite models file (also reported below).
|
13
|
+
|
14
|
+
The 'make_searchable' line reports all the searchable fields
|
15
|
+
in that model. You probably do not want all of the fields
|
16
|
+
in your Model, so edit the line as appropriate
|
17
|
+
|
18
|
+
IMPORTANT:
|
19
|
+
|
20
|
+
Make sure to the following line to the top of any model file
|
21
|
+
you edit to make searchable.
|
22
|
+
|
23
|
+
require_dependency "search_system"
|
24
|
+
|
25
|
+
howto_make_searchable
|
26
|
+
|
27
|
+
Dir.glob(File.join(@destination_root,"app/models/*.rb")).each do |rbfile|
|
28
|
+
bname = File.basename(rbfile,'.rb')
|
29
|
+
classname = Inflector.camelize(bname)
|
30
|
+
classvar = eval(classname)
|
31
|
+
if classvar.respond_to?(:descends_from_active_record?) and
|
32
|
+
classvar.descends_from_active_record? then
|
33
|
+
attrs = classvar.columns_hash.keys.collect { |a| ":" + a.to_s}
|
34
|
+
|
35
|
+
puts "-----[ #{classname} => #{File.expand_path(rbfile)} ]-----"
|
36
|
+
if classvar.respond_to?(:searchable_fields) then
|
37
|
+
fields = classvar.searchable_fields
|
38
|
+
if fields.nil? or fields.size == 0 then
|
39
|
+
puts "#{classname} is searchable, but no fields are selected."
|
40
|
+
puts
|
41
|
+
puts " make_searchable [ #{attrs.join(", ")} ]"
|
42
|
+
else
|
43
|
+
fields = fields.collect { |f| ":" + f.to_s }
|
44
|
+
puts "#{classname} has the following fields marked as searchable:"
|
45
|
+
puts
|
46
|
+
puts " [ #{fields.join(", ")} ]"
|
47
|
+
end
|
48
|
+
else
|
49
|
+
puts " make_searchable [ #{attrs.join(", ")} ]"
|
50
|
+
end
|
51
|
+
puts
|
52
|
+
end
|
53
|
+
end
|
54
|
+
puts
|
55
|
+
end
|
56
|
+
|
57
|
+
def remove
|
58
|
+
manifest.rewind(Rails::Generator::Command::Destroy)
|
59
|
+
end
|
60
|
+
|
61
|
+
def manifest
|
62
|
+
record do |m|
|
63
|
+
|
64
|
+
if options[:inspect] then
|
65
|
+
m.inspect
|
66
|
+
else
|
67
|
+
# system
|
68
|
+
m.template "lib/search_system.rb", "lib/search_system.rb"
|
69
|
+
|
70
|
+
# controller
|
71
|
+
m.template "app/controllers/controller.rb", "app/controllers/#{file_name}_controller.rb"
|
72
|
+
|
73
|
+
# layout
|
74
|
+
m.template "app/views/layouts/layout.rhtml", "app/views/layouts/#{file_name}.rhtml"
|
75
|
+
|
76
|
+
# views
|
77
|
+
m.directory File.join("app/views", class_path, file_name)
|
78
|
+
m.template "app/views/search/index.rhtml", "app/views/#{file_name}/index.rhtml"
|
79
|
+
m.template "app/views/search/_generic.rhtml", "app/views/#{file_name}/_generic.rhtml"
|
80
|
+
|
81
|
+
m.directory "app/views/opensearch"
|
82
|
+
m.template "app/views/opensearch/rss.rhtml", "app/views/opensearch/rss.rhtml"
|
83
|
+
m.template "app/views/opensearch/description.rxml", "app/views/opensearch/description.rxml"
|
84
|
+
m.template "app/views/opensearch/_generic.rhtml", "app/views/opensearch/_generic.rhtml"
|
85
|
+
|
86
|
+
# scripts
|
87
|
+
m.template "script/indexer", "script/indexer", :chmod => 0755
|
88
|
+
m.template "script/searcher", "script/searcher", :chmod => 0755
|
89
|
+
|
90
|
+
# custom to this generation install README
|
91
|
+
m.template "README", "README_SEARCH"
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
data/templates/README
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
== Installation
|
2
|
+
|
3
|
+
After the search engine has been generated, there are still tasks to
|
4
|
+
fully integrate the search engine into your site.
|
5
|
+
|
6
|
+
=== Inspect
|
7
|
+
|
8
|
+
execute:
|
9
|
+
|
10
|
+
script/generate search <%= class_name %> --inspect
|
11
|
+
|
12
|
+
This will report which of your models can be made searchable. Feel
|
13
|
+
free to run it many times.
|
14
|
+
|
15
|
+
=== Models
|
16
|
+
|
17
|
+
In each of your Models in which you want to have the content
|
18
|
+
searched, and are ActiveRecord descendants, you need to add a
|
19
|
+
require_dependency "search_system". Then you are able to invoke the
|
20
|
+
class method 'make_searchable' with an Array of field symbols.
|
21
|
+
|
22
|
+
For example:
|
23
|
+
|
24
|
+
require_dependency "search_system"
|
25
|
+
class Article < ActiveRecord::Base
|
26
|
+
make_searchable [ :title, :author, :content ]
|
27
|
+
end
|
28
|
+
|
29
|
+
=== Routes
|
30
|
+
|
31
|
+
Add the following lines to your config/routes.rb to hook in search
|
32
|
+
|
33
|
+
# allow for searching view the route
|
34
|
+
map.connect '<%= file_name %>/:search_terms/:count', :controller => '<%= file_name %>', :action => 'index', :count => '-1'
|
35
|
+
|
36
|
+
# allow for Open Search RSS feeds searching
|
37
|
+
map.connect 'rss/opensearch/description.xml', :controller => '<%= file_name %>', :action => 'description'
|
38
|
+
map.connect 'rss/opensearch/:search_terms/:count', :controller => '<%= file_name %>', :action => 'rss', :count => '-1'
|
39
|
+
|
40
|
+
=== Layouts
|
41
|
+
|
42
|
+
A 'very' basic layout/<%= file_name %>.rhtml is installed that shows the basic
|
43
|
+
results. This should be customized for your site.
|
44
|
+
|
45
|
+
=== Views
|
46
|
+
|
47
|
+
Two new views have been added to your rails application.
|
48
|
+
|
49
|
+
1. Search
|
50
|
+
|
51
|
+
This view should be customized for your site so that the search
|
52
|
+
results fit in well with your site. The default _partial
|
53
|
+
template that exists will render out a generic table showing all
|
54
|
+
the fields and their values for the search results. You should
|
55
|
+
customize the index.rhtml file to integrate with your site, and
|
56
|
+
you should create a _partial.rhtml for each Model that you could
|
57
|
+
have search results for.
|
58
|
+
|
59
|
+
That is, if you have an application with an Article Model, you
|
60
|
+
should create a _article.rhtml file in this view to render out
|
61
|
+
the results of your search that are of Article class.
|
62
|
+
|
63
|
+
The generic index.rhtml that is present will automatically use
|
64
|
+
the appropriate _parital.rhtml file based upon the class name if
|
65
|
+
it is present.
|
66
|
+
|
67
|
+
2. Open Search
|
68
|
+
|
69
|
+
This view is to return results in the format of OpenSearch RSS
|
70
|
+
(http://opensearch.a9.com/spec/opensearchrss/1.0/). This
|
71
|
+
combined with the rss/opensearch Routes above and the
|
72
|
+
description.rxml file found in this view should provide you with
|
73
|
+
an OpenSearch-able site.
|
74
|
+
|
75
|
+
Again, you should create a _partial.rhtml file in this directory
|
76
|
+
for each Model you have that can return search results.
|
77
|
+
|
78
|
+
Also, the description.xml file should be configure with your
|
79
|
+
sites information.
|
80
|
+
|
81
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require_dependency "search_system"
|
2
|
+
|
3
|
+
class <%= class_name %>Controller < ApplicationController
|
4
|
+
layout "<%= file_name %>" , :except => [:rss, :description]
|
5
|
+
|
6
|
+
def index
|
7
|
+
search
|
8
|
+
end
|
9
|
+
|
10
|
+
#-----------------------------------------------------------------------
|
11
|
+
# search through the index, get the ActiveRecord's that match and
|
12
|
+
# return those to the caller
|
13
|
+
#-----------------------------------------------------------------------
|
14
|
+
def search
|
15
|
+
@search_terms = @params['search_terms'].split
|
16
|
+
@count = @params['count'].to_i || -1
|
17
|
+
|
18
|
+
empty_contents = MockContents.new
|
19
|
+
simple_index = Search::Simple::Searcher.load(empty_contents,"#{File.dirname(__FILE__)}/../../db/search_cache")
|
20
|
+
|
21
|
+
# what to return to the caller
|
22
|
+
@results = Array.new
|
23
|
+
|
24
|
+
# TODO: sort by score at some point ?
|
25
|
+
search_results = simple_index.find_words(@search_terms)
|
26
|
+
|
27
|
+
if search_results.contains_matches then
|
28
|
+
search_results.results.sort.each do |result|
|
29
|
+
(classname,pk_id,column) = result.name.split(".")
|
30
|
+
classvar = eval(classname)
|
31
|
+
@results << classvar.find(pk_id)
|
32
|
+
break if @count > 0 and @results.size >= @count
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
@results.uniq!
|
37
|
+
end
|
38
|
+
|
39
|
+
def description
|
40
|
+
@headers["Content-Type"] = "text/xml"
|
41
|
+
render 'opensearch/description'
|
42
|
+
end
|
43
|
+
def rss
|
44
|
+
@headers["Content-Type"] = "text/xml"
|
45
|
+
search
|
46
|
+
render 'opensearch/rss'
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
2
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
3
|
+
<head>
|
4
|
+
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
5
|
+
<title>SITE TITLE</title>
|
6
|
+
</head>
|
7
|
+
<body>
|
8
|
+
|
9
|
+
<h1>Search SITE</h1>
|
10
|
+
|
11
|
+
<form action="/search" method="get">
|
12
|
+
<%% if @search_terms.size > 0 %>
|
13
|
+
<input type="text" name="search_terms" value="<%%= @search_terms.join(" ") %>" size="30" />
|
14
|
+
<%% else %>
|
15
|
+
<input type="text" name="search_terms" value="" size="30" />
|
16
|
+
<%% end %>
|
17
|
+
</form>
|
18
|
+
|
19
|
+
<hr />
|
20
|
+
|
21
|
+
<h2>Results</h2>
|
22
|
+
<%%= @content_for_layout %>
|
23
|
+
|
24
|
+
</body>
|
25
|
+
</html>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<title><%%= generic.class.name %></title>
|
2
|
+
<link>INSERT CODE TO GET LINK TO THIS ITEM</link>
|
3
|
+
<description>
|
4
|
+
<div class="record">
|
5
|
+
<table>
|
6
|
+
<%% generic.class.searchable_fields.each do |field| %>
|
7
|
+
<tr> <th><%%= field.to_s %></th> <td><%%= generic.send(field) %></td> </tr>
|
8
|
+
<%% end %>
|
9
|
+
</table>
|
10
|
+
</div>
|
11
|
+
</description>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
xml.OpenSearchDescription(:xmlns => "http://a9.com/-/spec/opensearchrss/1.0/") do
|
2
|
+
xml.url("http://localhost:3000/opensearch/{searchTerms}/{count}")
|
3
|
+
xml.format("http://a9.com/-/spec/opensearchrss/1.0/")
|
4
|
+
xml.shortname("site shortname")
|
5
|
+
xml.longname("site longname")
|
6
|
+
xml.description("site description")
|
7
|
+
xml.syndicationright("open")
|
8
|
+
xml.adultcontent("false")
|
9
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<rss version="1.0" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/">
|
3
|
+
<channel>
|
4
|
+
<title>Site title</title>
|
5
|
+
<link><%%= @request.env['REQUEST_URI'] %></link>
|
6
|
+
<description>Site description</description>
|
7
|
+
<language>en-us</language>
|
8
|
+
<copyright>&copy;2003-2005, site its affiliates.</copyright>
|
9
|
+
<openSearch:totalResults><%%= @results.size %></openSearch:totalResults>
|
10
|
+
<openSearch:startIndex>1</openSearch:startIndex>
|
11
|
+
<openSearch:itemsPerPage><%%= @results.size %></openSearch:itemsPerPage>
|
12
|
+
|
13
|
+
|
14
|
+
<%% for result in @results %>
|
15
|
+
<%% begin %>
|
16
|
+
<%%= render_partial "opensearch/#{Inflector.underscore(result.class)}", result %>
|
17
|
+
<%% rescue ActionView::ActionViewError %>
|
18
|
+
<%%= render_partial "opensearch/generic", result %>
|
19
|
+
<%% end %>
|
20
|
+
<%% end %>
|
21
|
+
</channel>
|
22
|
+
</rss>
|
23
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<%% @results.each do |result| %>
|
2
|
+
<hr />
|
3
|
+
|
4
|
+
<%%# Try to render a partial based upon the class name %>
|
5
|
+
<%%# but if that does not work, reneder a generic one %>
|
6
|
+
|
7
|
+
<%% begin %>
|
8
|
+
<%%= render_partial Inflector.underscore(result.class), result %>
|
9
|
+
<%% rescue ActionView::ActionViewError %>
|
10
|
+
<pre>No parital available for <%%= result.class %>, using generic </pre>
|
11
|
+
<%%= render_partial "generic", result %>
|
12
|
+
<%% end %>
|
13
|
+
|
14
|
+
<%% end %>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_gem "SimpleSearch"
|
2
|
+
|
3
|
+
class ActiveRecord::Base
|
4
|
+
|
5
|
+
def self.make_searchable(list_of_field_symbols)
|
6
|
+
@searchable_fields = list_of_field_symbols
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.searchable_fields
|
10
|
+
@searchable_fields
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
class MockContents
|
16
|
+
def latest_mtime
|
17
|
+
Time.at(0)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,82 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "#{File.dirname(__FILE__)}/../config/environment"
|
4
|
+
|
5
|
+
require_gem "SimpleSearch"
|
6
|
+
|
7
|
+
#-----------------------------------------------------------------------
|
8
|
+
# the container for all the contents to be indexed
|
9
|
+
#-----------------------------------------------------------------------
|
10
|
+
contents = Search::Simple::Contents.new
|
11
|
+
|
12
|
+
#-----------------------------------------------------------------------
|
13
|
+
# the current time is used to invalidate the Searcher's cache so it will
|
14
|
+
# force an indexing
|
15
|
+
#-----------------------------------------------------------------------
|
16
|
+
ts = Time.now
|
17
|
+
|
18
|
+
#-----------------------------------------------------------------------
|
19
|
+
# iterate over all the files in the models directory looking for those
|
20
|
+
# Models that are descendants of ActiveRecord
|
21
|
+
#-----------------------------------------------------------------------
|
22
|
+
puts "Searching for Models..."
|
23
|
+
Dir.glob("#{File.dirname(__FILE__)}/../app/models/*.rb").each do |rbfile|
|
24
|
+
|
25
|
+
bname = File.basename(rbfile,'.rb')
|
26
|
+
classname = Inflector.camelize(bname)
|
27
|
+
classvar = eval(classname)
|
28
|
+
|
29
|
+
if classvar.respond_to?(:descends_from_active_record?) and
|
30
|
+
classvar.descends_from_active_record? then
|
31
|
+
puts "\tFound #{classname} "
|
32
|
+
|
33
|
+
|
34
|
+
#---------------------------------------------------------------
|
35
|
+
# if the class that is a dscendant from ActiveRecord also has
|
36
|
+
# the special method :searchable_fields then those fields are
|
37
|
+
# considered searchable
|
38
|
+
#---------------------------------------------------------------
|
39
|
+
if classvar.respond_to?(:searchable_fields) then
|
40
|
+
|
41
|
+
if not classvar.searchable_fields.nil?
|
42
|
+
|
43
|
+
cnames = classvar.searchable_fields.collect {|c| c.to_s}
|
44
|
+
puts "\t\t- searching columns #{cnames.join(",")}"
|
45
|
+
indexed_records = 0
|
46
|
+
|
47
|
+
#-----------------------------------------------------------
|
48
|
+
# now we interate over all the records of the particular
|
49
|
+
# type and record all the information for indexing.
|
50
|
+
#-----------------------------------------------------------
|
51
|
+
classvar.find_all.each do |ar|
|
52
|
+
record_id = "#{classname}.#{ar.send(classvar.primary_key)}"
|
53
|
+
indexed_records = indexed_records + 1
|
54
|
+
|
55
|
+
classvar.searchable_fields.each do |column|
|
56
|
+
column_id = "#{record_id}.#{column.to_s}"
|
57
|
+
data = ar.send(column)
|
58
|
+
|
59
|
+
# only index non-nil content
|
60
|
+
if not data.nil? then
|
61
|
+
contents << Search::Simple::Content.new(ar.send(column), column_id, ts)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
puts "\t\t- indexed #{indexed_records} records"
|
67
|
+
else
|
68
|
+
puts "\t\t- no make_searchable fields"
|
69
|
+
end
|
70
|
+
|
71
|
+
else
|
72
|
+
puts "\t\t- class is not searchable"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
#-----------------------------------------------------------------------
|
78
|
+
# this is where the actual indexing is done. There previous sections of
|
79
|
+
# code just collected the data to do the indexing.
|
80
|
+
#-----------------------------------------------------------------------
|
81
|
+
s = Search::Simple::Searcher.load(contents,"#{File.dirname(__FILE__)}/../db/search_cache")
|
82
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "#{File.dirname(__FILE__)}/../config/environment"
|
4
|
+
|
5
|
+
require_dependency "search_system"
|
6
|
+
|
7
|
+
#-----------------------------------------------------------------------
|
8
|
+
# grab the first word on the command line as the term to search for
|
9
|
+
#-----------------------------------------------------------------------
|
10
|
+
search_terms = Array.new
|
11
|
+
if ARGV.size > 0 then
|
12
|
+
search_terms << ARGV[0]
|
13
|
+
else
|
14
|
+
puts "no search term given, searching for 'ruby'"
|
15
|
+
search_terms << "ruby"
|
16
|
+
end
|
17
|
+
|
18
|
+
#-----------------------------------------------------------------------
|
19
|
+
# a mock contents so that we use the cache
|
20
|
+
#-----------------------------------------------------------------------
|
21
|
+
contents = MockContents.new
|
22
|
+
s = Search::Simple::Searcher.load(contents,"#{File.dirname(__FILE__)}/../db/search_cache")
|
23
|
+
|
24
|
+
#-----------------------------------------------------------------------
|
25
|
+
# do the search
|
26
|
+
#-----------------------------------------------------------------------
|
27
|
+
sr = s.find_words(search_terms)
|
28
|
+
|
29
|
+
if sr.contains_matches then
|
30
|
+
puts "Score\t#File"
|
31
|
+
sr.results.sort.each do |res|
|
32
|
+
puts "#{res.score}\t#{res.name}"
|
33
|
+
end
|
34
|
+
else
|
35
|
+
puts sr.warnings
|
36
|
+
puts "No matches"
|
37
|
+
end
|
38
|
+
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.10
|
3
|
+
specification_version: 1
|
4
|
+
name: search_generator
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: "0.4"
|
7
|
+
date: 2005-04-11
|
8
|
+
summary: "[Rails] Search generator."
|
9
|
+
require_paths:
|
10
|
+
- "."
|
11
|
+
email: jeremy@hinegardner.org
|
12
|
+
homepage:
|
13
|
+
rubyforge_project:
|
14
|
+
description: Generates Rails code implementing a search system using SimpleSearch for your Rails app.
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: false
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
-
|
22
|
+
- ">"
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 0.0.0
|
25
|
+
version:
|
26
|
+
platform: ruby
|
27
|
+
authors:
|
28
|
+
- Jeremy Hinegardner
|
29
|
+
files:
|
30
|
+
- USAGE
|
31
|
+
- LICENSE
|
32
|
+
- search_generator.rb
|
33
|
+
- templates/README
|
34
|
+
- templates/lib
|
35
|
+
- templates/app
|
36
|
+
- templates/script
|
37
|
+
- templates/lib/search_system.rb
|
38
|
+
- templates/app/controllers
|
39
|
+
- templates/app/views
|
40
|
+
- templates/app/controllers/controller.rb
|
41
|
+
- templates/app/views/search
|
42
|
+
- templates/app/views/opensearch
|
43
|
+
- templates/app/views/layouts
|
44
|
+
- templates/app/views/search/index.rhtml
|
45
|
+
- templates/app/views/search/_generic.rhtml
|
46
|
+
- templates/app/views/opensearch/_generic.rhtml
|
47
|
+
- templates/app/views/opensearch/rss.rhtml
|
48
|
+
- templates/app/views/opensearch/description.rxml
|
49
|
+
- templates/app/views/layouts/layout.rhtml
|
50
|
+
- templates/script/indexer
|
51
|
+
- templates/script/searcher
|
52
|
+
test_files: []
|
53
|
+
rdoc_options: []
|
54
|
+
extra_rdoc_files: []
|
55
|
+
executables: []
|
56
|
+
extensions: []
|
57
|
+
requirements: []
|
58
|
+
dependencies:
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: rails
|
61
|
+
version_requirement:
|
62
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
63
|
+
requirements:
|
64
|
+
-
|
65
|
+
- ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 0.10.0
|
68
|
+
version:
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: SimpleSearch
|
71
|
+
version_requirement:
|
72
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
73
|
+
requirements:
|
74
|
+
-
|
75
|
+
- ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 0.5.0
|
78
|
+
version:
|