search_generator 0.4 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
data/USAGE CHANGED
@@ -9,13 +9,13 @@ SYNOPSIS
9
9
  Good names, anything that means search would be good. Search,
10
10
  Forage, Frisk or Shakedown.
11
11
 
12
- search has an additional option --inspect which will travers your
12
+ search has an additional option --inspect which will traverse your
13
13
  Model objects and tell you which ones could be made searchable
14
14
 
15
15
  DESCRIPTION
16
16
 
17
17
  This generator integrates the SimpleSearch search engine into a
18
- rails applicaiton. In addition, once configured for you site, it
18
+ rails application. In addition, once configured for you site, it
19
19
  provides an Open Search (http://opensearch.a9.com/) compatible
20
20
  interface.
21
21
 
@@ -27,7 +27,7 @@ DESCRIPTION
27
27
  - Open Search RSS style results
28
28
  * an indexer to run periodically against your data to keep the
29
29
  search indexes up to date.
30
- * a README on the additional hand coded tasks to intgerate
30
+ * a README on the additional hand coded tasks to integrate
31
31
  the search engine with your application
32
32
 
33
33
  EXAMPLE
data/search_generator.rb CHANGED
@@ -73,6 +73,10 @@ howto_make_searchable
73
73
  # layout
74
74
  m.template "app/views/layouts/layout.rhtml", "app/views/layouts/#{file_name}.rhtml"
75
75
 
76
+
77
+ # config
78
+ m.template "config/search.yml", "config/search.yml"
79
+
76
80
  # views
77
81
  m.directory File.join("app/views", class_path, file_name)
78
82
  m.template "app/views/search/index.rhtml", "app/views/#{file_name}/index.rhtml"
data/templates/README CHANGED
@@ -26,6 +26,29 @@
26
26
  make_searchable [ :title, :author, :content ]
27
27
  end
28
28
 
29
+ === Configuration
30
+
31
+ A default configuration file 'search.yml' in installed in your
32
+ application config directory. It should work as-is, but if you want
33
+ to move the simple search index file to a different location or
34
+ rename it, feel free to do so. Just be aware that the index file
35
+ must be relative to RAILS_ROOT.
36
+
37
+ Yes, if you look at the index file it does appear that other
38
+ backends could be available, but for now, there are no other search
39
+ backends besides SimpleSearch.
40
+
41
+ === Index the data
42
+
43
+ Once your Models class are updated with make_searchable you'll need
44
+ to run script/indexer to crawl through your data and create the
45
+ index that is used to search the data.
46
+
47
+ Currently, this index is not automatically created and any new
48
+ content that is added to the database will not get indexed. You
49
+ should have cron, or a scheduled task run the indexer periodically
50
+ to keep your index in sync with your data.
51
+
29
52
  === Routes
30
53
 
31
54
  Add the following lines to your config/routes.rb to hook in search
@@ -37,6 +60,9 @@
37
60
  map.connect 'rss/opensearch/description.xml', :controller => '<%= file_name %>', :action => 'description'
38
61
  map.connect 'rss/opensearch/:search_terms/:count', :controller => '<%= file_name %>', :action => 'rss', :count => '-1'
39
62
 
63
+ Remember to put these routes before the default route or you will
64
+ get errors.
65
+
40
66
  === Layouts
41
67
 
42
68
  A 'very' basic layout/<%= file_name %>.rhtml is installed that shows the basic
@@ -61,21 +87,21 @@
61
87
  the results of your search that are of Article class.
62
88
 
63
89
  The generic index.rhtml that is present will automatically use
64
- the appropriate _parital.rhtml file based upon the class name if
90
+ the appropriate _partial.rhtml file based upon the class name if
65
91
  it is present.
66
92
 
67
93
  2. Open Search
68
94
 
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.
95
+ This view is to return results in the format of OpenSearch RSS
96
+ (http://opensearch.a9.com/spec/opensearchrss/1.0/). This
97
+ combined with the rss/opensearch Routes above and the
98
+ description.rxml file found in this view should provide you with
99
+ an OpenSearch-able site.
74
100
 
75
- Again, you should create a _partial.rhtml file in this directory
76
- for each Model you have that can return search results.
101
+ Again, you should create a _partial.rhtml file in this directory
102
+ for each Model you have that can return search results.
77
103
 
78
- Also, the description.xml file should be configure with your
79
- sites information.
104
+ Also, the description.xml file should be configure with your
105
+ sites information.
80
106
 
81
107
 
@@ -12,16 +12,34 @@ class <%= class_name %>Controller < ApplicationController
12
12
  # return those to the caller
13
13
  #-----------------------------------------------------------------------
14
14
  def search
15
- @search_terms = @params['search_terms'].split
15
+ @search_config = YAML.load(File.open(File.join(RAILS_ROOT,"config","search.yml")))
16
+
17
+ if @params['search_terms'].nil? then
18
+ @search_terms = @search_config['default_search_terms']
19
+ else
20
+ @search_terms = @params['search_terms'].split
21
+ end
22
+
16
23
  @count = @params['count'].to_i || -1
17
-
24
+
25
+ self.send("#{@search_config['search_backend']}_search")
26
+ end
27
+
28
+ def simple_search
29
+
18
30
  empty_contents = MockContents.new
19
- simple_index = Search::Simple::Searcher.load(empty_contents,"#{File.dirname(__FILE__)}/../../db/search_cache")
31
+
32
+ index_filename = File.join(RAILS_ROOT,@search_config['simple_backend']['index_filename'])
33
+
34
+ if not File.exists?(index_filename) then
35
+ raise "content index file (#{File.expand_path(index_filename)}) does not exist. Did you run scripts/indexer ?"
36
+ end
37
+
38
+ simple_index = Search::Simple::Searcher.load(empty_contents,index_filename)
20
39
 
21
40
  # what to return to the caller
22
41
  @results = Array.new
23
42
 
24
- # TODO: sort by score at some point ?
25
43
  search_results = simple_index.find_words(@search_terms)
26
44
 
27
45
  if search_results.contains_matches then
@@ -36,6 +54,7 @@ class <%= class_name %>Controller < ApplicationController
36
54
  @results.uniq!
37
55
  end
38
56
 
57
+
39
58
  def description
40
59
  @headers["Content-Type"] = "text/xml"
41
60
  render 'opensearch/description'
@@ -0,0 +1,10 @@
1
+ ---
2
+ search_backend: "simple"
3
+
4
+ simple_backend:
5
+ index_filename: db/simple_search_index
6
+
7
+ default_search_terms:
8
+ - ruby
9
+ - search
10
+
@@ -1,82 +1,97 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "#{File.dirname(__FILE__)}/../config/environment"
3
+ # load the rails environment
4
+ require File.join(File.dirname(__FILE__),"..","config", "environment")
4
5
 
5
- require_gem "SimpleSearch"
6
+ puts "Loading config [#{File.expand_path(File.join(RAILS_ROOT,"config","search.yml"))}]"
7
+ SEARCH_CONFIG = YAML.load(File.open(File.join(RAILS_ROOT,"config","search.yml")))
6
8
 
7
9
  #-----------------------------------------------------------------------
8
- # the container for all the contents to be indexed
10
+ # define how to build a index using SimpleSearch
9
11
  #-----------------------------------------------------------------------
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)
12
+ def simple_index
13
+ require_gem "SimpleSearch"
14
+
15
+ #-----------------------------------------------------------------------
16
+ # the container for all the contents to be indexed
17
+ #-----------------------------------------------------------------------
18
+ contents = Search::Simple::Contents.new
19
+
20
+ #-----------------------------------------------------------------------
21
+ # the current time is used to invalidate the Searcher's cache so it will
22
+ # force an indexing
23
+ #-----------------------------------------------------------------------
24
+ ts = Time.now
25
+
26
+ #-----------------------------------------------------------------------
27
+ # iterate over all the files in the models directory looking for those
28
+ # Models that are descendants of ActiveRecord
29
+ #-----------------------------------------------------------------------
30
+ puts "Searching for Models..."
31
+ Dir.glob(File.join(RAILS_ROOT,"app","models","*.rb")).each do |rbfile|
32
+
33
+ bname = File.basename(rbfile,'.rb')
34
+ classname = Inflector.camelize(bname)
35
+ classvar = eval(classname)
36
+
37
+ if classvar.respond_to?(:descends_from_active_record?) and
38
+ classvar.descends_from_active_record? then
39
+ puts "\tFound #{classname} "
40
+
41
+
42
+ #---------------------------------------------------------------
43
+ # if the class that is a dscendant from ActiveRecord also has
44
+ # the special method :searchable_fields then those fields are
45
+ # considered searchable
46
+ #---------------------------------------------------------------
47
+ if classvar.respond_to?(:searchable_fields) then
48
+
49
+ if not classvar.searchable_fields.nil?
50
+
51
+ cnames = classvar.searchable_fields.collect {|c| c.to_s}
52
+ puts "\t\t- searching columns #{cnames.join(",")}"
53
+ indexed_records = 0
54
+
55
+ #-----------------------------------------------------------
56
+ # now we interate over all the records of the particular
57
+ # type and record all the information for indexing.
58
+ #-----------------------------------------------------------
59
+ classvar.find_all.each do |ar|
60
+ record_id = "#{classname}.#{ar.send(classvar.primary_key)}"
61
+ indexed_records = indexed_records + 1
62
+
63
+ classvar.searchable_fields.each do |column|
64
+ column_id = "#{record_id}.#{column.to_s}"
65
+ data = ar.send(column)
66
+
67
+ # only index non-nil content
68
+ if not data.nil? then
69
+ contents << Search::Simple::Content.new(ar.send(column), column_id, ts)
70
+ end
62
71
  end
63
72
  end
64
- end
65
73
 
66
- puts "\t\t- indexed #{indexed_records} records"
67
- else
68
- puts "\t\t- no make_searchable fields"
69
- end
74
+ puts "\t\t- indexed #{indexed_records} records"
75
+ else
76
+ puts "\t\t- no make_searchable fields"
77
+ end
70
78
 
71
- else
72
- puts "\t\t- class is not searchable"
79
+ else
80
+ puts "\t\t- class is not searchable"
81
+ end
73
82
  end
74
83
  end
75
- end
76
84
 
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")
85
+ #-----------------------------------------------------------------------
86
+ # this is where the actual indexing is done. There previous sections of
87
+ # code just collected the data to do the indexing.
88
+ #-----------------------------------------------------------------------
89
+ index_file = File.join(RAILS_ROOT,SEARCH_CONFIG['simple_backend']['index_filename'])
90
+ puts "creating index file #{File.expand_path(index_file)}"
91
+ s = Search::Simple::Searcher.load(contents,index_file)
92
+ end
82
93
 
94
+ case SEARCH_CONFIG['search_backend']
95
+ when 'simple'
96
+ simple_index
97
+ end
@@ -1,8 +1,12 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "#{File.dirname(__FILE__)}/../config/environment"
3
+ require File.join(File.dirname(__FILE__),"..","config","environment")
4
4
 
5
5
  require_dependency "search_system"
6
+ #-----------------------------------------------------------------------
7
+ # load the config
8
+ #-----------------------------------------------------------------------
9
+ search_config = YAML.load(File.open(File.join(RAILS_ROOT,"config","search.yml")))
6
10
 
7
11
  #-----------------------------------------------------------------------
8
12
  # grab the first word on the command line as the term to search for
@@ -11,28 +15,31 @@ search_terms = Array.new
11
15
  if ARGV.size > 0 then
12
16
  search_terms << ARGV[0]
13
17
  else
14
- puts "no search term given, searching for 'ruby'"
15
- search_terms << "ruby"
18
+ puts "no search term given, searching for #{search_config['default_search_terms'].join(',')}"
19
+ search_terms = search_config['default_search_terms']
16
20
  end
17
21
 
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")
22
+ case search_config['search_backend']
23
+ when 'simple'
24
+ #-----------------------------------------------------------------------
25
+ # a mock contents so that we use the cache
26
+ #-----------------------------------------------------------------------
27
+ contents = MockContents.new
28
+ s = Search::Simple::Searcher.load(contents,search_config['simple_backend']['index_filename'])
23
29
 
24
- #-----------------------------------------------------------------------
25
- # do the search
26
- #-----------------------------------------------------------------------
27
- sr = s.find_words(search_terms)
30
+ #-----------------------------------------------------------------------
31
+ # do the search
32
+ #-----------------------------------------------------------------------
33
+ sr = s.find_words(search_terms)
28
34
 
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}"
35
+ if sr.contains_matches then
36
+ puts "Score\t#File"
37
+ sr.results.sort.each do |res|
38
+ puts "#{res.score}\t#{res.name}"
39
+ end
40
+ else
41
+ puts sr.warnings
42
+ puts "No matches"
33
43
  end
34
- else
35
- puts sr.warnings
36
- puts "No matches"
44
+
37
45
  end
38
-
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.10
3
3
  specification_version: 1
4
4
  name: search_generator
5
5
  version: !ruby/object:Gem::Version
6
- version: "0.4"
7
- date: 2005-04-11
6
+ version: "0.5"
7
+ date: 2005-04-24
8
8
  summary: "[Rails] Search generator."
9
9
  require_paths:
10
10
  - "."
@@ -30,10 +30,12 @@ files:
30
30
  - USAGE
31
31
  - LICENSE
32
32
  - search_generator.rb
33
+ - templates/config
33
34
  - templates/README
34
35
  - templates/lib
35
36
  - templates/app
36
37
  - templates/script
38
+ - templates/config/search.yml
37
39
  - templates/lib/search_system.rb
38
40
  - templates/app/controllers
39
41
  - templates/app/views