Commit c4cde5101957a38693cb767e781240b9d851e935

Authored by Braulio Bhavamitra
1 parent 22bc741d

Revert "Revert "Merge branch 'merge-requests/25'""

This reverts commit 4e223943ab159d8fa7faf4b042ec3121d74ed32e.

Conflicts:

	app/controllers/my_profile/profile_members_controller.rb
	config/solr.yml.dist
	features/step_definitions/noosfero_steps.rb
	lib/tasks/test.rake
	test/functional/profile_members_controller_test.rb
	test/unit/category_finder_test.rb
Showing 234 changed files with 9071 additions and 3867 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 234 files displayed.

@@ -40,6 +40,9 @@ commands and make sure you understand what you are doing): @@ -40,6 +40,9 @@ commands and make sure you understand what you are doing):
40 cp config/database.yml.sqlite3 config/database.yml 40 cp config/database.yml.sqlite3 config/database.yml
41 # create tmp directory if it doesn't exist 41 # create tmp directory if it doesn't exist
42 mkdir tmp 42 mkdir tmp
  43 + # download and start Solr
  44 + rake solr:download
  45 + rake solr:start
43 # create the development database 46 # create the development database
44 rake db:schema:load 47 rake db:schema:load
45 # run pending migrations 48 # run pending migrations
@@ -13,7 +13,7 @@ You need to install some packages Noosfero depends on. On Debian GNU/Linux or @@ -13,7 +13,7 @@ You need to install some packages Noosfero depends on. On Debian GNU/Linux or
13 Debian-based systems, all of these packages are available through the Debian 13 Debian-based systems, all of these packages are available through the Debian
14 archive. You can install them with the following command: 14 archive. You can install them with the following command:
15 15
16 - # apt-get install ruby rake po4a libgettext-ruby-util libgettext-ruby-data libgettext-ruby1.8 libsqlite3-ruby rcov librmagick-ruby libredcloth-ruby libwill-paginate-ruby iso-codes libfeedparser-ruby libferret-ruby libdaemons-ruby mongrel mongrel-cluster tango-icon-theme libhpricot-ruby 16 + # apt-get install ruby rake po4a libgettext-ruby-util libgettext-ruby-data libgettext-ruby1.8 libsqlite3-ruby rcov librmagick-ruby libredcloth-ruby libwill-paginate-ruby iso-codes libfeedparser-ruby openjdk-6-jre libdaemons-ruby mongrel mongrel-cluster tango-icon-theme libhpricot-ruby
17 17
18 On other systems, they may or may not be available through your regular package 18 On other systems, they may or may not be available through your regular package
19 management system. Below are the links to their homepages. 19 management system. Below are the links to their homepages.
@@ -24,7 +24,7 @@ management system. Below are the links to their homepages. @@ -24,7 +24,7 @@ management system. Below are the links to their homepages.
24 * Ruby-GetText: http://www.yotabanana.com/hiki/ruby-gettext.html?ruby-gettext (at least version 1.9.0) 24 * Ruby-GetText: http://www.yotabanana.com/hiki/ruby-gettext.html?ruby-gettext (at least version 1.9.0)
25 * Ruby-sqlite3: http://rubyforge.org/projects/sqlite-ruby 25 * Ruby-sqlite3: http://rubyforge.org/projects/sqlite-ruby
26 * rcov: http://eigenclass.org/hiki/rcov 26 * rcov: http://eigenclass.org/hiki/rcov
27 -* Ferret: http://ferret.davebalmain.com/trac 27 +* Solr: http://lucene.apache.org/solr
28 * RMagick: http://rmagick.rubyforge.org/ 28 * RMagick: http://rmagick.rubyforge.org/
29 * RedCloth: http://redcloth.org/ 29 * RedCloth: http://redcloth.org/
30 * will_paginate: http://github.com/mislav/will_paginate/wikis 30 * will_paginate: http://github.com/mislav/will_paginate/wikis
@@ -115,8 +115,11 @@ $ tar -zxvf noosfero-0.27.1.tar.gz @@ -115,8 +115,11 @@ $ tar -zxvf noosfero-0.27.1.tar.gz
115 $ ln -s noosfero-0.27.1 current 115 $ ln -s noosfero-0.27.1 current
116 $ cd current 116 $ cd current
117 117
118 -Copy config/ferret_server.yml.dist to config/ferret_server.yml. You will 118 +Copy config/solr.yml.dist to config/solr.yml. You will
119 probably not need to customize this configuration, but have a look at it. 119 probably not need to customize this configuration, but have a look at it.
  120 +Then you'll need to download Solr into noosfero:
  121 +
  122 +$ rake solr:download
120 123
121 Create the mongrel configuration file: 124 Create the mongrel configuration file:
122 125
@@ -237,6 +240,10 @@ Create the database structure: @@ -237,6 +240,10 @@ Create the database structure:
237 240
238 $ RAILS_ENV=production rake db:schema:load 241 $ RAILS_ENV=production rake db:schema:load
239 242
  243 +Run Solr:
  244 +
  245 +$ rake solr:start
  246 +
240 Now we have to create some initial data. To create your default environment 247 Now we have to create some initial data. To create your default environment
241 (the first one), run the command below: 248 (the first one), run the command below:
242 249
@@ -7,4 +7,6 @@ require 'rake' @@ -7,4 +7,6 @@ require 'rake'
7 require 'rake/testtask' 7 require 'rake/testtask'
8 require 'rake/rdoctask' 8 require 'rake/rdoctask'
9 9
  10 +ACTS_AS_SEARCHABLE_ENABLED = false if Rake.application.top_level_tasks.detect{|t| t == 'db:data:minimal'}
  11 +
10 require 'tasks/rails' 12 require 'tasks/rails'
app/controllers/public/browse_controller.rb
@@ -21,9 +21,10 @@ class BrowseController < PublicController @@ -21,9 +21,10 @@ class BrowseController < PublicController
21 @results = @environment.people.visible.send(@filter) 21 @results = @environment.people.visible.send(@filter)
22 22
23 if !params[:query].blank? 23 if !params[:query].blank?
24 - @results = @results.find_by_contents(params[:query]) 24 + @results = @results.find_by_contents(params[:query], {:per_page => per_page, :page => params[:page]})[:results]
  25 + else
  26 + @results = @results.compact.paginate(:per_page => per_page, :page => params[:page])
25 end 27 end
26 - @results = @results.compact.paginate(:per_page => per_page, :page => params[:page])  
27 end 28 end
28 29
29 def communities 30 def communities
@@ -33,9 +34,10 @@ class BrowseController < PublicController @@ -33,9 +34,10 @@ class BrowseController < PublicController
33 @results = @environment.communities.visible.send(@filter) 34 @results = @environment.communities.visible.send(@filter)
34 35
35 if !params[:query].blank? 36 if !params[:query].blank?
36 - @results = @results.find_by_contents(params[:query]) 37 + @results = @results.find_by_contents(params[:query], {:per_page => per_page, :page => params[:page]})[:results]
  38 + else
  39 + @results = @results.compact.paginate(:per_page => per_page, :page => params[:page])
37 end 40 end
38 - @results = @results.compact.paginate(:per_page => per_page, :page => params[:page])  
39 end 41 end
40 42
41 def contents 43 def contents
app/controllers/public/profile_search_controller.rb
@@ -8,11 +8,10 @@ class ProfileSearchController < PublicController @@ -8,11 +8,10 @@ class ProfileSearchController < PublicController
8 def index 8 def index
9 @q = params[:q] 9 @q = params[:q]
10 unless @q.blank? 10 unless @q.blank?
11 - @filtered_query = remove_stop_words(@q)  
12 if params[:where] == 'environment' 11 if params[:where] == 'environment'
13 redirect_to :controller => 'search', :query => @q 12 redirect_to :controller => 'search', :query => @q
14 else 13 else
15 - @results = profile.articles.published.find_by_contents(@filtered_query).paginate(:per_page => 10, :page => params[:page]) 14 + @results = Article.find_by_contents(@q + " profile_id:#{profile.id} published:true")[:results].paginate(:per_page => 10, :page => params[:page])
16 end 15 end
17 end 16 end
18 end 17 end
app/controllers/public/search_controller.rb
@@ -89,7 +89,8 @@ class SearchController < PublicController @@ -89,7 +89,8 @@ class SearchController < PublicController
89 # REFACTOR DUPLICATED CODE inner loop doing the same thing that outter loop 89 # REFACTOR DUPLICATED CODE inner loop doing the same thing that outter loop
90 90
91 if !@query.blank? || @region && !params[:radius].blank? 91 if !@query.blank? || @region && !params[:radius].blank?
92 - @result_ids = @noosfero_finder.find(asset, @filtered_query, calculate_find_options(asset, nil, params[:page], @product_category, @region, params[:radius], params[:year], params[:month]).merge({:limit => :all})) 92 + ret = @noosfero_finder.find(asset, @query, calculate_find_options(asset, nil, params[:page], @product_category, @region, params[:radius], params[:year], params[:month]).merge({:limit => :all}))
  93 + @result_ids = ret.is_a?(Hash) ? ret[:results] : ret
93 end 94 end
94 95
95 end 96 end
@@ -149,7 +150,6 @@ class SearchController < PublicController @@ -149,7 +150,6 @@ class SearchController < PublicController
149 150
150 def index 151 def index
151 @query = params[:query] || '' 152 @query = params[:query] || ''
152 - @filtered_query = remove_stop_words(@query)  
153 @product_category = ProductCategory.find(params[:product_category]) if params[:product_category] 153 @product_category = ProductCategory.find(params[:product_category]) if params[:product_category]
154 154
155 @region = City.find_by_id(params[:city]) if !params[:city].blank? && params[:city] =~ /^\d+$/ 155 @region = City.find_by_id(params[:city]) if !params[:city].blank? && params[:city] =~ /^\d+$/
@@ -158,12 +158,16 @@ class SearchController < PublicController @@ -158,12 +158,16 @@ class SearchController < PublicController
158 number_of_result_assets = @searching.values.select{|v| v}.size 158 number_of_result_assets = @searching.values.select{|v| v}.size
159 159
160 @results = {} 160 @results = {}
  161 + @facets = {}
161 @order = [] 162 @order = []
162 @names = {} 163 @names = {}
163 164
164 where_to_search.select { |key,description| @searching[key] }.each do |key, description| 165 where_to_search.select { |key,description| @searching[key] }.each do |key, description|
165 @order << key 166 @order << key
166 - @results[key] = @noosfero_finder.find(key, @filtered_query, calculate_find_options(key, limit, params[:page], @product_category, @region, params[:radius], params[:year], params[:month])) 167 + find_options = calculate_find_options(key, limit, params[:page], @product_category, @region, params[:radius], params[:year], params[:month]);
  168 + ret = @noosfero_finder.find(key, @query, find_options)
  169 + @results[key] = ret.is_a?(Hash) ? ret[:results] : ret
  170 + @facets[key] = ret.is_a?(Hash) ? ret[:facets] : {}
167 @names[key] = getterm(description) 171 @names[key] = getterm(description)
168 end 172 end
169 173
app/helpers/application_helper.rb
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 # application. 2 # application.
3 module ApplicationHelper 3 module ApplicationHelper
4 4
5 - include PermissionName 5 + include PermissionNameHelper
6 6
7 include LightboxHelper 7 include LightboxHelper
8 8
app/helpers/search_helper.rb
@@ -3,21 +3,12 @@ module SearchHelper @@ -3,21 +3,12 @@ module SearchHelper
3 # FIXME remove it after search_controler refactored 3 # FIXME remove it after search_controler refactored
4 include EventsHelper 4 include EventsHelper
5 5
6 - STOP_WORDS = {  
7 - 'pt_BR' => Ferret::Analysis::FULL_PORTUGUESE_STOP_WORDS,  
8 - 'en' => Ferret::Analysis::FULL_ENGLISH_STOP_WORDS,  
9 - }  
10 -  
11 def relevance_for(hit) 6 def relevance_for(hit)
12 n = (hit.ferret_score if hit.respond_to?(:ferret_score)) 7 n = (hit.ferret_score if hit.respond_to?(:ferret_score))
13 n ||= 1.0 8 n ||= 1.0
14 (n * 100.0).round 9 (n * 100.0).round
15 end 10 end
16 11
17 - def remove_stop_words(query)  
18 - (query.downcase.scan(/"[^"]*"?|'[^']*'?|[^'"\s]+/) - (STOP_WORDS[locale] || [])).join(' ')  
19 - end  
20 -  
21 def display_results(use_map = true) 12 def display_results(use_map = true)
22 13
23 unless use_map && GoogleMaps.enabled?(environment.default_hostname) 14 unless use_map && GoogleMaps.enabled?(environment.default_hostname)
app/models/article.rb
@@ -409,7 +409,7 @@ class Article &lt; ActiveRecord::Base @@ -409,7 +409,7 @@ class Article &lt; ActiveRecord::Base
409 end 409 end
410 410
411 def comments_updated 411 def comments_updated
412 - ferret_update 412 + solr_save
413 end 413 end
414 414
415 def accept_category?(cat) 415 def accept_category?(cat)
app/models/category_finder.rb
@@ -28,10 +28,12 @@ class CategoryFinder @@ -28,10 +28,12 @@ class CategoryFinder
28 end 28 end
29 29
30 if query.blank? 30 if query.blank?
  31 + options.delete(:facets)
31 asset_class(asset).send(finder_method, :all, options_for_find(asset_class(asset), {:order => "#{asset_table(asset)}.name"}.merge(options), date_range)) 32 asset_class(asset).send(finder_method, :all, options_for_find(asset_class(asset), {:order => "#{asset_table(asset)}.name"}.merge(options), date_range))
32 else 33 else
33 - ferret_options = {:page => options.delete(:page), :per_page => options.delete(:per_page)}  
34 - asset_class(asset).find_by_contents(query, ferret_options, options_for_find(asset_class(asset), options, date_range)) 34 + pg_options = {:page => options.delete(:page), :per_page => options.delete(:per_page)}
  35 + solr_options = {:facets => options.delete(:facets)}
  36 + asset_class(asset).find_by_contents(query, pg_options, solr_options, options_for_find(asset_class(asset), options, date_range))[:results]
35 end 37 end
36 end 38 end
37 39
app/models/enterprise.rb
@@ -71,7 +71,7 @@ class Enterprise &lt; Organization @@ -71,7 +71,7 @@ class Enterprise &lt; Organization
71 end 71 end
72 72
73 def product_updated 73 def product_updated
74 - ferret_update 74 + solr_save
75 end 75 end
76 76
77 after_save do |e| 77 after_save do |e|
app/models/environment_finder.rb
@@ -22,6 +22,8 @@ class EnvironmentFinder @@ -22,6 +22,8 @@ class EnvironmentFinder
22 end 22 end
23 23
24 if query.blank? 24 if query.blank?
  25 + options.delete(:facets)
  26 +
25 # FIXME this test is in more than one place 27 # FIXME this test is in more than one place
26 if finder_method == 'paginate' 28 if finder_method == 'paginate'
27 options = {:order => "#{asset_table(asset)}.name"}.merge(options) 29 options = {:order => "#{asset_table(asset)}.name"}.merge(options)
@@ -48,14 +50,20 @@ class EnvironmentFinder @@ -48,14 +50,20 @@ class EnvironmentFinder
48 end 50 end
49 end 51 end
50 else 52 else
51 - ferret_options = {:page => options.delete(:page), :per_page => options.delete(:per_page)} 53 + pg_options = {:page => options.delete(:page), :per_page => options.delete(:per_page)}
  54 + solr_options = {:facets => options.delete(:facets)}
52 if product_category && asset == :products 55 if product_category && asset == :products
53 # SECURITY no risk of SQL injection, since product_category_ids comes from trusted source 56 # SECURITY no risk of SQL injection, since product_category_ids comes from trusted source
54 - @environment.send(asset).find_by_contents(query, ferret_options, options.merge({:include => 'product_categorizations', :conditions => 'product_categorizations.category_id = (%s)' % product_category.id })) 57 + ret = @environment.send(asset).find_by_contents(query, pg_options, solr_options, options.merge({:include => 'product_categorizations', :conditions => 'product_categorizations.category_id = (%s)' % product_category.id }))
55 elsif product_category && asset == :enterprises 58 elsif product_category && asset == :enterprises
56 - @environment.send(asset).find_by_contents(query, ferret_options, options.merge(:joins => 'inner join product_categorizations on (product_categorizations.product_id = products.id)', :include => 'products', :conditions => "product_categorizations.category_id = (#{product_category.id})")) 59 + ret = @environment.send(asset).find_by_contents(query, pg_options, solr_options, options.merge(:joins => 'inner join product_categorizations on (product_categorizations.product_id = products.id)', :include => 'products', :conditions => "product_categorizations.category_id = (#{product_category.id})"))
  60 + else
  61 + ret = @environment.send(asset).find_by_contents(query, pg_options, solr_options, options)
  62 + end
  63 + if solr_options[:facets].nil?
  64 + ret[:results]
57 else 65 else
58 - @environment.send(asset).find_by_contents(query, ferret_options, options) 66 + ret
59 end 67 end
60 end 68 end
61 end 69 end
app/models/region.rb
@@ -5,10 +5,9 @@ class Region &lt; Category @@ -5,10 +5,9 @@ class Region &lt; Category
5 require_dependency 'enterprise' # enterprises can also be validators 5 require_dependency 'enterprise' # enterprises can also be validators
6 6
7 # searches for organizations that could become validators for this region. 7 # searches for organizations that could become validators for this region.
8 - # <tt>search</tt> is passed as is to ferret's find_by_contents on Organizatio  
9 - # find_by_contents on Organization class. 8 + # <tt>search</tt> is passed as is to find_by_contents on Organization.
10 def search_possible_validators(search) 9 def search_possible_validators(search)
11 - Organization.find_by_contents(search).reject {|item| self.validator_ids.include?(item.id) } 10 + Organization.find_by_contents(search)[:results].reject {|item| self.validator_ids.include?(item.id) }
12 end 11 end
13 12
14 def has_validator? 13 def has_validator?
config/environments/cucumber.rb
@@ -26,4 +26,3 @@ config.gem &#39;rspec-rails&#39;, :lib =&gt; &#39;spec/rails&#39;, :version =&gt; &#39;1.2.9&#39; unles @@ -26,4 +26,3 @@ config.gem &#39;rspec-rails&#39;, :lib =&gt; &#39;spec/rails&#39;, :version =&gt; &#39;1.2.9&#39; unles
26 config.gem 'Selenium', :lib => 'selenium', :version => '>= 1.1.14' unless File.directory?(File.join(Rails.root, 'vendor/plugins/selenium')) 26 config.gem 'Selenium', :lib => 'selenium', :version => '>= 1.1.14' unless File.directory?(File.join(Rails.root, 'vendor/plugins/selenium'))
27 config.gem 'selenium-client', :lib => 'selenium/client', :version => '>= 1.2.17' unless File.directory?(File.join(Rails.root, 'vendor/plugins/selenium-client')) 27 config.gem 'selenium-client', :lib => 'selenium/client', :version => '>= 1.2.17' unless File.directory?(File.join(Rails.root, 'vendor/plugins/selenium-client'))
28 config.gem 'database_cleaner', :lib => 'database_cleaner' 28 config.gem 'database_cleaner', :lib => 'database_cleaner'
29 -  
config/solr.yml.dist
@@ -15,3 +15,6 @@ test: @@ -15,3 +15,6 @@ test:
15 url: http://0.0.0.0:8981/solr 15 url: http://0.0.0.0:8981/solr
16 jvm_options: -server -Xmx32M -Xms16M 16 jvm_options: -server -Xmx32M -Xms16M
17 17
  18 +cucumber:
  19 + url: http://0.0.0.0:8980/solr
  20 + jvm_options: -server -Xmx32M -Xms16M
debian/control
@@ -11,7 +11,7 @@ Vcs-Browser: http://git.colivre.coop.br/?p=noosfero.git @@ -11,7 +11,7 @@ Vcs-Browser: http://git.colivre.coop.br/?p=noosfero.git
11 11
12 Package: noosfero 12 Package: noosfero
13 Architecture: all 13 Architecture: all
14 -Depends: rails, ruby1.8, ruby, rake, libgettext-ruby-data, libsqlite3-ruby, libpgsql-ruby, libmysql-ruby, librmagick-ruby, libredcloth-ruby, libwill-paginate-ruby, iso-codes, libfeedparser-ruby, libferret-ruby, libdaemons-ruby, rcov, mongrel, mongrel-cluster, tango-icon-theme, libhpricot-ruby, iso-codes, memcached, debconf, dbconfig-common, postgresql, adduser, ${misc:Depends} 14 +Depends: rails, ruby1.8, ruby, rake, libgettext-ruby-data, libsqlite3-ruby, libpgsql-ruby, libmysql-ruby, librmagick-ruby, libredcloth-ruby, libwill-paginate-ruby, iso-codes, libfeedparser-ruby, openjdk-6-jre, libdaemons-ruby, rcov, mongrel, mongrel-cluster, tango-icon-theme, libhpricot-ruby, iso-codes, memcached, debconf, dbconfig-common, postgresql, adduser, ${misc:Depends}
15 Recommends: postgresql-client 15 Recommends: postgresql-client
16 Description: free web-based platform for social networks 16 Description: free web-based platform for social networks
17 Noosfero is a web platform for social and solidarity economy networks with 17 Noosfero is a web platform for social and solidarity economy networks with
debian/ferret_server.yml
@@ -1,4 +0,0 @@ @@ -1,4 +0,0 @@
1 -production:  
2 - host: localhost  
3 - port: 51000  
4 - pid_file: tmp/pids/ferret.production.pid  
debian/noosfero.install
@@ -28,7 +28,7 @@ public usr/share/noosfero @@ -28,7 +28,7 @@ public usr/share/noosfero
28 debian/default/noosfero etc/default 28 debian/default/noosfero etc/default
29 etc/init.d/noosfero etc/init.d 29 etc/init.d/noosfero etc/init.d
30 debian/mongrel_cluster.yml etc/noosfero 30 debian/mongrel_cluster.yml etc/noosfero
31 -debian/ferret_server.yml etc/noosfero 31 +debian/solr.yml etc/noosfero
32 etc/logrotate.d/noosfero etc/logrotate.d 32 etc/logrotate.d/noosfero etc/logrotate.d
33 debian/noosfero.yml etc/noosfero 33 debian/noosfero.yml etc/noosfero
34 34
debian/noosfero.links
@@ -3,7 +3,7 @@ var/tmp/noosfero usr/share/noosfero/tmp @@ -3,7 +3,7 @@ var/tmp/noosfero usr/share/noosfero/tmp
3 var/log/noosfero usr/share/noosfero/log 3 var/log/noosfero usr/share/noosfero/log
4 etc/noosfero/database.yml usr/share/noosfero/config/database.yml 4 etc/noosfero/database.yml usr/share/noosfero/config/database.yml
5 etc/noosfero/mongrel_cluster.yml usr/share/noosfero/config/mongrel_cluster.yml 5 etc/noosfero/mongrel_cluster.yml usr/share/noosfero/config/mongrel_cluster.yml
6 -etc/noosfero/ferret_server.yml usr/share/noosfero/config/ferret_server.yml 6 +etc/noosfero/solr.yml usr/share/noosfero/config/solr.yml
7 etc/noosfero/plugins usr/share/noosfero/config/plugins 7 etc/noosfero/plugins usr/share/noosfero/config/plugins
8 etc/noosfero/noosfero.yml usr/share/noosfero/config/noosfero.yml 8 etc/noosfero/noosfero.yml usr/share/noosfero/config/noosfero.yml
9 etc/noosfero/local.rb usr/share/noosfero/config/local.rb 9 etc/noosfero/local.rb usr/share/noosfero/config/local.rb
debian/solr.yml 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +# Config file for the acts_as_solr plugin.
  2 +#
  3 +# If you change the host or port number here, make sure you update
  4 +# them in your Solr config file
  5 +
  6 +production:
  7 + url: http://127.0.0.1:8983/solr
  8 + jvm_options: -server -Xmx512M -Xms64M
  9 +
etc/init.d/noosfero
@@ -43,14 +43,14 @@ if [ -z &quot;$NOOSFERO_DIR&quot; ] || [ -z &quot;$NOOSFERO_USER&quot; ]; then @@ -43,14 +43,14 @@ if [ -z &quot;$NOOSFERO_DIR&quot; ] || [ -z &quot;$NOOSFERO_USER&quot; ]; then
43 fi 43 fi
44 44
45 ###################### 45 ######################
46 -FERRET_PID_FILE=$NOOSFERO_DIR/tmp/pids/ferret.production.pid 46 +SOLR_PID_FILE=$NOOSFERO_DIR/tmp/pids/solr.production.pid
47 47
48 main_script() { 48 main_script() {
49 cd $NOOSFERO_DIR 49 cd $NOOSFERO_DIR
50 if [ "$NOOSFERO_USER" != "$USER" ]; then 50 if [ "$NOOSFERO_USER" != "$USER" ]; then
51 - su $NOOSFERO_USER -l -c "./script/production $1" 51 + su $NOOSFERO_USER -l -c "SOLR_DATA_PATH=/var/lib/noosfero-data/index ./script/production $1"
52 else 52 else
53 - ./script/production $1 53 + SOLR_DATA_PATH=/var/lib/noosfero-data/index ./script/production $1
54 fi 54 fi
55 } 55 }
56 56
@@ -76,6 +76,13 @@ do_setup() { @@ -76,6 +76,13 @@ do_setup() {
76 chmod 750 /var/tmp/noosfero 76 chmod 750 /var/tmp/noosfero
77 fi 77 fi
78 78
  79 + # Solr directory
  80 + if [ ! -d /var/tmp/noosfero/solr ]; then
  81 + mkdir -p /var/tmp/noosfero/solr
  82 + chown $NOOSFERO_USER:root /var/tmp/noosfero/solr
  83 + chmod 750 /var/tmp/noosfero/solr
  84 + fi
  85 +
79 # symlink the directories into Noosfero directory 86 # symlink the directories into Noosfero directory
80 if [ ! -e $NOOSFERO_DIR/tmp ]; then 87 if [ ! -e $NOOSFERO_DIR/tmp ]; then
81 ln -s /var/tmp/noosfero $NOOSFERO_DIR/tmp 88 ln -s /var/tmp/noosfero $NOOSFERO_DIR/tmp
@@ -90,8 +97,8 @@ do_setup() { @@ -90,8 +97,8 @@ do_setup() {
90 97
91 do_start() { 98 do_start() {
92 99
93 - # FIXME should not test for ferret only  
94 - if [ -e $FERRET_PID_FILE ]; then 100 + # FIXME should not test for solr only
  101 + if [ -e $SOLR_PID_FILE ]; then
95 echo 'noosfero already running, cannot start.' 102 echo 'noosfero already running, cannot start.'
96 exit 2 103 exit 2
97 fi 104 fi
@@ -104,8 +111,8 @@ do_start() { @@ -104,8 +111,8 @@ do_start() {
104 111
105 do_stop() { 112 do_stop() {
106 113
107 - # FIXME should not test for ferret only  
108 - if [ ! -e $FERRET_PID_FILE ]; then 114 + # FIXME should not test for solr only
  115 + if [ ! -e $SOLR_PID_FILE ]; then
109 echo 'noosfero not running, cannot stop' 116 echo 'noosfero not running, cannot stop'
110 exit 2 117 exit 2
111 fi 118 fi
features/browse.feature
@@ -4,6 +4,7 @@ Feature: browse @@ -4,6 +4,7 @@ Feature: browse
4 4
5 Background: 5 Background:
6 Given I am on the homepage 6 Given I am on the homepage
  7 + And the search index is empty
7 And the following users 8 And the following users
8 | login | name | 9 | login | name |
9 | joaosilva | Joao Silva | 10 | joaosilva | Joao Silva |
features/profile_search.feature
@@ -4,7 +4,8 @@ Feature: search inside a profile @@ -4,7 +4,8 @@ Feature: search inside a profile
4 In order to find stuff from a profile 4 In order to find stuff from a profile
5 5
6 Background: 6 Background:
7 - Given the following users 7 + Given the search index is empty
  8 + And the following users
8 | login | name | 9 | login | name |
9 | joaosilva | Joao Silva | 10 | joaosilva | Joao Silva |
10 And the following articles 11 And the following articles
features/search.feature
@@ -3,6 +3,9 @@ Feature: search @@ -3,6 +3,9 @@ Feature: search
3 I want to search 3 I want to search
4 In order to find stuff 4 In order to find stuff
5 5
  6 + Background:
  7 + Given the search index is empty
  8 +
6 Scenario: simple search for person 9 Scenario: simple search for person
7 Given the following users 10 Given the following users
8 | login | name | 11 | login | name |
features/step_definitions/noosfero_steps.rb
@@ -488,3 +488,7 @@ Then /^&quot;([^\&quot;]*)&quot; profile should not exist$/ do |profile_selector| @@ -488,3 +488,7 @@ Then /^&quot;([^\&quot;]*)&quot; profile should not exist$/ do |profile_selector|
488 profile.nil?.should be_true 488 profile.nil?.should be_true
489 end 489 end
490 end 490 end
  491 +
  492 +Given /^the search index is empty$/ do
  493 + ActsAsSolr::Post.execute(Solr::Request::Delete.new(:query => '*:*'))
  494 +end
lib/acts_as_searchable.rb
1 module ActsAsSearchable 1 module ActsAsSearchable
2 2
3 module ClassMethods 3 module ClassMethods
  4 + ACTS_AS_SEARCHABLE_ENABLED = true unless defined? ACTS_AS_SEARCHABLE_ENABLED
  5 +
4 def acts_as_searchable(options = {}) 6 def acts_as_searchable(options = {})
5 - if Noosfero::MultiTenancy.on? and ActiveRecord::Base.postgresql?  
6 - options[:additional_fields] ||= {}  
7 - options[:additional_fields] = Hash[*options[:additional_fields].collect{ |v| [v, {}] }.flatten] if options[:additional_fields].is_a?(Array)  
8 - options[:additional_fields].merge!(:schema_name => { :index => :untokenized }) 7 + if ACTS_AS_SEARCHABLE_ENABLED
  8 + if (!options[:fields])
  9 + options[:additional_fields] |= [{:schema_name => :string}]
  10 + else
  11 + options[:fields] << {:schema_name => :string}
  12 + end
  13 + acts_as_solr options
  14 + extend FindByContents
  15 + send :include, InstanceMethods
9 end 16 end
10 - acts_as_ferret({ :remote => true }.merge(options))  
11 - extend FindByContents  
12 - send :include, InstanceMethods  
13 end 17 end
14 18
15 module InstanceMethods 19 module InstanceMethods
16 def schema_name 20 def schema_name
17 - ActiveRecord::Base.connection.schema_search_path 21 + (Noosfero::MultiTenancy.on? and ActiveRecord::Base.postgresql?) ? ActiveRecord::Base.connection.schema_search_path : ''
18 end 22 end
19 end 23 end
20 24
21 module FindByContents 25 module FindByContents
22 26
23 def schema_name 27 def schema_name
24 - ActiveRecord::Base.connection.schema_search_path 28 + (Noosfero::MultiTenancy.on? and ActiveRecord::Base.postgresql?) ? ActiveRecord::Base.connection.schema_search_path : ''
25 end 29 end
26 30
27 - def find_by_contents(query, ferret_options = {}, db_options = {})  
28 - pg_options = {}  
29 - if ferret_options[:page]  
30 - pg_options[:page] = ferret_options.delete(:page)  
31 - end  
32 - if ferret_options[:per_page]  
33 - pg_options[:per_page] = ferret_options.delete(:per_page)  
34 - end 31 + def find_by_contents(query, pg_options = {}, options = {}, db_options = {})
  32 + pg_options[:page] ||= 1
  33 + pg_options[:per_page] ||= 20
  34 + options[:limit] = pg_options[:per_page].to_i*pg_options[:page].to_i
  35 + options[:scores] = true;
35 36
36 - ferret_options[:limit] = :all 37 + query = !schema_name.empty? ? "+schema_name:\"#{schema_name}\" AND #{query}" : query
  38 + solr_result = find_by_solr(query, options)
  39 + if solr_result.nil?
  40 + results = facets = []
  41 + else
  42 + facets = options.include?(:facets) ? solr_result.facets : []
37 43
38 - ferret_query = (Noosfero::MultiTenancy.on? and ActiveRecord::Base.postgresql?) ? "+schema_name:\"#{schema_name}\" AND #{query}" : query  
39 - # FIXME this is a HORRIBLE HACK  
40 - ids = find_ids_with_ferret(ferret_query, ferret_options)[1][0..8000].map{|r|r[:id].to_i} 44 + if db_options.empty?
  45 + results = solr_result.results
  46 + else
  47 + ids = solr_result.results.map{|r|r[:id].to_i}
  48 + if ids.empty?
  49 + ids << -1
  50 + end
41 51
42 - if ids.empty?  
43 - ids << -1  
44 - end 52 + if db_options[:conditions]
  53 + db_options[:conditions] = sanitize_sql_for_conditions(db_options[:conditions]) + " and #{table_name}.id in (#{ids.join(', ')})"
  54 + else
  55 + db_options[:conditions] = "#{table_name}.id in (#{ids.join(', ')})"
  56 + end
45 57
46 - if db_options[:conditions]  
47 - db_options[:conditions] = sanitize_sql_for_conditions(db_options[:conditions]) + " and #{table_name}.id in (#{ids.join(', ')})"  
48 - else  
49 - db_options[:conditions] = "#{table_name}.id in (#{ids.join(', ')})" 58 + results = find(:all, db_options)
  59 + end
  60 +
  61 + results = results.paginate(pg_options.merge(:total_entries => solr_result.total))
50 end 62 end
51 63
52 - pg_options[:page] ||= 1  
53 - result = find(:all, db_options)  
54 - result.paginate(pg_options) 64 + {:results => results, :facets => facets}
55 end 65 end
56 end 66 end
57 end 67 end
lib/create_thumbnails_job.rb
1 class CreateThumbnailsJob < Struct.new(:class_name, :file_id) 1 class CreateThumbnailsJob < Struct.new(:class_name, :file_id)
2 def perform 2 def perform
3 return unless class_name.constantize.exists?(file_id) 3 return unless class_name.constantize.exists?(file_id)
4 - Article.disable_ferret # acts_as_ferret sucks  
5 file = class_name.constantize.find(file_id) 4 file = class_name.constantize.find(file_id)
6 file.create_thumbnails 5 file.create_thumbnails
7 - Article.enable_ferret # acts_as_ferret sucks  
8 end 6 end
9 end 7 end
lib/tasks/cucumber.rake
@@ -11,6 +11,13 @@ begin @@ -11,6 +11,13 @@ begin
11 vendored_cucumber_binary = Dir["#{RAILS_ROOT}/vendor/{gems,plugins}/cucumber*/bin/cucumber"].first 11 vendored_cucumber_binary = Dir["#{RAILS_ROOT}/vendor/{gems,plugins}/cucumber*/bin/cucumber"].first
12 12
13 namespace :cucumber do 13 namespace :cucumber do
  14 + task :solr_start do
  15 + ENV['RAILS_ENV'] = 'cucumber'
  16 + Rake::Task['solr:stop'].invoke
  17 + Rake::Task['solr:download'].invoke
  18 + Rake::Task['solr:start'].invoke
  19 + end
  20 +
14 Cucumber::Rake::Task.new({:ok => 'db:test:prepare'}, 'Run features that should pass') do |t| 21 Cucumber::Rake::Task.new({:ok => 'db:test:prepare'}, 'Run features that should pass') do |t|
15 t.binary = vendored_cucumber_binary 22 t.binary = vendored_cucumber_binary
16 t.fork = true # You may get faster startup if you set this to false 23 t.fork = true # You may get faster startup if you set this to false
@@ -29,11 +36,17 @@ begin @@ -29,11 +36,17 @@ begin
29 t.cucumber_opts = "--color -p selenium --format #{ENV['CUCUMBER_FORMAT'] || 'pretty'}" 36 t.cucumber_opts = "--color -p selenium --format #{ENV['CUCUMBER_FORMAT'] || 'pretty'}"
30 end 37 end
31 38
  39 + task :solr_stop do
  40 + ENV['RAILS_ENV'] = 'cucumber'
  41 + Rake::Task['solr:stop'].invoke
  42 + end
  43 +
32 desc 'Run all features' 44 desc 'Run all features'
33 - task :all => [:ok, :wip] 45 + task :all => [:solr_start, :ok, :wip, :solr_stop] do
  46 + end
34 end 47 end
35 desc 'Alias for cucumber:ok' 48 desc 'Alias for cucumber:ok'
36 - task :cucumber => 'cucumber:ok' 49 + task :cucumber => ['cucumber:solr_start', 'cucumber:ok', 'cucumber:solr_stop']
37 50
38 task :features => :cucumber do 51 task :features => :cucumber do
39 STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***" 52 STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***"
lib/tasks/package.rake
@@ -8,10 +8,22 @@ task :package =&gt; &#39;package:clobber&#39; do @@ -8,10 +8,22 @@ task :package =&gt; &#39;package:clobber&#39; do
8 puts "** The `package` task only works from within #{Noosfero::PROJECT}'s git repository." 8 puts "** The `package` task only works from within #{Noosfero::PROJECT}'s git repository."
9 fail 9 fail
10 end 10 end
  11 + begin
  12 + sh 'test -f vendor/plugins/acts_as_solr_reloaded/solr/start.jar'
  13 + rescue
  14 + puts "** The `package` task needs Solr installed within #{Noosfero::PROJECT}. Run 'rake solr:download'."
  15 + fail
  16 + end
11 release = "#{Noosfero::PROJECT}-#{Noosfero::VERSION}" 17 release = "#{Noosfero::PROJECT}-#{Noosfero::VERSION}"
12 target = "pkg/#{release}" 18 target = "pkg/#{release}"
13 mkdir_p target 19 mkdir_p target
14 sh "git archive HEAD | (cd #{target} && tar x)" 20 sh "git archive HEAD | (cd #{target} && tar x)"
  21 +
  22 + #solr inclusion
  23 + cp_r "vendor/plugins/acts_as_solr_reloaded/solr", "#{target}/vendor/plugins/acts_as_solr_reloaded", :verbose => true
  24 + rm_r "#{target}/vendor/plugins/acts_as_solr_reloaded/solr/work"
  25 + mkdir_p "#{target}/vendor/plugins/acts_as_solr_reloaded/solr/work"
  26 +
15 sh "cd pkg && tar czf #{release}.tar.gz #{release}" 27 sh "cd pkg && tar czf #{release}.tar.gz #{release}"
16 end 28 end
17 29
lib/tasks/test.rake
@@ -7,6 +7,10 @@ else @@ -7,6 +7,10 @@ else
7 end 7 end
8 8
9 task :test do 9 task :test do
  10 + ENV['RAILS_ENV'] = 'test'
  11 + Rake::Task['solr:stop'].invoke
  12 + Rake::Task['solr:download'].invoke
  13 + Rake::Task['solr:start'].invoke
10 errors = %w(test:units test:functionals test:integration cucumber selenium test:noosfero_plugins).collect do |task| 14 errors = %w(test:units test:functionals test:integration cucumber selenium test:noosfero_plugins).collect do |task|
11 begin 15 begin
12 Rake::Task[task].invoke 16 Rake::Task[task].invoke
@@ -15,6 +19,7 @@ task :test do @@ -15,6 +19,7 @@ task :test do
15 task 19 task
16 end 20 end
17 end.compact 21 end.compact
  22 + Rake::Task['solr:stop'].invoke
18 abort "Errors running #{errors.to_sentence}!" if errors.any? 23 abort "Errors running #{errors.to_sentence}!" if errors.any?
19 end 24 end
20 25
script/development
1 #!/bin/sh 1 #!/bin/sh
2 2
  3 +export RAILS_ENV=development
  4 +
3 stop() { 5 stop() {
4 ./script/delayed_job stop 6 ./script/delayed_job stop
5 ./script/feed-updater stop 7 ./script/feed-updater stop
  8 + rake -s solr:stop
6 } 9 }
7 10
8 start() { 11 start() {
9 ./script/feed-updater start 12 ./script/feed-updater start
10 ./script/delayed_job start 13 ./script/delayed_job start
  14 + rake -s solr:download
  15 + rake -s solr:start
11 trap stop INT TERM 16 trap stop INT TERM
12 ./script/server $@ 17 ./script/server $@
13 } 18 }
script/ferret_server
@@ -1,10 +0,0 @@ @@ -1,10 +0,0 @@
1 -#!/usr/bin/env ruby  
2 -  
3 -begin  
4 - require File.join(File.dirname(__FILE__), '../vendor/plugins/acts_as_ferret/lib/server_manager')  
5 -rescue LoadError  
6 - # try the gem  
7 - require 'rubygems'  
8 - gem 'acts_as_ferret'  
9 - require 'server_manager'  
10 -end  
script/production
@@ -31,7 +31,7 @@ do_start() { @@ -31,7 +31,7 @@ do_start() {
31 fi 31 fi
32 32
33 clear_cache 33 clear_cache
34 - ./script/ferret_server -e $RAILS_ENV start 34 + rake -s solr:start
35 environments_loop 35 environments_loop
36 mongrel_rails cluster::start 36 mongrel_rails cluster::start
37 } 37 }
@@ -40,7 +40,7 @@ do_stop() { @@ -40,7 +40,7 @@ do_stop() {
40 mongrel_rails cluster::stop 40 mongrel_rails cluster::stop
41 ./script/delayed_job stop 41 ./script/delayed_job stop
42 ./script/feed-updater stop 42 ./script/feed-updater stop
43 - ./script/ferret_server -e $RAILS_ENV stop 43 + rake -s solr:stop
44 } 44 }
45 45
46 environments_loop() { 46 environments_loop() {
test/factories.rb
@@ -22,7 +22,7 @@ module Noosfero::Factory @@ -22,7 +22,7 @@ module Noosfero::Factory
22 end 22 end
23 end 23 end
24 if options[:search] 24 if options[:search]
25 - obj.ferret_create 25 + obj.solr_save
26 end 26 end
27 obj 27 obj
28 end 28 end
test/functional/browse_controller_test.rb
@@ -7,6 +7,7 @@ class BrowseController; def rescue_action(e) raise e end; end @@ -7,6 +7,7 @@ class BrowseController; def rescue_action(e) raise e end; end
7 class BrowseControllerTest < Test::Unit::TestCase 7 class BrowseControllerTest < Test::Unit::TestCase
8 8
9 def setup 9 def setup
  10 + Test::Unit::TestCase::setup
10 @controller = BrowseController.new 11 @controller = BrowseController.new
11 @request = ActionController::TestRequest.new 12 @request = ActionController::TestRequest.new
12 @request.stubs(:ssl?).returns(false) 13 @request.stubs(:ssl?).returns(false)
test/functional/profile_members_controller_test.rb
@@ -6,6 +6,7 @@ class ProfileMembersController; def rescue_action(e) raise e end; end @@ -6,6 +6,7 @@ class ProfileMembersController; def rescue_action(e) raise e end; end
6 6
7 class ProfileMembersControllerTest < Test::Unit::TestCase 7 class ProfileMembersControllerTest < Test::Unit::TestCase
8 def setup 8 def setup
  9 + Test::Unit::TestCase::setup
9 @controller = ProfileMembersController.new 10 @controller = ProfileMembersController.new
10 @request = ActionController::TestRequest.new 11 @request = ActionController::TestRequest.new
11 @request.stubs(:ssl?).returns(true) 12 @request.stubs(:ssl?).returns(true)
test/functional/profile_search_controller_test.rb
@@ -6,6 +6,7 @@ class ProfileSearchController; def rescue_action(e) raise e end; end @@ -6,6 +6,7 @@ class ProfileSearchController; def rescue_action(e) raise e end; end
6 6
7 class ProfileSearchControllerTest < Test::Unit::TestCase 7 class ProfileSearchControllerTest < Test::Unit::TestCase
8 def setup 8 def setup
  9 + Test::Unit::TestCase::setup
9 @controller = ProfileSearchController.new 10 @controller = ProfileSearchController.new
10 @request = ActionController::TestRequest.new 11 @request = ActionController::TestRequest.new
11 @response = ActionController::TestResponse.new 12 @response = ActionController::TestResponse.new
@@ -14,14 +15,6 @@ class ProfileSearchControllerTest &lt; Test::Unit::TestCase @@ -14,14 +15,6 @@ class ProfileSearchControllerTest &lt; Test::Unit::TestCase
14 end 15 end
15 attr_reader :person 16 attr_reader :person
16 17
17 - should 'filter stop words' do  
18 - @controller.expects(:locale).returns('en').at_least_once  
19 - get 'index', :profile => person.identifier, :q => 'an article about something'  
20 - assert_response :success  
21 - assert_template 'index'  
22 - assert_equal 'article something', assigns('filtered_query')  
23 - end  
24 -  
25 should 'espape xss attack' do 18 should 'espape xss attack' do
26 @controller.expects(:profile).returns(person).at_least_once 19 @controller.expects(:profile).returns(person).at_least_once
27 get 'index', :profile => person.identifier, :q => '<wslite>' 20 get 'index', :profile => person.identifier, :q => '<wslite>'
@@ -41,8 +34,8 @@ class ProfileSearchControllerTest &lt; Test::Unit::TestCase @@ -41,8 +34,8 @@ class ProfileSearchControllerTest &lt; Test::Unit::TestCase
41 end 34 end
42 35
43 should 'display search results' do 36 should 'display search results' do
44 - article1 = fast_create(Article, :body => '<p>Article to test profile search</p>', :profile_id => person.id)  
45 - article2 = fast_create(Article, :body => '<p>Another article to test profile search</p>', :profile_id => person.id) 37 + article1 = fast_create(Article, {:body => '<p>Article to test profile search</p>', :profile_id => person.id}, :search => true)
  38 + article2 = fast_create(Article, {:body => '<p>Another article to test profile search</p>', :profile_id => person.id}, :search => true)
46 39
47 get 'index', :profile => person.identifier, :q => 'article' 40 get 'index', :profile => person.identifier, :q => 'article'
48 41
test/functional/search_controller_test.rb
@@ -6,6 +6,7 @@ class SearchController; def rescue_action(e) raise e end; end @@ -6,6 +6,7 @@ class SearchController; def rescue_action(e) raise e end; end
6 6
7 class SearchControllerTest < Test::Unit::TestCase 7 class SearchControllerTest < Test::Unit::TestCase
8 def setup 8 def setup
  9 + Test::Unit::TestCase::setup
9 @controller = SearchController.new 10 @controller = SearchController.new
10 @request = ActionController::TestRequest.new 11 @request = ActionController::TestRequest.new
11 @response = ActionController::TestResponse.new 12 @response = ActionController::TestResponse.new
@@ -35,21 +36,6 @@ class SearchControllerTest &lt; Test::Unit::TestCase @@ -35,21 +36,6 @@ class SearchControllerTest &lt; Test::Unit::TestCase
35 assert_valid_xhtml 36 assert_valid_xhtml
36 end 37 end
37 38
38 - should 'filter stop words' do  
39 - @controller.expects(:locale).returns('pt_BR').at_least_once  
40 - get 'index', :query => 'a carne da vaca'  
41 - assert_response :success  
42 - assert_template 'index'  
43 - assert_equal 'carne vaca', assigns('filtered_query')  
44 - end  
45 -  
46 - should 'search with filtered query' do  
47 - @controller.expects(:locale).returns('pt_BR').at_least_once  
48 - get 'index', :query => 'a carne da vaca'  
49 -  
50 - assert_equal 'carne vaca', assigns('filtered_query')  
51 - end  
52 -  
53 should 'espape xss attack' do 39 should 'espape xss attack' do
54 get 'index', :query => '<wslite>' 40 get 'index', :query => '<wslite>'
55 assert_no_tag :tag => 'wslite' 41 assert_no_tag :tag => 'wslite'
test/test_helper.rb
@@ -47,6 +47,11 @@ class Test::Unit::TestCase @@ -47,6 +47,11 @@ class Test::Unit::TestCase
47 include AuthenticatedTestHelper 47 include AuthenticatedTestHelper
48 48
49 fixtures :environments, :roles 49 fixtures :environments, :roles
  50 +
  51 + def self.setup
  52 + # clean up index db before each test
  53 + ActsAsSolr::Post.execute(Solr::Request::Delete.new(:query => '*:*'))
  54 + end
50 55
51 def self.all_fixtures 56 def self.all_fixtures
52 Dir.glob(File.join(RAILS_ROOT, 'test', 'fixtures', '*.yml')).each do |item| 57 Dir.glob(File.join(RAILS_ROOT, 'test', 'fixtures', '*.yml')).each do |item|
@@ -190,7 +195,6 @@ class Test::Unit::TestCase @@ -190,7 +195,6 @@ class Test::Unit::TestCase
190 adapter.any_instance.stubs(:adapter_name).returns('PostgreSQL') 195 adapter.any_instance.stubs(:adapter_name).returns('PostgreSQL')
191 adapter.any_instance.stubs(:schema_search_path).returns(schema_name) 196 adapter.any_instance.stubs(:schema_search_path).returns(schema_name)
192 Noosfero::MultiTenancy.stubs(:on?).returns(true) 197 Noosfero::MultiTenancy.stubs(:on?).returns(true)
193 - reload_for_ferret  
194 end 198 end
195 199
196 def uses_sqlite 200 def uses_sqlite
@@ -199,20 +203,6 @@ class Test::Unit::TestCase @@ -199,20 +203,6 @@ class Test::Unit::TestCase
199 Noosfero::MultiTenancy.stubs(:on?).returns(false) 203 Noosfero::MultiTenancy.stubs(:on?).returns(false)
200 end 204 end
201 205
202 - def reload_for_ferret  
203 - ActsAsFerret.send(:remove_const, :DEFAULT_FIELD_OPTIONS)  
204 - load File.join(RAILS_ROOT, 'lib', 'acts_as_searchable.rb')  
205 - load File.join(RAILS_ROOT, 'vendor', 'plugins', 'acts_as_ferret', 'lib', 'acts_as_ferret.rb')  
206 - [Article, Profile, Product].each do |clazz|  
207 - inst_meth = clazz.instance_methods.reject{ |m| m =~ /_to_ferret$/ }  
208 - clazz.stubs(:instance_methods).returns(inst_meth)  
209 - end  
210 - #FIXME Is there a way to avoid this replication from model code?  
211 - Article.acts_as_searchable :additional_fields => [ :comment_data ]  
212 - Profile.acts_as_searchable :additional_fields => [ :extra_data_for_index ]  
213 - Product.acts_as_searchable :fields => [ :name, :description, :category_full_name ]  
214 - end  
215 -  
216 end 206 end
217 207
218 module NoosferoTestHelper 208 module NoosferoTestHelper
test/unit/article_test.rb
@@ -5,6 +5,7 @@ class ArticleTest &lt; Test::Unit::TestCase @@ -5,6 +5,7 @@ class ArticleTest &lt; Test::Unit::TestCase
5 fixtures :environments 5 fixtures :environments
6 6
7 def setup 7 def setup
  8 + Test::Unit::TestCase::setup
8 @profile = create_user('testing').person 9 @profile = create_user('testing').person
9 end 10 end
10 attr_reader :profile 11 attr_reader :profile
@@ -356,7 +357,7 @@ class ArticleTest &lt; Test::Unit::TestCase @@ -356,7 +357,7 @@ class ArticleTest &lt; Test::Unit::TestCase
356 357
357 should 'reindex when comments are changed' do 358 should 'reindex when comments are changed' do
358 a = Article.new 359 a = Article.new
359 - a.expects(:ferret_update) 360 + a.expects(:solr_save)
360 a.comments_updated 361 a.comments_updated
361 end 362 end
362 363
@@ -365,7 +366,7 @@ class ArticleTest &lt; Test::Unit::TestCase @@ -365,7 +366,7 @@ class ArticleTest &lt; Test::Unit::TestCase
365 art = owner.articles.build(:name => 'ytest'); art.save! 366 art = owner.articles.build(:name => 'ytest'); art.save!
366 c1 = art.comments.build(:title => 'a nice comment', :body => 'anything', :author => owner); c1.save! 367 c1 = art.comments.build(:title => 'a nice comment', :body => 'anything', :author => owner); c1.save!
367 368
368 - assert_includes Article.find_by_contents('nice'), art 369 + assert_includes Article.find_by_contents('nice')[:results], art
369 end 370 end
370 371
371 should 'index comments body together with article' do 372 should 'index comments body together with article' do
@@ -373,7 +374,7 @@ class ArticleTest &lt; Test::Unit::TestCase @@ -373,7 +374,7 @@ class ArticleTest &lt; Test::Unit::TestCase
373 art = owner.articles.build(:name => 'ytest'); art.save! 374 art = owner.articles.build(:name => 'ytest'); art.save!
374 c1 = art.comments.build(:title => 'test comment', :body => 'anything', :author => owner); c1.save! 375 c1 = art.comments.build(:title => 'test comment', :body => 'anything', :author => owner); c1.save!
375 376
376 - assert_includes Article.find_by_contents('anything'), art 377 + assert_includes Article.find_by_contents('anything')[:results], art
377 end 378 end
378 379
379 should 'cache children count' do 380 should 'cache children count' do
@@ -1506,24 +1507,24 @@ class ArticleTest &lt; Test::Unit::TestCase @@ -1506,24 +1507,24 @@ class ArticleTest &lt; Test::Unit::TestCase
1506 should 'index by schema name when database is postgresql' do 1507 should 'index by schema name when database is postgresql' do
1507 uses_postgresql 'schema_one' 1508 uses_postgresql 'schema_one'
1508 art1 = Article.create!(:name => 'some thing', :profile_id => @profile.id) 1509 art1 = Article.create!(:name => 'some thing', :profile_id => @profile.id)
1509 - assert_equal Article.find_by_contents('thing'), [art1] 1510 + assert_equal Article.find_by_contents('thing')[:results], [art1]
1510 uses_postgresql 'schema_two' 1511 uses_postgresql 'schema_two'
1511 art2 = Article.create!(:name => 'another thing', :profile_id => @profile.id) 1512 art2 = Article.create!(:name => 'another thing', :profile_id => @profile.id)
1512 - assert_not_includes Article.find_by_contents('thing'), art1  
1513 - assert_includes Article.find_by_contents('thing'), art2 1513 + assert_not_includes Article.find_by_contents('thing')[:results], art1
  1514 + assert_includes Article.find_by_contents('thing')[:results], art2
1514 uses_postgresql 'schema_one' 1515 uses_postgresql 'schema_one'
1515 - assert_includes Article.find_by_contents('thing'), art1  
1516 - assert_not_includes Article.find_by_contents('thing'), art2 1516 + assert_includes Article.find_by_contents('thing')[:results], art1
  1517 + assert_not_includes Article.find_by_contents('thing')[:results], art2
1517 uses_sqlite 1518 uses_sqlite
1518 end 1519 end
1519 1520
1520 should 'not index by schema name when database is not postgresql' do 1521 should 'not index by schema name when database is not postgresql' do
1521 uses_sqlite 1522 uses_sqlite
1522 art1 = Article.create!(:name => 'some thing', :profile_id => @profile.id) 1523 art1 = Article.create!(:name => 'some thing', :profile_id => @profile.id)
1523 - assert_equal Article.find_by_contents('thing'), [art1] 1524 + assert_equal Article.find_by_contents('thing')[:results], [art1]
1524 art2 = Article.create!(:name => 'another thing', :profile_id => @profile.id) 1525 art2 = Article.create!(:name => 'another thing', :profile_id => @profile.id)
1525 - assert_includes Article.find_by_contents('thing'), art1  
1526 - assert_includes Article.find_by_contents('thing'), art2 1526 + assert_includes Article.find_by_contents('thing')[:results], art1
  1527 + assert_includes Article.find_by_contents('thing')[:results], art2
1527 end 1528 end
1528 1529
1529 should 'get images paths in article body' do 1530 should 'get images paths in article body' do
test/unit/category_finder_test.rb
@@ -3,10 +3,13 @@ require File.dirname(__FILE__) + &#39;/../test_helper&#39; @@ -3,10 +3,13 @@ require File.dirname(__FILE__) + &#39;/../test_helper&#39;
3 class CategoryFinderTest < ActiveSupport::TestCase 3 class CategoryFinderTest < ActiveSupport::TestCase
4 4
5 def setup 5 def setup
  6 + Test::Unit::TestCase::setup
6 @category = Category.create!(:name => 'my category', :environment => Environment.default) 7 @category = Category.create!(:name => 'my category', :environment => Environment.default)
7 @finder = CategoryFinder.new(@category) 8 @finder = CategoryFinder.new(@category)
8 @product_category = fast_create(ProductCategory, :name => 'Products') 9 @product_category = fast_create(ProductCategory, :name => 'Products')
9 10
  11 + Profile.rebuild_index
  12 + Comment.skip_captcha!
10 end 13 end
11 14
12 should 'search for articles in a specific category' do 15 should 'search for articles in a specific category' do
test/unit/enterprise_test.rb
@@ -4,6 +4,7 @@ class EnterpriseTest &lt; Test::Unit::TestCase @@ -4,6 +4,7 @@ class EnterpriseTest &lt; Test::Unit::TestCase
4 fixtures :profiles, :environments, :users 4 fixtures :profiles, :environments, :users
5 5
6 def setup 6 def setup
  7 + Test::Unit::TestCase::setup
7 @product_category = fast_create(ProductCategory, :name => 'Products') 8 @product_category = fast_create(ProductCategory, :name => 'Products')
8 end 9 end
9 10
@@ -91,7 +92,7 @@ class EnterpriseTest &lt; Test::Unit::TestCase @@ -91,7 +92,7 @@ class EnterpriseTest &lt; Test::Unit::TestCase
91 92
92 ent2 = fast_create(Enterprise, :name => 'test2', :identifier => 'test2') 93 ent2 = fast_create(Enterprise, :name => 'test2', :identifier => 'test2')
93 94
94 - result = Enterprise.find_by_contents(prod_cat.name) 95 + result = Enterprise.find_by_contents(prod_cat.name)[:results]
95 96
96 assert_includes result, ent1 97 assert_includes result, ent1
97 assert_not_includes result, ent2 98 assert_not_includes result, ent2
@@ -105,7 +106,7 @@ class EnterpriseTest &lt; Test::Unit::TestCase @@ -105,7 +106,7 @@ class EnterpriseTest &lt; Test::Unit::TestCase
105 106
106 ent2 = fast_create(Enterprise, :name => 'test2', :identifier => 'test2') 107 ent2 = fast_create(Enterprise, :name => 'test2', :identifier => 'test2')
107 108
108 - result = Enterprise.find_by_contents(prod_cat.name) 109 + result = Enterprise.find_by_contents(prod_cat.name)[:results]
109 110
110 assert_includes result, ent1 111 assert_includes result, ent1
111 assert_not_includes result, ent2 112 assert_not_includes result, ent2
@@ -420,6 +421,12 @@ class EnterpriseTest &lt; Test::Unit::TestCase @@ -420,6 +421,12 @@ class EnterpriseTest &lt; Test::Unit::TestCase
420 421
421 assert_equal product.inputs, enterprise.inputs 422 assert_equal product.inputs, enterprise.inputs
422 end 423 end
  424 +
  425 + should 'reindex when products are changed' do
  426 + a = Enterprise.new
  427 + a.expects(:solr_save)
  428 + a.product_updated
  429 + end
423 430
424 should "the followed_by? be true only to members" do 431 should "the followed_by? be true only to members" do
425 e = fast_create(Enterprise) 432 e = fast_create(Enterprise)
test/unit/environment_finder_test.rb
@@ -3,6 +3,7 @@ require File.dirname(__FILE__) + &#39;/../test_helper&#39; @@ -3,6 +3,7 @@ require File.dirname(__FILE__) + &#39;/../test_helper&#39;
3 class EnvironmentFinderTest < ActiveSupport::TestCase 3 class EnvironmentFinderTest < ActiveSupport::TestCase
4 4
5 def setup 5 def setup
  6 + Test::Unit::TestCase::setup
6 @product_category = fast_create(ProductCategory, :name => 'Products') 7 @product_category = fast_create(ProductCategory, :name => 'Products')
7 end 8 end
8 9
@@ -77,10 +78,10 @@ class EnvironmentFinderTest &lt; ActiveSupport::TestCase @@ -77,10 +78,10 @@ class EnvironmentFinderTest &lt; ActiveSupport::TestCase
77 finder = EnvironmentFinder.new(Environment.default) 78 finder = EnvironmentFinder.new(Environment.default)
78 79
79 region = fast_create(Region, :name => 'r-test', :environment_id => Environment.default.id, :lat => 45.0, :lng => 45.0) 80 region = fast_create(Region, :name => 'r-test', :environment_id => Environment.default.id, :lat => 45.0, :lng => 45.0)
80 - ent1 = fast_create(Enterprise, :name => 'test 1', :identifier => 'test1', :lat => 45.0, :lng => 45.0) 81 + ent1 = fast_create(Enterprise, {:name => 'test 1', :identifier => 'test1', :lat => 45.0, :lng => 45.0}, :search => true)
81 p1 = create_user('test2').person 82 p1 = create_user('test2').person
82 p1.name = 'test 2'; p1.lat = 45.0; p1.lng = 45.0; p1.save! 83 p1.name = 'test 2'; p1.lat = 45.0; p1.lng = 45.0; p1.save!
83 - ent2 = fast_create(Enterprise, :name => 'test 3', :identifier => 'test3', :lat => 30.0, :lng => 30.0) 84 + ent2 = fast_create(Enterprise, {:name => 'test 3', :identifier => 'test3', :lat => 30.0, :lng => 30.0}, :search => true)
84 p2 = create_user('test4').person 85 p2 = create_user('test4').person
85 p2.name = 'test 4'; p2.lat = 30.0; p2.lng = 30.0; p2.save! 86 p2.name = 'test 4'; p2.lat = 30.0; p2.lng = 30.0; p2.save!
86 87
test/unit/environment_test.rb
@@ -3,6 +3,10 @@ require File.dirname(__FILE__) + &#39;/../test_helper&#39; @@ -3,6 +3,10 @@ require File.dirname(__FILE__) + &#39;/../test_helper&#39;
3 class EnvironmentTest < Test::Unit::TestCase 3 class EnvironmentTest < Test::Unit::TestCase
4 fixtures :environments 4 fixtures :environments
5 5
  6 + def setup
  7 + Test::Unit::TestCase::setup
  8 + end
  9 +
6 def test_exists_default_and_it_is_unique 10 def test_exists_default_and_it_is_unique
7 Environment.delete_all 11 Environment.delete_all
8 vc = Environment.new(:name => 'Test Community') 12 vc = Environment.new(:name => 'Test Community')
@@ -450,7 +454,7 @@ class EnvironmentTest &lt; Test::Unit::TestCase @@ -450,7 +454,7 @@ class EnvironmentTest &lt; Test::Unit::TestCase
450 should 'find by contents from articles' do 454 should 'find by contents from articles' do
451 environment = fast_create(Environment) 455 environment = fast_create(Environment)
452 assert_nothing_raised do 456 assert_nothing_raised do
453 - environment.articles.find_by_contents('') 457 + environment.articles.find_by_contents('')[:results]
454 end 458 end
455 end 459 end
456 460
@@ -567,7 +571,7 @@ class EnvironmentTest &lt; Test::Unit::TestCase @@ -567,7 +571,7 @@ class EnvironmentTest &lt; Test::Unit::TestCase
567 Enterprise.create!(:name => 'test ' + n, :identifier => 'test_' + n) 571 Enterprise.create!(:name => 'test ' + n, :identifier => 'test_' + n)
568 end 572 end
569 573
570 - assert_equal 20, env.enterprises.find_by_contents('test').total_entries 574 + assert_equal 20, env.enterprises.find_by_contents('test')[:results].total_entries
571 end 575 end
572 576
573 should 'set replace_enterprise_template_when_enable on environment' do 577 should 'set replace_enterprise_template_when_enable on environment' do
test/unit/event_test.rb
@@ -2,6 +2,10 @@ require File.dirname(__FILE__) + &#39;/../test_helper&#39; @@ -2,6 +2,10 @@ require File.dirname(__FILE__) + &#39;/../test_helper&#39;
2 2
3 class EventTest < ActiveSupport::TestCase 3 class EventTest < ActiveSupport::TestCase
4 4
  5 + def setup
  6 + Test::Unit::TestCase::setup
  7 + end
  8 +
5 should 'be an article' do 9 should 'be an article' do
6 assert_kind_of Article, Event.new 10 assert_kind_of Article, Event.new
7 end 11 end
@@ -59,13 +63,13 @@ class EventTest &lt; ActiveSupport::TestCase @@ -59,13 +63,13 @@ class EventTest &lt; ActiveSupport::TestCase
59 should 'be indexed by title' do 63 should 'be indexed by title' do
60 profile = create_user('testuser').person 64 profile = create_user('testuser').person
61 e = Event.create!(:name => 'my surprisingly nice event', :start_date => Date.new(2008, 06, 06), :profile => profile) 65 e = Event.create!(:name => 'my surprisingly nice event', :start_date => Date.new(2008, 06, 06), :profile => profile)
62 - assert_includes Event.find_by_contents('surprisingly'), e 66 + assert_includes Event.find_by_contents('surprisingly')[:results], e
63 end 67 end
64 68
65 should 'be indexed by body' do 69 should 'be indexed by body' do
66 profile = create_user('testuser').person 70 profile = create_user('testuser').person
67 e = Event.create!(:name => 'bli', :start_date => Date.new(2008, 06, 06), :profile => profile, :body => 'my surprisingly long description about my freaking nice event') 71 e = Event.create!(:name => 'bli', :start_date => Date.new(2008, 06, 06), :profile => profile, :body => 'my surprisingly long description about my freaking nice event')
68 - assert_includes Event.find_by_contents('surprisingly'), e 72 + assert_includes Event.find_by_contents('surprisingly')[:results], e
69 end 73 end
70 74
71 should 'use its own icon' do 75 should 'use its own icon' do
test/unit/forum_helper_test.rb
@@ -50,14 +50,14 @@ class ForumHelperTest &lt; Test::Unit::TestCase @@ -50,14 +50,14 @@ class ForumHelperTest &lt; Test::Unit::TestCase
50 some_post.comments << Comment.new(:title => 'test', :body => 'test', :author => a2) 50 some_post.comments << Comment.new(:title => 'test', :body => 'test', :author => a2)
51 c = Comment.last 51 c = Comment.last
52 assert_equal 2, some_post.comments.count 52 assert_equal 2, some_post.comments.count
53 - assert_match /#{c.created_at.to_s} ago by <a href='[^']+'>a2<\/a>/, last_topic_update(some_post) 53 + assert_match(/#{Regexp.escape(c.created_at.to_s)} ago by <a href='[^']+'>a2<\/a>/, last_topic_update(some_post))
54 end 54 end
55 55
56 should "return last comment author's name from unauthenticated user" do 56 should "return last comment author's name from unauthenticated user" do
57 some_post = TextileArticle.create!(:name => 'First post', :profile => profile, :parent => forum, :published => true) 57 some_post = TextileArticle.create!(:name => 'First post', :profile => profile, :parent => forum, :published => true)
58 some_post.comments << Comment.new(:name => 'John', :email => 'lenon@example.com', :title => 'test', :body => 'test') 58 some_post.comments << Comment.new(:name => 'John', :email => 'lenon@example.com', :title => 'test', :body => 'test')
59 c = Comment.last 59 c = Comment.last
60 - assert_match /#{c.created_at.to_s} ago by John/m, last_topic_update(some_post) 60 + assert_match(/#{Regexp.escape(c.created_at.to_s)} ago by John/m, last_topic_update(some_post))
61 end 61 end
62 62
63 protected 63 protected
test/unit/product_test.rb
@@ -3,6 +3,7 @@ require File.dirname(__FILE__) + &#39;/../test_helper&#39; @@ -3,6 +3,7 @@ require File.dirname(__FILE__) + &#39;/../test_helper&#39;
3 class ProductTest < Test::Unit::TestCase 3 class ProductTest < Test::Unit::TestCase
4 4
5 def setup 5 def setup
  6 + Test::Unit::TestCase::setup
6 @product_category = fast_create(ProductCategory, :name => 'Products') 7 @product_category = fast_create(ProductCategory, :name => 'Products')
7 end 8 end
8 9
@@ -92,7 +93,7 @@ class ProductTest &lt; Test::Unit::TestCase @@ -92,7 +93,7 @@ class ProductTest &lt; Test::Unit::TestCase
92 p.stubs(:category_full_name).returns('interesting category') 93 p.stubs(:category_full_name).returns('interesting category')
93 p.save! 94 p.save!
94 95
95 - assert_includes Product.find_by_contents('interesting'), p 96 + assert_includes Product.find_by_contents('interesting')[:results], p
96 end 97 end
97 98
98 should 'have same lat and lng of its enterprise' do 99 should 'have same lat and lng of its enterprise' do
@@ -362,24 +363,24 @@ class ProductTest &lt; Test::Unit::TestCase @@ -362,24 +363,24 @@ class ProductTest &lt; Test::Unit::TestCase
362 should 'index by schema name when database is postgresql' do 363 should 'index by schema name when database is postgresql' do
363 uses_postgresql 'schema_one' 364 uses_postgresql 'schema_one'
364 p1 = Product.create!(:name => 'some thing', :product_category => @product_category) 365 p1 = Product.create!(:name => 'some thing', :product_category => @product_category)
365 - assert_equal Product.find_by_contents('thing'), [p1] 366 + assert_equal Product.find_by_contents('thing')[:results], [p1]
366 uses_postgresql 'schema_two' 367 uses_postgresql 'schema_two'
367 p2 = Product.create!(:name => 'another thing', :product_category => @product_category) 368 p2 = Product.create!(:name => 'another thing', :product_category => @product_category)
368 - assert_not_includes Product.find_by_contents('thing'), p1  
369 - assert_includes Product.find_by_contents('thing'), p2 369 + assert_not_includes Product.find_by_contents('thing')[:results], p1
  370 + assert_includes Product.find_by_contents('thing')[:results], p2
370 uses_postgresql 'schema_one' 371 uses_postgresql 'schema_one'
371 - assert_includes Product.find_by_contents('thing'), p1  
372 - assert_not_includes Product.find_by_contents('thing'), p2 372 + assert_includes Product.find_by_contents('thing')[:results], p1
  373 + assert_not_includes Product.find_by_contents('thing')[:results], p2
373 uses_sqlite 374 uses_sqlite
374 end 375 end
375 376
376 should 'not index by schema name when database is not postgresql' do 377 should 'not index by schema name when database is not postgresql' do
377 uses_sqlite 378 uses_sqlite
378 p1 = Product.create!(:name => 'some thing', :product_category => @product_category) 379 p1 = Product.create!(:name => 'some thing', :product_category => @product_category)
379 - assert_equal Product.find_by_contents('thing'), [p1] 380 + assert_equal Product.find_by_contents('thing')[:results], [p1]
380 p2 = Product.create!(:name => 'another thing', :product_category => @product_category) 381 p2 = Product.create!(:name => 'another thing', :product_category => @product_category)
381 - assert_includes Product.find_by_contents('thing'), p1  
382 - assert_includes Product.find_by_contents('thing'), p2 382 + assert_includes Product.find_by_contents('thing')[:results], p1
  383 + assert_includes Product.find_by_contents('thing')[:results], p2
383 end 384 end
384 385
385 end 386 end
test/unit/profile_test.rb
@@ -3,6 +3,10 @@ require File.dirname(__FILE__) + &#39;/../test_helper&#39; @@ -3,6 +3,10 @@ require File.dirname(__FILE__) + &#39;/../test_helper&#39;
3 class ProfileTest < Test::Unit::TestCase 3 class ProfileTest < Test::Unit::TestCase
4 fixtures :profiles, :environments, :users, :roles, :domains 4 fixtures :profiles, :environments, :users, :roles, :domains
5 5
  6 + def setup
  7 + Test::Unit::TestCase::setup
  8 + end
  9 +
6 def test_identifier_validation 10 def test_identifier_validation
7 p = Profile.new 11 p = Profile.new
8 p.valid? 12 p.valid?
@@ -100,8 +104,8 @@ class ProfileTest &lt; Test::Unit::TestCase @@ -100,8 +104,8 @@ class ProfileTest &lt; Test::Unit::TestCase
100 def test_find_by_contents 104 def test_find_by_contents
101 p = create(Profile, :name => 'wanted') 105 p = create(Profile, :name => 'wanted')
102 106
103 - assert Profile.find_by_contents('wanted').include?(p)  
104 - assert ! Profile.find_by_contents('not_wanted').include?(p) 107 + assert Profile.find_by_contents('wanted')[:results].include?(p)
  108 + assert ! Profile.find_by_contents('not_wanted')[:results].include?(p)
105 end 109 end
106 110
107 should 'remove pages when removing profile' do 111 should 'remove pages when removing profile' do
@@ -192,10 +196,10 @@ class ProfileTest &lt; Test::Unit::TestCase @@ -192,10 +196,10 @@ class ProfileTest &lt; Test::Unit::TestCase
192 small = create(Profile, :name => 'A small profile for testing') 196 small = create(Profile, :name => 'A small profile for testing')
193 big = create(Profile, :name => 'A big profile for testing') 197 big = create(Profile, :name => 'A big profile for testing')
194 198
195 - assert Profile.find_by_contents('small').include?(small)  
196 - assert Profile.find_by_contents('big').include?(big) 199 + assert Profile.find_by_contents('small')[:results].include?(small)
  200 + assert Profile.find_by_contents('big')[:results].include?(big)
197 201
198 - both = Profile.find_by_contents('profile testing') 202 + both = Profile.find_by_contents('profile testing')[:results]
199 assert both.include?(small) 203 assert both.include?(small)
200 assert both.include?(big) 204 assert both.include?(big)
201 end 205 end
@@ -517,18 +521,18 @@ class ProfileTest &lt; Test::Unit::TestCase @@ -517,18 +521,18 @@ class ProfileTest &lt; Test::Unit::TestCase
517 should 'actually index by results of extra_data_for_index' do 521 should 'actually index by results of extra_data_for_index' do
518 profile = TestingExtraDataForIndex.create!(:name => 'testprofile', :identifier => 'testprofile') 522 profile = TestingExtraDataForIndex.create!(:name => 'testprofile', :identifier => 'testprofile')
519 523
520 - assert_includes TestingExtraDataForIndex.find_by_contents('sample'), profile 524 + assert_includes TestingExtraDataForIndex.find_by_contents('sample')[:results], profile
521 end 525 end
522 526
523 should 'index profile identifier for searching' do 527 should 'index profile identifier for searching' do
524 Profile.destroy_all 528 Profile.destroy_all
525 p = create(Profile, :identifier => 'lalala') 529 p = create(Profile, :identifier => 'lalala')
526 - assert_includes Profile.find_by_contents('lalala'), p 530 + assert_includes Profile.find_by_contents('lalala')[:results], p
527 end 531 end
528 532
529 should 'index profile name for searching' do 533 should 'index profile name for searching' do
530 p = create(Profile, :name => 'Interesting Profile') 534 p = create(Profile, :name => 'Interesting Profile')
531 - assert_includes Profile.find_by_contents('interesting'), p 535 + assert_includes Profile.find_by_contents('interesting')[:results], p
532 end 536 end
533 537
534 should 'enabled by default on creation' do 538 should 'enabled by default on creation' do
@@ -1665,24 +1669,24 @@ class ProfileTest &lt; Test::Unit::TestCase @@ -1665,24 +1669,24 @@ class ProfileTest &lt; Test::Unit::TestCase
1665 should 'index by schema name when database is postgresql' do 1669 should 'index by schema name when database is postgresql' do
1666 uses_postgresql 'schema_one' 1670 uses_postgresql 'schema_one'
1667 p1 = Profile.create!(:name => 'some thing', :identifier => 'some-thing') 1671 p1 = Profile.create!(:name => 'some thing', :identifier => 'some-thing')
1668 - assert_equal Profile.find_by_contents('thing'), [p1] 1672 + assert_equal Profile.find_by_contents('thing')[:results], [p1]
1669 uses_postgresql 'schema_two' 1673 uses_postgresql 'schema_two'
1670 p2 = Profile.create!(:name => 'another thing', :identifier => 'another-thing') 1674 p2 = Profile.create!(:name => 'another thing', :identifier => 'another-thing')
1671 - assert_not_includes Profile.find_by_contents('thing'), p1  
1672 - assert_includes Profile.find_by_contents('thing'), p2 1675 + assert_not_includes Profile.find_by_contents('thing')[:results], p1
  1676 + assert_includes Profile.find_by_contents('thing')[:results], p2
1673 uses_postgresql 'schema_one' 1677 uses_postgresql 'schema_one'
1674 - assert_includes Profile.find_by_contents('thing'), p1  
1675 - assert_not_includes Profile.find_by_contents('thing'), p2 1678 + assert_includes Profile.find_by_contents('thing')[:results], p1
  1679 + assert_not_includes Profile.find_by_contents('thing')[:results], p2
1676 uses_sqlite 1680 uses_sqlite
1677 end 1681 end
1678 1682
1679 should 'not index by schema name when database is not postgresql' do 1683 should 'not index by schema name when database is not postgresql' do
1680 uses_sqlite 1684 uses_sqlite
1681 p1 = Profile.create!(:name => 'some thing', :identifier => 'some-thing') 1685 p1 = Profile.create!(:name => 'some thing', :identifier => 'some-thing')
1682 - assert_equal Profile.find_by_contents('thing'), [p1] 1686 + assert_equal Profile.find_by_contents('thing')[:results], [p1]
1683 p2 = Profile.create!(:name => 'another thing', :identifier => 'another-thing') 1687 p2 = Profile.create!(:name => 'another thing', :identifier => 'another-thing')
1684 - assert_includes Profile.find_by_contents('thing'), p1  
1685 - assert_includes Profile.find_by_contents('thing'), p2 1688 + assert_includes Profile.find_by_contents('thing')[:results], p1
  1689 + assert_includes Profile.find_by_contents('thing')[:results], p2
1686 end 1690 end
1687 1691
1688 should 'know if url is the profile homepage' do 1692 should 'know if url is the profile homepage' do
test/unit/tiny_mce_article_test.rb
@@ -3,7 +3,8 @@ require File.dirname(__FILE__) + &#39;/../test_helper&#39; @@ -3,7 +3,8 @@ require File.dirname(__FILE__) + &#39;/../test_helper&#39;
3 class TinyMceArticleTest < Test::Unit::TestCase 3 class TinyMceArticleTest < Test::Unit::TestCase
4 4
5 def setup 5 def setup
6 - Article.rebuild_index 6 + Test::Unit::TestCase::setup
  7 + Article.rebuild_solr_index
7 @profile = create_user('zezinho').person 8 @profile = create_user('zezinho').person
8 end 9 end
9 attr_reader :profile 10 attr_reader :profile
@@ -23,8 +24,8 @@ class TinyMceArticleTest &lt; Test::Unit::TestCase @@ -23,8 +24,8 @@ class TinyMceArticleTest &lt; Test::Unit::TestCase
23 24
24 should 'be found when searching for articles by query' do 25 should 'be found when searching for articles by query' do
25 tma = TinyMceArticle.create!(:name => 'test tinymce article', :body => '---', :profile => profile) 26 tma = TinyMceArticle.create!(:name => 'test tinymce article', :body => '---', :profile => profile)
26 - assert_includes TinyMceArticle.find_by_contents('article'), tma  
27 - assert_includes Article.find_by_contents('article'), tma 27 + assert_includes TinyMceArticle.find_by_contents('article')[:results], tma
  28 + assert_includes Article.find_by_contents('article')[:results], tma
28 end 29 end
29 30
30 should 'not sanitize target attribute' do 31 should 'not sanitize target attribute' do
vendor/plugins/access_control/init.rb
@@ -2,5 +2,5 @@ require &#39;acts_as_accessor&#39; @@ -2,5 +2,5 @@ require &#39;acts_as_accessor&#39;
2 require 'acts_as_accessible' 2 require 'acts_as_accessible'
3 require 'permission_name_helper' 3 require 'permission_name_helper'
4 module ApplicationHelper 4 module ApplicationHelper
5 - include PermissionName 5 + include PermissionNameHelper
6 end 6 end
vendor/plugins/access_control/lib/permission_name_helper.rb
1 -module PermissionName 1 +module PermissionNameHelper
2 def permission_name(p) 2 def permission_name(p)
3 msgid = ActiveRecord::Base::PERMISSIONS.values.inject({}){|s,v| s.merge(v)}[p] 3 msgid = ActiveRecord::Base::PERMISSIONS.values.inject({}){|s,v| s.merge(v)}[p]
4 gettext(msgid) 4 gettext(msgid)
vendor/plugins/acts_as_ferret/LICENSE
@@ -1,20 +0,0 @@ @@ -1,20 +0,0 @@
1 -Copyright (c) 2006 Kasper Weibel, Jens Kraemer  
2 -  
3 -Permission is hereby granted, free of charge, to any person obtaining  
4 -a copy of this software and associated documentation files (the  
5 -"Software"), to deal in the Software without restriction, including  
6 -without limitation the rights to use, copy, modify, merge, publish,  
7 -distribute, sublicense, and/or sell copies of the Software, and to  
8 -permit persons to whom the Software is furnished to do so, subject to  
9 -the following conditions:  
10 -  
11 -The above copyright notice and this permission notice shall be  
12 -included in all copies or substantial portions of the Software.  
13 -  
14 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,  
15 -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF  
16 -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND  
17 -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE  
18 -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION  
19 -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION  
20 -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  
vendor/plugins/acts_as_ferret/README
@@ -1,53 +0,0 @@ @@ -1,53 +0,0 @@
1 -= acts_as_ferret  
2 -  
3 -This ActiveRecord mixin adds full text search capabilities to any Rails model.  
4 -  
5 -It is heavily based on the original acts_as_ferret plugin done by  
6 -Kasper Weibel and a modified version done by Thomas Lockney, which  
7 -both can be found on http://ferret.davebalmain.com/trac/wiki/FerretOnRails  
8 -  
9 -== Installation  
10 -  
11 -=== Installation inside your Rails project via script/plugin  
12 -  
13 -script/plugin install svn://projects.jkraemer.net/acts_as_ferret/trunk/plugin/acts_as_ferret  
14 -  
15 -Aaf is is also available via git from Rubyforge:  
16 -git clone git://rubyforge.org/actsasferret.git  
17 -  
18 -=== System-wide installation with Rubygems  
19 -  
20 -<tt>sudo gem install acts_as_ferret</tt>  
21 -  
22 -To use acts_as_ferret in your project, add the following line to your  
23 -project's config/environment.rb:  
24 -  
25 -<tt>require 'acts_as_ferret'</tt>  
26 -  
27 -Call the aaf_install script inside your project directory to install the sample  
28 -config file and the drb server start/stop script.  
29 -  
30 -  
31 -== Usage  
32 -  
33 -include the following in your model class (specifiying the fields you want to get indexed):  
34 -  
35 -<tt>acts_as_ferret :fields => [ :title, :description ]</tt>  
36 -  
37 -now you can use ModelClass.find_by_contents(query) to find instances of your model  
38 -whose indexed fields match a given query. All query terms are required by default,  
39 -but explicit OR queries are possible. This differs from the ferret default, but  
40 -imho is the more often needed/expected behaviour (more query terms result in  
41 -less results).  
42 -  
43 -Please see ActsAsFerret::ActMethods#acts_as_ferret for more information.  
44 -  
45 -== License  
46 -  
47 -Released under the MIT license.  
48 -  
49 -== Authors  
50 -  
51 -* Kasper Weibel Nielsen-Refs (original author)  
52 -* Jens Kraemer <jk@jkraemer.net> (current maintainer)  
53 -  
vendor/plugins/acts_as_ferret/bin/aaf_install
@@ -1,23 +0,0 @@ @@ -1,23 +0,0 @@
1 -# acts_as_ferret gem install script  
2 -# Use inside the root of your Rails project  
3 -require 'fileutils'  
4 -  
5 -@basedir = File.join(File.dirname(__FILE__), '..')  
6 -  
7 -def install(dir, file, executable=false)  
8 - puts "Installing: #{file}"  
9 - target = File.join('.', dir, file)  
10 - if File.exists?(target)  
11 - puts "#{target} already exists, skipping"  
12 - else  
13 - FileUtils.cp File.join(@basedir, dir, file), target  
14 - FileUtils.chmod 0755, target if executable  
15 - end  
16 -end  
17 -  
18 -  
19 -install 'script', 'ferret_server', true  
20 -install 'config', 'ferret_server.yml'  
21 -  
22 -puts IO.read(File.join(@basedir, 'README'))  
23 -  
vendor/plugins/acts_as_ferret/config/ferret_server.yml
@@ -1,24 +0,0 @@ @@ -1,24 +0,0 @@
1 -# configuration for the acts_as_ferret DRb server  
2 -# host: where to reach the DRb server (used by application processes to contact the server)  
3 -# port: which port the server should listen on  
4 -# socket: where the DRb server should create the socket (absolute path), this setting overrides host:port configuration  
5 -# pid_file: location of the server's pid file (relative to RAILS_ROOT)  
6 -# log_file: log file (default: RAILS_ROOT/log/ferret_server.log  
7 -# log_level: log level for the server's logger  
8 -production:  
9 - host: localhost  
10 - port: 9010  
11 - pid_file: log/ferret.pid  
12 - log_file: log/ferret_server.log  
13 - log_level: warn  
14 -  
15 -# aaf won't try to use the DRb server in environments that are not  
16 -# configured here.  
17 -#development:  
18 -# host: localhost  
19 -# port: 9010  
20 -# pid_file: log/ferret.pid  
21 -#test:  
22 -# host: localhost  
23 -# port: 9009  
24 -# pid_file: log/ferret.pid  
vendor/plugins/acts_as_ferret/doc/README.win32
@@ -1,23 +0,0 @@ @@ -1,23 +0,0 @@
1 -Credits  
2 -=======  
3 -  
4 -The Win32 service support scripts have been written by  
5 -Herryanto Siatono <herryanto@pluitsolutions.com>.  
6 -  
7 -See his accompanying blog posting at  
8 -http://www.pluitsolutions.com/2007/07/30/acts-as-ferret-drbserver-win32-service/  
9 -  
10 -  
11 -Usage  
12 -=====  
13 -  
14 -There are two scripts:  
15 -  
16 -script/ferret_service is used to install/remove/start/stop the win32 service.  
17 -  
18 -script/ferret_daemon is to be called by Win32 service to start/stop the  
19 -DRbServer.  
20 -  
21 -Run 'ruby script/ferret_service -h' for more info.  
22 -  
23 -  
vendor/plugins/acts_as_ferret/doc/monit-example
@@ -1,22 +0,0 @@ @@ -1,22 +0,0 @@
1 -# monit configuration snippet to watch the Ferret DRb server shipped with  
2 -# acts_as_ferret  
3 -check process ferret with pidfile /path/to/ferret.pid  
4 -  
5 - # username is the user the drb server should be running as (It's good practice  
6 - # to run such services as a non-privileged user)  
7 - start program = "/bin/su -c 'cd /path/to/your/app/current/ && script/ferret_server -e production start' username"  
8 - stop program = "/bin/su -c 'cd /path/to/your/app/current/ && script/ferret_server -e production stop' username"  
9 -  
10 - # cpu usage boundaries  
11 - if cpu > 60% for 2 cycles then alert  
12 - if cpu > 90% for 5 cycles then restart  
13 -  
14 - # memory usage varies with index size and usage scenarios, so check how  
15 - # much memory your DRb server uses up usually and add some spare to that  
16 - # before enabling this rule:  
17 - # if totalmem > 50.0 MB for 5 cycles then restart  
18 -  
19 - # adjust port numbers according to your setup:  
20 - if failed port 9010 then alert  
21 - if failed port 9010 for 2 cycles then restart  
22 - group ferret  
vendor/plugins/acts_as_ferret/init.rb
@@ -1,24 +0,0 @@ @@ -1,24 +0,0 @@
1 -# Copyright (c) 2006 Kasper Weibel Nielsen-Refs, Thomas Lockney, Jens Krämer  
2 -#  
3 -# Permission is hereby granted, free of charge, to any person obtaining a copy  
4 -# of this software and associated documentation files (the "Software"), to deal  
5 -# in the Software without restriction, including without limitation the rights  
6 -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell  
7 -# copies of the Software, and to permit persons to whom the Software is  
8 -# furnished to do so, subject to the following conditions:  
9 -#  
10 -# The above copyright notice and this permission notice shall be included in all  
11 -# copies or substantial portions of the Software.  
12 -#  
13 -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
14 -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
15 -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  
16 -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
17 -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  
18 -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  
19 -# SOFTWARE.  
20 -  
21 -require 'acts_as_ferret'  
22 -  
23 -config.after_initialize { ActsAsFerret::load_config }  
24 -config.to_prepare { ActsAsFerret::load_config }  
vendor/plugins/acts_as_ferret/install.rb
@@ -1,18 +0,0 @@ @@ -1,18 +0,0 @@
1 -# acts_as_ferret install script  
2 -require 'fileutils'  
3 -  
4 -def install(file)  
5 - puts "Installing: #{file}"  
6 - target = File.join(File.dirname(__FILE__), '..', '..', '..', file)  
7 - if File.exists?(target)  
8 - puts "target #{target} already exists, skipping"  
9 - else  
10 - FileUtils.cp File.join(File.dirname(__FILE__), file), target  
11 - end  
12 -end  
13 -  
14 -install File.join( 'script', 'ferret_server' )  
15 -install File.join( 'config', 'ferret_server.yml' )  
16 -  
17 -puts IO.read(File.join(File.dirname(__FILE__), 'README'))  
18 -  
vendor/plugins/acts_as_ferret/lib/act_methods.rb
@@ -1,155 +0,0 @@ @@ -1,155 +0,0 @@
1 -module ActsAsFerret #:nodoc:  
2 -  
3 - # This module defines the acts_as_ferret method and is included into  
4 - # ActiveRecord::Base  
5 - module ActMethods  
6 -  
7 -  
8 - def reloadable?; false end  
9 -  
10 - # declares a class as ferret-searchable.  
11 - #  
12 - # ====options:  
13 - # fields:: names all fields to include in the index. If not given,  
14 - # all attributes of the class will be indexed. You may also give  
15 - # symbols pointing to instance methods of your model here, i.e.  
16 - # to retrieve and index data from a related model.  
17 - #  
18 - # additional_fields:: names fields to include in the index, in addition  
19 - # to those derived from the db scheme. use if you want  
20 - # to add custom fields derived from methods to the db  
21 - # fields (which will be picked by aaf). This option will  
22 - # be ignored when the fields option is given, in that  
23 - # case additional fields get specified there.  
24 - #  
25 - # if:: Can be set to a block that will be called with the record in question  
26 - # to determine if it should be indexed or not.  
27 - #  
28 - # index_dir:: declares the directory where to put the index for this class.  
29 - # The default is RAILS_ROOT/index/RAILS_ENV/CLASSNAME.  
30 - # The index directory will be created if it doesn't exist.  
31 - #  
32 - # reindex_batch_size:: reindexing is done in batches of this size, default is 1000  
33 - # mysql_fast_batches:: set this to false to disable the faster mysql batching  
34 - # algorithm if this model uses a non-integer primary key named  
35 - # 'id' on MySQL.  
36 - #  
37 - # ferret:: Hash of Options that directly influence the way the Ferret engine works. You  
38 - # can use most of the options the Ferret::I class accepts here, too. Among the  
39 - # more useful are:  
40 - #  
41 - # or_default:: whether query terms are required by  
42 - # default (the default, false), or not (true)  
43 - #  
44 - # analyzer:: the analyzer to use for query parsing (default: nil,  
45 - # which means the ferret StandardAnalyzer gets used)  
46 - #  
47 - # default_field:: use to set one or more fields that are searched for query terms  
48 - # that don't have an explicit field list. This list should *not*  
49 - # contain any untokenized fields. If it does, you're asking  
50 - # for trouble (i.e. not getting results for queries having  
51 - # stop words in them). Aaf by default initializes the default field  
52 - # list to contain all tokenized fields. If you use :single_index => true,  
53 - # you really should set this option specifying your default field  
54 - # list (which should be equal in all your classes sharing the index).  
55 - # Otherwise you might get incorrect search results and you won't get  
56 - # any lazy loading of stored field data.  
57 - #  
58 - # For downwards compatibility reasons you can also specify the Ferret options in the  
59 - # last Hash argument.  
60 - def acts_as_ferret(options={})  
61 -  
62 - extend ClassMethods  
63 -  
64 - include InstanceMethods  
65 - include MoreLikeThis::InstanceMethods  
66 -  
67 - if options[:rdig]  
68 - cattr_accessor :rdig_configuration  
69 - self.rdig_configuration = options[:rdig]  
70 - require 'rdig_adapter'  
71 - include ActsAsFerret::RdigAdapter  
72 - end  
73 -  
74 - unless included_modules.include?(ActsAsFerret::WithoutAR)  
75 - # set up AR hooks  
76 - after_create :ferret_create  
77 - after_update :ferret_update  
78 - after_destroy :ferret_destroy  
79 - end  
80 -  
81 - cattr_accessor :aaf_configuration  
82 -  
83 - # apply default config for rdig based models  
84 - if options[:rdig]  
85 - options[:fields] ||= { :title => { :boost => 3, :store => :yes },  
86 - :content => { :store => :yes } }  
87 - end  
88 -  
89 - # name of this index  
90 - index_name = options.delete(:index) || self.name.underscore  
91 -  
92 - index = ActsAsFerret::register_class_with_index(self, index_name, options)  
93 - self.aaf_configuration = index.index_definition.dup  
94 - logger.debug "configured index for class #{self.name}:\n#{aaf_configuration.inspect}"  
95 -  
96 - # update our copy of the global index config with options local to this class  
97 - aaf_configuration[:class_name] ||= self.name  
98 - aaf_configuration[:if] ||= options[:if]  
99 -  
100 - # add methods for retrieving field values  
101 - add_fields options[:fields]  
102 - add_fields options[:additional_fields]  
103 - add_fields aaf_configuration[:fields]  
104 - add_fields aaf_configuration[:additional_fields]  
105 -  
106 - # not good at class level, index might get initialized too early  
107 - #if options[:remote]  
108 - # aaf_index.ensure_index_exists  
109 - #end  
110 - end  
111 -  
112 -  
113 - protected  
114 -  
115 -  
116 - # helper to defines a method which adds the given field to a ferret  
117 - # document instance  
118 - def define_to_field_method(field, options = {})  
119 - method_name = "#{field}_to_ferret"  
120 - return if instance_methods.include?(method_name) # already defined  
121 - aaf_configuration[:defined_fields] ||= {}  
122 - aaf_configuration[:defined_fields][field] = options  
123 - dynamic_boost = options[:boost] if options[:boost].is_a?(Symbol)  
124 - via = options[:via] || field  
125 - define_method(method_name.to_sym) do  
126 - val = begin  
127 - content_for_field_name(field, via, dynamic_boost)  
128 - rescue  
129 - logger.warn("Error retrieving value for field #{field}: #{$!}")  
130 - ''  
131 - end  
132 - logger.debug("Adding field #{field} with value '#{val}' to index")  
133 - val  
134 - end  
135 - end  
136 -  
137 - def add_fields(field_config)  
138 - # TODO  
139 - #field_config.each do |*args|  
140 - # define_to_field_method *args  
141 - #end  
142 - if field_config.is_a? Hash  
143 - field_config.each_pair do |field, options|  
144 - define_to_field_method field, options  
145 - end  
146 - elsif field_config.respond_to?(:each)  
147 - field_config.each do |field|  
148 - define_to_field_method field  
149 - end  
150 - end  
151 - end  
152 -  
153 - end  
154 -  
155 -end  
vendor/plugins/acts_as_ferret/lib/acts_as_ferret.rb
@@ -1,567 +0,0 @@ @@ -1,567 +0,0 @@
1 -# Copyright (c) 2006 Kasper Weibel Nielsen-Refs, Thomas Lockney, Jens Krämer  
2 -#  
3 -# Permission is hereby granted, free of charge, to any person obtaining a copy  
4 -# of this software and associated documentation files (the "Software"), to deal  
5 -# in the Software without restriction, including without limitation the rights  
6 -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell  
7 -# copies of the Software, and to permit persons to whom the Software is  
8 -# furnished to do so, subject to the following conditions:  
9 -#  
10 -# The above copyright notice and this permission notice shall be included in all  
11 -# copies or substantial portions of the Software.  
12 -#  
13 -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
14 -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
15 -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  
16 -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
17 -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  
18 -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  
19 -# SOFTWARE.  
20 -  
21 -require 'active_support'  
22 -require 'active_record'  
23 -require 'set'  
24 -require 'enumerator'  
25 -require 'ferret'  
26 -  
27 -require 'ferret_find_methods'  
28 -require 'remote_functions'  
29 -require 'blank_slate'  
30 -require 'bulk_indexer'  
31 -require 'ferret_extensions'  
32 -require 'act_methods'  
33 -require 'search_results'  
34 -require 'class_methods'  
35 -require 'ferret_result'  
36 -require 'instance_methods'  
37 -require 'without_ar'  
38 -  
39 -require 'multi_index'  
40 -require 'remote_multi_index'  
41 -require 'more_like_this'  
42 -  
43 -require 'index'  
44 -require 'local_index'  
45 -require 'remote_index'  
46 -  
47 -require 'ferret_server'  
48 -  
49 -require 'rdig_adapter'  
50 -  
51 -# The Rails ActiveRecord Ferret Mixin.  
52 -#  
53 -# This mixin adds full text search capabilities to any Rails model.  
54 -#  
55 -# The current version emerged from on the original acts_as_ferret plugin done by  
56 -# Kasper Weibel and a modified version done by Thomas Lockney, which both can be  
57 -# found on the Ferret Wiki: http://ferret.davebalmain.com/trac/wiki/FerretOnRails.  
58 -#  
59 -# basic usage:  
60 -# include the following in your model class (specifiying the fields you want to get indexed):  
61 -# acts_as_ferret :fields => [ :title, :description ]  
62 -#  
63 -# now you can use ModelClass.find_by_contents(query) to find instances of your model  
64 -# whose indexed fields match a given query. All query terms are required by default, but  
65 -# explicit OR queries are possible. This differs from the ferret default, but imho is the more  
66 -# often needed/expected behaviour (more query terms result in less results).  
67 -#  
68 -# Released under the MIT license.  
69 -#  
70 -# Authors:  
71 -# Kasper Weibel Nielsen-Refs (original author)  
72 -# Jens Kraemer <jk@jkraemer.net> (active maintainer since 2006)  
73 -#  
74 -#  
75 -# == Global properties  
76 -#  
77 -# raise_drb_errors:: Set this to true if you want aaf to raise Exceptions  
78 -# in case the DRb server cannot be reached (in other word - behave like  
79 -# versions up to 0.4.3). Defaults to false so DRb exceptions  
80 -# are logged but not raised. Be sure to set up some  
81 -# monitoring so you still detect when your DRb server died for  
82 -# whatever reason.  
83 -#  
84 -# remote:: Set this to false to force acts_as_ferret into local (non-DRb) mode even if  
85 -# config/ferret_server.yml contains a section for the current RAILS_ENV  
86 -# Usually you won't need to touch this option - just configure DRb for  
87 -# production mode in ferret_server.yml.  
88 -#  
89 -module ActsAsFerret  
90 -  
91 - class ActsAsFerretError < StandardError; end  
92 - class IndexNotDefined < ActsAsFerretError; end  
93 - class IndexAlreadyDefined < ActsAsFerretError; end  
94 -  
95 - # global Hash containing all multi indexes created by all classes using the plugin  
96 - # key is the concatenation of alphabetically sorted names of the classes the  
97 - # searcher searches.  
98 - @@multi_indexes = Hash.new  
99 - def self.multi_indexes; @@multi_indexes end  
100 -  
101 - # global Hash containing the ferret indexes of all classes using the plugin  
102 - # key is the index name.  
103 - @@ferret_indexes = Hash.new  
104 - def self.ferret_indexes; @@ferret_indexes end  
105 -  
106 - # mapping from class name to index name  
107 - @@index_using_classes = {}  
108 -  
109 - @@logger = Logger.new "#{RAILS_ROOT}/log/acts_as_ferret.log"  
110 - @@logger.level = ActiveRecord::Base.logger.level rescue Logger::DEBUG  
111 - mattr_accessor :logger  
112 -  
113 -  
114 - # Default ferret configuration for index fields  
115 - DEFAULT_FIELD_OPTIONS = {  
116 - :store => :no,  
117 - :highlight => :yes,  
118 - :index => :yes,  
119 - :term_vector => :with_positions_offsets,  
120 - :boost => 1.0  
121 - }  
122 -  
123 - @@raise_drb_errors = false  
124 - mattr_writer :raise_drb_errors  
125 - def self.raise_drb_errors?; @@raise_drb_errors end  
126 -  
127 - @@remote = nil  
128 - mattr_accessor :remote  
129 - def self.remote?  
130 - if @@remote.nil?  
131 - if ENV["FERRET_USE_LOCAL_INDEX"] || ActsAsFerret::Remote::Server.running  
132 - @@remote = false  
133 - else  
134 - @@remote = ActsAsFerret::Remote::Config.new.uri rescue false  
135 - end  
136 - if @@remote  
137 - logger.info "Will use remote index server which should be available at #{@@remote}"  
138 - else  
139 - logger.info "Will use local index."  
140 - end  
141 - end  
142 - @@remote  
143 - end  
144 - remote?  
145 -  
146 -  
147 - # Globally declares an index.  
148 - #  
149 - # This method is also used to implicitly declare an index when you use the  
150 - # acts_as_ferret call in your class. Returns the created index instance.  
151 - #  
152 - # === Options are:  
153 - #  
154 - # +models+:: Hash of model classes and their per-class option hashes which should  
155 - # use this index. Any models mentioned here will automatically use  
156 - # the index, there is no need to explicitly call +acts_as_ferret+ in the  
157 - # model class definition.  
158 - def self.define_index(name, options = {})  
159 - name = name.to_sym  
160 - pending_classes = nil  
161 - if ferret_indexes.has_key?(name)  
162 - # seems models have been already loaded. remove that index for now,  
163 - # re-register any already loaded classes later on.  
164 - idx = get_index(name)  
165 - pending_classes = idx.index_definition[:registered_models]  
166 - pending_classes_configs = idx.registered_models_config  
167 - idx.close  
168 - ferret_indexes.delete(name)  
169 - end  
170 -  
171 - index_definition = {  
172 - :index_dir => "#{ActsAsFerret::index_dir}/#{name}",  
173 - :name => name,  
174 - :single_index => false,  
175 - :reindex_batch_size => 1000,  
176 - :ferret => {},  
177 - :ferret_fields => {}, # list of indexed fields that will be filled later  
178 - :enabled => true, # used for class-wide disabling of Ferret  
179 - :mysql_fast_batches => true, # turn off to disable the faster, id based batching mechanism for MySQL  
180 - :raise_drb_errors => false # handle DRb connection errors by default  
181 - }.update( options )  
182 -  
183 - index_definition[:registered_models] = []  
184 -  
185 - # build ferret configuration  
186 - index_definition[:ferret] = {  
187 - :or_default => false,  
188 - :handle_parse_errors => true,  
189 - :default_field => nil, # will be set later on  
190 - #:max_clauses => 512,  
191 - #:analyzer => Ferret::Analysis::StandardAnalyzer.new,  
192 - # :wild_card_downcase => true  
193 - }.update( options[:ferret] || {} )  
194 -  
195 - index_definition[:user_default_field] = index_definition[:ferret][:default_field]  
196 -  
197 - unless remote?  
198 - ActsAsFerret::ensure_directory index_definition[:index_dir]  
199 - index_definition[:index_base_dir] = index_definition[:index_dir]  
200 - index_definition[:index_dir] = find_last_index_version(index_definition[:index_dir])  
201 - logger.debug "using index in #{index_definition[:index_dir]}"  
202 - end  
203 -  
204 - # these properties are somewhat vital to the plugin and shouldn't  
205 - # be overwritten by the user:  
206 - index_definition[:ferret].update(  
207 - :key => ((Noosfero::MultiTenancy.on? and ActiveRecord::Base.postgresql?) ? [:id, :class_name, :schema_name] : [:id, :class_name]),  
208 - :path => index_definition[:index_dir],  
209 - :auto_flush => true, # slower but more secure in terms of locking problems TODO disable when running in drb mode?  
210 - :create_if_missing => true  
211 - )  
212 -  
213 - # field config  
214 - index_definition[:ferret_fields] = build_field_config( options[:fields] )  
215 - index_definition[:ferret_fields].update build_field_config( options[:additional_fields] )  
216 -  
217 - idx = ferret_indexes[name] = create_index_instance( index_definition )  
218 -  
219 - # re-register early loaded classes  
220 - if pending_classes  
221 - pending_classes.each { |clazz| idx.register_class clazz, { :force_re_registration => true }.merge(pending_classes_configs[clazz]) }  
222 - end  
223 -  
224 - if models = options[:models]  
225 - models.each do |clazz, config|  
226 - clazz.send :include, ActsAsFerret::WithoutAR unless clazz.respond_to?(:acts_as_ferret)  
227 - clazz.acts_as_ferret config.merge(:index => name)  
228 - end  
229 - end  
230 -  
231 - return idx  
232 - end  
233 -  
234 - # called internally by the acts_as_ferret method  
235 - #  
236 - # returns the index  
237 - def self.register_class_with_index(clazz, index_name, options = {})  
238 - index_name = index_name.to_sym  
239 - @@index_using_classes[clazz.name] = index_name  
240 - unless index = ferret_indexes[index_name]  
241 - # index definition on the fly  
242 - # default to all attributes of this class  
243 - options[:fields] ||= clazz.new.attributes.keys.map { |k| k.to_sym }  
244 - index = define_index index_name, options  
245 - end  
246 - index.register_class(clazz, options)  
247 - return index  
248 - end  
249 -  
250 - def self.load_config  
251 - # using require_dependency to make the reloading in dev mode work.  
252 - require_dependency "#{RAILS_ROOT}/config/aaf.rb"  
253 - ActsAsFerret::logger.info "loaded configuration file aaf.rb"  
254 - rescue LoadError  
255 - ensure  
256 - @aaf_config_loaded = true  
257 - end  
258 -  
259 - # returns the index with the given name.  
260 - def self.get_index(name)  
261 - name = name.to_sym rescue nil  
262 - unless ferret_indexes.has_key?(name)  
263 - if @aaf_config_loaded  
264 - raise IndexNotDefined.new(name.to_s)  
265 - else  
266 - load_config and return get_index name  
267 - end  
268 - end  
269 - ferret_indexes[name]  
270 - end  
271 -  
272 - # count hits for a query with multiple models  
273 - def self.total_hits(query, models, options = {})  
274 - find_index(models).total_hits query, options.merge( :models => models )  
275 - end  
276 -  
277 - # find ids of records with multiple models  
278 - # TODO pagination logic?  
279 - def self.find_ids(query, models, options = {}, &block)  
280 - find_index(models).find_ids query, options.merge( :models => models ), &block  
281 - end  
282 -  
283 - def self.find_index(models_or_index_name)  
284 - case models_or_index_name  
285 - when Symbol  
286 - get_index models_or_index_name  
287 - when String  
288 - get_index models_or_index_name.to_sym  
289 - #when Array  
290 - # get_index_for models_or_index_name  
291 - else  
292 - get_index_for models_or_index_name  
293 - end  
294 - end  
295 -  
296 - def self.find(query, models_or_index_name, options = {}, ar_options = {})  
297 - # TODO generalize local/remote index so we can remove the workaround below  
298 - # (replace logic in class_methods#find_with_ferret)  
299 - # maybe put pagination stuff in a module to be included by all index  
300 - # implementations  
301 - models = [ models_or_index_name ] if Class === models_or_index_name  
302 - if models && models.size == 1  
303 - return models.shift.find_with_ferret query, options, ar_options  
304 - end  
305 - index = find_index(models_or_index_name)  
306 - multi = (MultiIndex === index or index.shared?)  
307 - if options[:per_page]  
308 - options[:page] = options[:page] ? options[:page].to_i : 1  
309 - limit = options[:per_page]  
310 - offset = (options[:page] - 1) * limit  
311 - if ar_options[:conditions] && !multi  
312 - ar_options[:limit] = limit  
313 - ar_options[:offset] = offset  
314 - options[:limit] = :all  
315 - options.delete :offset  
316 - else  
317 - # do pagination with ferret (or after everything is done in the case  
318 - # of multi_search)  
319 - options[:limit] = limit  
320 - options[:offset] = offset  
321 - end  
322 - elsif ar_options[:conditions]  
323 - if multi  
324 - # multisearch ignores find_options limit and offset  
325 - options[:limit] ||= ar_options.delete(:limit)  
326 - options[:offset] ||= ar_options.delete(:offset)  
327 - else  
328 - # let the db do the limiting and offsetting for single-table searches  
329 - unless options[:limit] == :all  
330 - ar_options[:limit] ||= options.delete(:limit)  
331 - end  
332 - ar_options[:offset] ||= options.delete(:offset)  
333 - options[:limit] = :all  
334 - end  
335 - end  
336 -  
337 - total_hits, result = index.find_records query, options.merge(:models => models), ar_options  
338 - logger.debug "Query: #{query}\ntotal hits: #{total_hits}, results delivered: #{result.size}"  
339 - SearchResults.new(result, total_hits, options[:page], options[:per_page])  
340 - end  
341 -  
342 - # returns the index used by the given class.  
343 - #  
344 - # If multiple classes are given, either the single index shared by these  
345 - # classes, or a multi index (to be used for search only) across the indexes  
346 - # of all models, is returned.  
347 - def self.get_index_for(*classes)  
348 - classes.flatten!  
349 - raise ArgumentError.new("no class specified") unless classes.any?  
350 - classes.map!(&:constantize) unless Class === classes.first  
351 - logger.debug "index_for #{classes.inspect}"  
352 - index = if classes.size > 1  
353 - indexes = classes.map { |c| get_index_for c }.uniq  
354 - indexes.size > 1 ? multi_index(indexes) : indexes.first  
355 - else  
356 - clazz = classes.first  
357 - clazz = clazz.superclass while clazz && !@@index_using_classes.has_key?(clazz.name)  
358 - get_index @@index_using_classes[clazz.name]  
359 - end  
360 - raise IndexNotDefined.new("no index found for class: #{classes.map(&:name).join(',')}") if index.nil?  
361 - return index  
362 - end  
363 -  
364 -  
365 - # creates a new Index instance.  
366 - def self.create_index_instance(definition)  
367 - (remote? ? RemoteIndex : LocalIndex).new(definition)  
368 - end  
369 -  
370 - def self.rebuild_index(name)  
371 - get_index(name).rebuild_index  
372 - end  
373 -  
374 - def self.change_index_dir(name, new_dir)  
375 - get_index(name).change_index_dir new_dir  
376 - end  
377 -  
378 - # find the most recent version of an index  
379 - def self.find_last_index_version(basedir)  
380 - # check for versioned index  
381 - versions = Dir.entries(basedir).select do |f|  
382 - dir = File.join(basedir, f)  
383 - File.directory?(dir) && File.file?(File.join(dir, 'segments')) && f =~ /^\d+(_\d+)?$/  
384 - end  
385 - if versions.any?  
386 - # select latest version  
387 - versions.sort!  
388 - File.join basedir, versions.last  
389 - else  
390 - basedir  
391 - end  
392 - end  
393 -  
394 - # returns a MultiIndex instance operating on a MultiReader  
395 - def self.multi_index(indexes)  
396 - index_names = indexes.dup  
397 - index_names = index_names.map(&:to_s) if Symbol === index_names.first  
398 - if String === index_names.first  
399 - indexes = index_names.map{ |name| get_index name }  
400 - else  
401 - index_names = index_names.map{ |i| i.index_name.to_s }  
402 - end  
403 - key = index_names.sort.join(",")  
404 - ActsAsFerret::multi_indexes[key] ||= (remote? ? ActsAsFerret::RemoteMultiIndex : ActsAsFerret::MultiIndex).new(indexes)  
405 - end  
406 -  
407 - # check for per-model conditions and return these if provided  
408 - def self.conditions_for_model(model, conditions = {})  
409 - if Hash === conditions  
410 - key = model.name.underscore.to_sym  
411 - conditions = conditions[key]  
412 - end  
413 - return conditions  
414 - end  
415 -  
416 - # retrieves search result records from a data structure like this:  
417 - # { 'Model1' => { '1' => [ rank, score ], '2' => [ rank, score ] }  
418 - #  
419 - # TODO: in case of STI AR will filter out hits from other  
420 - # classes for us, but this  
421 - # will lead to less results retrieved --> scoping of ferret query  
422 - # to self.class is still needed.  
423 - # from the ferret ML (thanks Curtis Hatter)  
424 - # > I created a method in my base STI class so I can scope my query. For scoping  
425 - # > I used something like the following line:  
426 - # >  
427 - # > query << " role:#{self.class.eql?(Contents) '*' : self.class}"  
428 - # >  
429 - # > Though you could make it more generic by simply asking  
430 - # > "self.descends_from_active_record?" which is how rails decides if it should  
431 - # > scope your "find" query for STI models. You can check out "base.rb" in  
432 - # > activerecord to see that.  
433 - # but maybe better do the scoping in find_ids_with_ferret...  
434 - def self.retrieve_records(id_arrays, find_options = {})  
435 - result = []  
436 - # get objects for each model  
437 - id_arrays.each do |model, id_array|  
438 - next if id_array.empty?  
439 - model_class = model.constantize  
440 -  
441 - # merge conditions  
442 - conditions = conditions_for_model model_class, find_options[:conditions]  
443 - conditions = combine_conditions([ "#{model_class.table_name}.#{model_class.primary_key} in (?)",  
444 - id_array.keys ],  
445 - conditions)  
446 -  
447 - # check for include association that might only exist on some models in case of multi_search  
448 - filtered_include_options = []  
449 - if include_options = find_options[:include]  
450 - include_options = [ include_options ] unless include_options.respond_to?(:each)  
451 - include_options.each do |include_option|  
452 - filtered_include_options << include_option if model_class.reflections.has_key?(include_option.is_a?(Hash) ? include_option.keys[0].to_sym : include_option.to_sym)  
453 - end  
454 - end  
455 - filtered_include_options = nil if filtered_include_options.empty?  
456 -  
457 - # fetch  
458 - tmp_result = model_class.find(:all, find_options.merge(:conditions => conditions,  
459 - :include => filtered_include_options))  
460 -  
461 - # set scores and rank  
462 - tmp_result.each do |record|  
463 - record.ferret_rank, record.ferret_score = id_array[record.id.to_s]  
464 - end  
465 - # merge with result array  
466 - result += tmp_result  
467 - end  
468 -  
469 - # order results as they were found by ferret, unless an AR :order  
470 - # option was given  
471 - result.sort! { |a, b| a.ferret_rank <=> b.ferret_rank } unless find_options[:order]  
472 - return result  
473 - end  
474 -  
475 - # combine our conditions with those given by user, if any  
476 - def self.combine_conditions(conditions, additional_conditions = [])  
477 - returning conditions do  
478 - if additional_conditions && additional_conditions.any?  
479 - cust_opts = (Array === additional_conditions) ? additional_conditions.dup : [ additional_conditions ]  
480 - logger.debug "cust_opts: #{cust_opts.inspect}"  
481 - conditions.first << " and " << cust_opts.shift  
482 - conditions.concat(cust_opts)  
483 - end  
484 - end  
485 - end  
486 -  
487 - def self.build_field_config(fields)  
488 - field_config = {}  
489 - case fields  
490 - when Array  
491 - fields.each { |name| field_config[name] = field_config_for name }  
492 - when Hash  
493 - fields.each { |name, options| field_config[name] = field_config_for name, options }  
494 - else raise InvalidArgumentError.new(":fields option must be Hash or Array")  
495 - end if fields  
496 - return field_config  
497 - end  
498 -  
499 - def self.ensure_directory(dir)  
500 - FileUtils.mkdir_p dir unless (File.directory?(dir) || File.symlink?(dir))  
501 - end  
502 -  
503 -  
504 - # make sure the default index base dir exists. by default, all indexes are created  
505 - # under RAILS_ROOT/index/RAILS_ENV  
506 - def self.init_index_basedir  
507 - index_base = "#{RAILS_ROOT}/index"  
508 - @@index_dir = "#{index_base}/#{RAILS_ENV}"  
509 - end  
510 -  
511 - mattr_accessor :index_dir  
512 - init_index_basedir  
513 -  
514 - def self.append_features(base)  
515 - super  
516 - base.extend(ClassMethods)  
517 - end  
518 -  
519 - # builds a FieldInfos instance for creation of an index  
520 - def self.field_infos(index_definition)  
521 - # default attributes for fields  
522 - fi = Ferret::Index::FieldInfos.new(:store => :no,  
523 - :index => :yes,  
524 - :term_vector => :no,  
525 - :boost => 1.0)  
526 - # primary key  
527 - fi.add_field(:id, :store => :yes, :index => :untokenized)  
528 - # class_name  
529 - fi.add_field(:class_name, :store => :yes, :index => :untokenized)  
530 -  
531 - # other fields  
532 - index_definition[:ferret_fields].each_pair do |field, options|  
533 - options = options.dup  
534 - options.delete :via  
535 - options.delete :boost if options[:boost].is_a?(Symbol) # dynamic boost  
536 - fi.add_field(field, options)  
537 - end  
538 - return fi  
539 - end  
540 -  
541 - def self.close_multi_indexes  
542 - # close combined index readers, just in case  
543 - # this seems to fix a strange test failure that seems to relate to a  
544 - # multi_index looking at an old version of the content_base index.  
545 - multi_indexes.each_pair do |key, index|  
546 - # puts "#{key} -- #{self.name}"  
547 - # TODO only close those where necessary (watch inheritance, where  
548 - # self.name is base class of a class where key is made from)  
549 - index.close #if key =~ /#{self.name}/  
550 - end  
551 - multi_indexes.clear  
552 - end  
553 -  
554 - protected  
555 -  
556 - def self.field_config_for(fieldname, options = {})  
557 - config = DEFAULT_FIELD_OPTIONS.merge options  
558 - config[:via] ||= fieldname  
559 - config[:term_vector] = :no if config[:index] == :no  
560 - return config  
561 - end  
562 -  
563 -end  
564 -  
565 -# include acts_as_ferret method into ActiveRecord::Base  
566 -ActiveRecord::Base.extend ActsAsFerret::ActMethods  
567 -  
vendor/plugins/acts_as_ferret/lib/ar_mysql_auto_reconnect_patch.rb
@@ -1,41 +0,0 @@ @@ -1,41 +0,0 @@
1 -# Source: http://pastie.caboo.se/154842  
2 -#  
3 -# in /etc/my.cnf on the MySQL server, you can set the interactive-timeout parameter,  
4 -# for example, 12 hours = 28800 sec  
5 -# interactive-timeout=28800  
6 -  
7 -# in ActiveRecord, setting the verification_timeout to something less than  
8 -# the interactive-timeout parameter; 14400 sec = 6 hours  
9 -ActiveRecord::Base.verification_timeout = 14400  
10 -ActiveRecord::Base.establish_connection  
11 -  
12 -# Below is a monkey patch for keeping ActiveRecord connections alive.  
13 -# http://www.sparecycles.org/2007/7/2/saying-goodbye-to-lost-connections-in-rails  
14 -  
15 -module ActiveRecord  
16 - module ConnectionAdapters  
17 - class MysqlAdapter  
18 - def execute(sql, name = nil) #:nodoc:  
19 - reconnect_lost_connections = true  
20 - begin  
21 - log(sql, name) { @connection.query(sql) }  
22 - rescue ActiveRecord::StatementInvalid => exception  
23 - if reconnect_lost_connections and exception.message =~ /(Lost connection to MySQL server during query  
24 -|MySQL server has gone away)/  
25 - reconnect_lost_connections = false  
26 - reconnect!  
27 - retry  
28 - elsif exception.message.split(":").first =~ /Packets out of order/  
29 - raise ActiveRecord::StatementInvalid, "'Packets out of order' error was received from the database.  
30 - Please update your mysql bindings (gem install mysql) and read http://dev.mysql.com/doc/mysql/en/password-hash  
31 -ing.html for more information. If you're on Windows, use the Instant Rails installer to get the updated mysql  
32 -bindings."  
33 - else  
34 - raise  
35 - end  
36 - end  
37 - end  
38 - end  
39 - end  
40 -end  
41 -  
vendor/plugins/acts_as_ferret/lib/blank_slate.rb
@@ -1,53 +0,0 @@ @@ -1,53 +0,0 @@
1 -if defined?(BlankSlate)  
2 - # Rails 2.x has it already  
3 - module ActsAsFerret  
4 - class BlankSlate < ::BlankSlate  
5 - end  
6 - end  
7 -else  
8 - module ActsAsFerret  
9 - # 'backported' for Rails pre 2.0  
10 - #  
11 - #--  
12 - # Copyright 2004, 2006 by Jim Weirich (jim@weirichhouse.org).  
13 - # All rights reserved.  
14 -  
15 - # Permission is granted for use, copying, modification, distribution,  
16 - # and distribution of modified versions of this work as long as the  
17 - # above copyright notice is included.  
18 - #++  
19 -  
20 - ######################################################################  
21 - # BlankSlate provides an abstract base class with no predefined  
22 - # methods (except for <tt>\_\_send__</tt> and <tt>\_\_id__</tt>).  
23 - # BlankSlate is useful as a base class when writing classes that  
24 - # depend upon <tt>method_missing</tt> (e.g. dynamic proxies).  
25 - #  
26 - class BlankSlate  
27 - class << self  
28 - # Hide the method named +name+ in the BlankSlate class. Don't  
29 - # hide +instance_eval+ or any method beginning with "__".  
30 - def hide(name)  
31 - if instance_methods.include?(name.to_s) and name !~ /^(__|instance_eval|methods)/  
32 - @hidden_methods ||= {}  
33 - @hidden_methods[name.to_sym] = instance_method(name)  
34 - undef_method name  
35 - end  
36 - end  
37 -  
38 - # Redefine a previously hidden method so that it may be called on a blank  
39 - # slate object.  
40 - #  
41 - # no-op here since we don't hide the methods we reveal where this is  
42 - # used in this implementation  
43 - def reveal(name)  
44 - end  
45 - end  
46 -  
47 - instance_methods.each { |m| hide(m) }  
48 -  
49 - end  
50 - end  
51 -  
52 -end  
53 -  
vendor/plugins/acts_as_ferret/lib/bulk_indexer.rb
@@ -1,35 +0,0 @@ @@ -1,35 +0,0 @@
1 -module ActsAsFerret  
2 - class BulkIndexer  
3 - def initialize(args = {})  
4 - @batch_size = args[:batch_size] || 1000  
5 - @logger = args[:logger]  
6 - @model = args[:model]  
7 - @work_done = 0  
8 - @index = args[:index]  
9 - if args[:reindex]  
10 - @reindex = true  
11 - @model_count = @model.count.to_f  
12 - else  
13 - @model_count = args[:total]  
14 - end  
15 - end  
16 -  
17 - def index_records(records, offset)  
18 - batch_time = measure_time {  
19 - records.each { |rec| @index.add_document(rec.to_doc, rec.ferret_analyzer) if rec.ferret_enabled?(true) }  
20 - }.to_f  
21 - @work_done = offset.to_f / @model_count * 100.0 if @model_count > 0  
22 - remaining_time = ( batch_time / @batch_size ) * ( @model_count - offset + @batch_size )  
23 - @logger.info "#{@reindex ? 're' : 'bulk '}index model #{@model.name} : #{'%.2f' % @work_done}% complete : #{'%.2f' % remaining_time} secs to finish"  
24 -  
25 - end  
26 -  
27 - def measure_time  
28 - t1 = Time.now  
29 - yield  
30 - Time.now - t1  
31 - end  
32 -  
33 - end  
34 -  
35 -end  
vendor/plugins/acts_as_ferret/lib/class_methods.rb
@@ -1,295 +0,0 @@ @@ -1,295 +0,0 @@
1 -module ActsAsFerret  
2 -  
3 - module ClassMethods  
4 -  
5 - # Disables ferret index updates for this model. When a block is given,  
6 - # Ferret will be re-enabled again after executing the block.  
7 - def disable_ferret  
8 - aaf_configuration[:enabled] = false  
9 - if block_given?  
10 - yield  
11 - enable_ferret  
12 - end  
13 - end  
14 -  
15 - def enable_ferret  
16 - aaf_configuration[:enabled] = true  
17 - end  
18 -  
19 - def ferret_enabled?  
20 - aaf_configuration[:enabled]  
21 - end  
22 -  
23 - # rebuild the index from all data stored for this model, and any other  
24 - # model classes associated with the same index.  
25 - # This is called automatically when no index exists yet.  
26 - #  
27 - def rebuild_index  
28 - aaf_index.rebuild_index  
29 - end  
30 -  
31 - # re-index a number records specified by the given ids. Use for large  
32 - # indexing jobs i.e. after modifying a lot of records with Ferret disabled.  
33 - # Please note that the state of Ferret (enabled or disabled at class or  
34 - # record level) is not checked by this method, so if you need to do so  
35 - # (e.g. because of a custom ferret_enabled? implementation), you have to do  
36 - # so yourself.  
37 - def bulk_index(*ids)  
38 - options = Hash === ids.last ? ids.pop : {}  
39 - ids = ids.first if ids.size == 1 && ids.first.is_a?(Enumerable)  
40 - aaf_index.bulk_index(self.name, ids, options)  
41 - end  
42 -  
43 - # true if our db and table appear to be suitable for the mysql fast batch  
44 - # hack (see  
45 - # http://weblog.jamisbuck.org/2007/4/6/faking-cursors-in-activerecord)  
46 - def use_fast_batches?  
47 - if connection.class.name =~ /Mysql/ && primary_key == 'id' && aaf_configuration[:mysql_fast_batches]  
48 - logger.info "using mysql specific batched find :all. Turn off with :mysql_fast_batches => false if you encounter problems (i.e. because of non-integer UUIDs in the id column)"  
49 - true  
50 - end  
51 - end  
52 -  
53 - # Returns all records modified or created after the specified time.  
54 - # Used by the rake rebuild task to find models that need to be updated in  
55 - # the index after the rebuild finished because they changed while the  
56 - # rebuild was running.  
57 - # Override if your models don't stick to the created_at/updated_at  
58 - # convention.  
59 - def records_modified_since(time)  
60 - condition = []  
61 - %w(updated_at created_at).each do |col|  
62 - condition << "#{col} >= ?" if column_names.include? col  
63 - end  
64 - if condition.empty?  
65 - logger.warn "#{self.name}: Override records_modified_since(time) to keep the index up to date with records changed during rebuild."  
66 - []  
67 - else  
68 - find :all, :conditions => [ condition.join(' AND '), *([time]*condition.size) ]  
69 - end  
70 - end  
71 -  
72 - # runs across all records yielding those to be indexed when the index is rebuilt  
73 - def records_for_rebuild(batch_size = 1000)  
74 - transaction do  
75 - if use_fast_batches?  
76 - offset = 0  
77 - while (rows = find :all, :conditions => [ "#{table_name}.id > ?", offset ], :limit => batch_size).any?  
78 - offset = rows.last.id  
79 - yield rows, offset  
80 - end  
81 - else  
82 - order = "#{primary_key} ASC" # fixes #212  
83 - 0.step(self.count, batch_size) do |offset|  
84 - yield find( :all, :limit => batch_size, :offset => offset, :order => order ), offset  
85 - end  
86 - end  
87 - end  
88 - end  
89 -  
90 - # yields the records with the given ids, in batches of batch_size  
91 - def records_for_bulk_index(ids, batch_size = 1000)  
92 - transaction do  
93 - offset = 0  
94 - ids.each_slice(batch_size) do |id_slice|  
95 - records = find( :all, :conditions => ["id in (?)", id_slice] )  
96 - #yield records, offset  
97 - yield find( :all, :conditions => ["id in (?)", id_slice] ), offset  
98 - offset += batch_size  
99 - end  
100 - end  
101 - end  
102 -  
103 - # Retrieve the index instance for this model class. This can either be a  
104 - # LocalIndex, or a RemoteIndex instance.  
105 - #  
106 - def aaf_index  
107 - @index ||= ActsAsFerret::get_index(aaf_configuration[:name])  
108 - end  
109 -  
110 - # Finds instances by searching the Ferret index. Terms are ANDed by default, use  
111 - # OR between terms for ORed queries. Or specify +:or_default => true+ in the  
112 - # +:ferret+ options hash of acts_as_ferret.  
113 - #  
114 - # You may either use the +offset+ and +limit+ options to implement your own  
115 - # pagination logic, or use the +page+ and +per_page+ options to use the  
116 - # built in pagination support which is compatible with will_paginate's view  
117 - # helpers. If +page+ and +per_page+ are given, +offset+ and +limit+ will be  
118 - # ignored.  
119 - #  
120 - # == options:  
121 - # page:: page of search results to retrieve  
122 - # per_page:: number of search results that are displayed per page  
123 - # offset:: first hit to retrieve (useful for paging)  
124 - # limit:: number of hits to retrieve, or :all to retrieve  
125 - # all results  
126 - # lazy:: Array of field names whose contents should be read directly  
127 - # from the index. Those fields have to be marked  
128 - # +:store => :yes+ in their field options. Give true to get all  
129 - # stored fields. Note that if you have a shared index, you have  
130 - # to explicitly state the fields you want to fetch, true won't  
131 - # work here)  
132 - #  
133 - # +find_options+ is a hash passed on to active_record's find when  
134 - # retrieving the data from db, useful to i.e. prefetch relationships with  
135 - # :include or to specify additional filter criteria with :conditions.  
136 - #  
137 - # This method returns a +SearchResults+ instance, which really is an Array that has  
138 - # been decorated with a total_hits attribute holding the total number of hits.  
139 - # Additionally, SearchResults is compatible with the pagination helper  
140 - # methods of the will_paginate plugin.  
141 - #  
142 - # Please keep in mind that the number of results delivered might be less than  
143 - # +limit+ if you specify any active record conditions that further limit  
144 - # the result. Use +limit+ and +offset+ as AR find_options instead.  
145 - # +page+ and +per_page+ are supposed to work regardless of any  
146 - # +conitions+ present in +find_options+.  
147 - def find_with_ferret(q, options = {}, find_options = {})  
148 - aaf_index.register_class(self, {})  
149 -  
150 - if respond_to?(:scope) && scope(:find, :conditions)  
151 - if find_options[:conditions]  
152 - find_options[:conditions] = "(#{find_options[:conditions]}) AND (#{scope(:find, :conditions)})"  
153 - else  
154 - find_options[:conditions] = scope(:find, :conditions)  
155 - end  
156 - end  
157 -  
158 - if options[:per_page]  
159 - options[:page] = options[:page] ? options[:page].to_i : 1  
160 - limit = options[:per_page]  
161 - offset = (options[:page] - 1) * limit  
162 - if find_options[:conditions]  
163 - find_options[:limit] = limit  
164 - find_options[:offset] = offset  
165 - options[:limit] = :all  
166 - options.delete :offset  
167 - else  
168 - # do pagination with ferret  
169 - options[:limit] = limit  
170 - options[:offset] = offset  
171 - end  
172 - elsif find_options[:conditions]  
173 - find_options[:limit] ||= options.delete(:limit) unless options[:limit] == :all  
174 - find_options[:offset] ||= options.delete(:offset)  
175 - options[:limit] = :all  
176 - end  
177 -  
178 - total_hits, result = aaf_index.find_records q, options.merge(:models => [self]), find_options  
179 - logger.debug "Query: #{q}\ntotal hits: #{total_hits}, results delivered: #{result.size}"  
180 - SearchResults.new(result, total_hits, options[:page], options[:per_page])  
181 - end  
182 -  
183 -  
184 - # Returns the total number of hits for the given query  
185 - #  
186 - # Note that since we don't query the database here, this method won't deliver  
187 - # the expected results when used on an AR association.  
188 - #  
189 - def total_hits(q, options={})  
190 - aaf_index.total_hits(q, options)  
191 - end  
192 -  
193 - # Finds instance model name, ids and scores by contents.  
194 - # Useful e.g. if you want to search across models or do not want to fetch  
195 - # all result records (yet).  
196 - #  
197 - # Options are the same as for find_by_contents  
198 - #  
199 - # A block can be given too, it will be executed with every result:  
200 - # find_ids_with_ferret(q, options) do |model, id, score|  
201 - # id_array << id  
202 - # scores_by_id[id] = score  
203 - # end  
204 - # NOTE: in case a block is given, only the total_hits value will be returned  
205 - # instead of the [total_hits, results] array!  
206 - #  
207 - def find_ids_with_ferret(q, options = {}, &block)  
208 - aaf_index.find_ids(q, options, &block)  
209 - end  
210 -  
211 -  
212 - protected  
213 -  
214 -# def find_records_lazy_or_not(q, options = {}, find_options = {})  
215 -# if options[:lazy]  
216 -# logger.warn "find_options #{find_options} are ignored because :lazy => true" unless find_options.empty?  
217 -# lazy_find_by_contents q, options  
218 -# else  
219 -# ar_find_by_contents q, options, find_options  
220 -# end  
221 -# end  
222 -#  
223 -# def ar_find_by_contents(q, options = {}, find_options = {})  
224 -# result_ids = {}  
225 -# total_hits = find_ids_with_ferret(q, options) do |model, id, score, data|  
226 -# # stores ids, index and score of each hit for later ordering of  
227 -# # results  
228 -# result_ids[id] = [ result_ids.size + 1, score ]  
229 -# end  
230 -#  
231 -# result = ActsAsFerret::retrieve_records( { self.name => result_ids }, find_options )  
232 -#  
233 -# # count total_hits via sql when using conditions or when we're called  
234 -# # from an ActiveRecord association.  
235 -# if find_options[:conditions] or caller.find{ |call| call =~ %r{active_record/associations} }  
236 -# # chances are the ferret result count is not our total_hits value, so  
237 -# # we correct this here.  
238 -# if options[:limit] != :all || options[:page] || options[:offset] || find_options[:limit] || find_options[:offset]  
239 -# # our ferret result has been limited, so we need to re-run that  
240 -# # search to get the full result set from ferret.  
241 -# result_ids = {}  
242 -# find_ids_with_ferret(q, options.update(:limit => :all, :offset => 0)) do |model, id, score, data|  
243 -# result_ids[id] = [ result_ids.size + 1, score ]  
244 -# end  
245 -# # Now ask the database for the total size of the final result set.  
246 -# total_hits = count_records( { self.name => result_ids }, find_options )  
247 -# else  
248 -# # what we got from the database is our full result set, so take  
249 -# # it's size  
250 -# total_hits = result.length  
251 -# end  
252 -# end  
253 -#  
254 -# [ total_hits, result ]  
255 -# end  
256 -#  
257 -# def lazy_find_by_contents(q, options = {})  
258 -# logger.debug "lazy_find_by_contents: #{q}"  
259 -# result = []  
260 -# rank = 0  
261 -# total_hits = find_ids_with_ferret(q, options) do |model, id, score, data|  
262 -# logger.debug "model: #{model}, id: #{id}, data: #{data}"  
263 -# result << FerretResult.new(model, id, score, rank += 1, data)  
264 -# end  
265 -# [ total_hits, result ]  
266 -# end  
267 -  
268 -  
269 - def model_find(model, id, find_options = {})  
270 - model.constantize.find(id, find_options)  
271 - end  
272 -  
273 -  
274 -# def count_records(id_arrays, find_options = {})  
275 -# count_options = find_options.dup  
276 -# count_options.delete :limit  
277 -# count_options.delete :offset  
278 -# count = 0  
279 -# id_arrays.each do |model, id_array|  
280 -# next if id_array.empty?  
281 -# model = model.constantize  
282 -# # merge conditions  
283 -# conditions = ActsAsFerret::combine_conditions([ "#{model.table_name}.#{model.primary_key} in (?)", id_array.keys ],  
284 -# find_options[:conditions])  
285 -# opts = find_options.merge :conditions => conditions  
286 -# opts.delete :limit; opts.delete :offset  
287 -# count += model.count opts  
288 -# end  
289 -# count  
290 -# end  
291 -  
292 - end  
293 -  
294 -end  
295 -  
vendor/plugins/acts_as_ferret/lib/ferret_extensions.rb
@@ -1,115 +0,0 @@ @@ -1,115 +0,0 @@
1 -module Ferret  
2 -  
3 - module Analysis  
4 -  
5 - # = PerFieldAnalyzer  
6 - #  
7 - # This PerFieldAnalyzer is a workaround to a memory leak in  
8 - # ferret 0.11.4. It does basically do the same as the original  
9 - # Ferret::Analysis::PerFieldAnalyzer, but without the leak :)  
10 - #  
11 - # http://ferret.davebalmain.com/api/classes/Ferret/Analysis/PerFieldAnalyzer.html  
12 - #  
13 - # Thanks to Ben from omdb.org for tracking this down and creating this  
14 - # workaround.  
15 - # You can read more about the issue there:  
16 - # http://blog.omdb-beta.org/2007/7/29/tracking-down-a-memory-leak-in-ferret-0-11-4  
17 - class PerFieldAnalyzer < ::Ferret::Analysis::Analyzer  
18 - def initialize( default_analyzer = StandardAnalyzer.new )  
19 - @analyzers = {}  
20 - @default_analyzer = default_analyzer  
21 - end  
22 -  
23 - def add_field( field, analyzer )  
24 - @analyzers[field] = analyzer  
25 - end  
26 - alias []= add_field  
27 -  
28 - def token_stream(field, string)  
29 - @analyzers.has_key?(field) ? @analyzers[field].token_stream(field, string) :  
30 - @default_analyzer.token_stream(field, string)  
31 - end  
32 - end  
33 - end  
34 -  
35 - class Index::Index  
36 - attr_accessor :batch_size, :logger  
37 -  
38 - def index_models(models)  
39 - models.each { |model| index_model model }  
40 - flush  
41 - optimize  
42 - close  
43 - ActsAsFerret::close_multi_indexes  
44 - end  
45 -  
46 - def index_model(model)  
47 - bulk_indexer = ActsAsFerret::BulkIndexer.new(:batch_size => @batch_size, :logger => logger,  
48 - :model => model, :index => self, :reindex => true)  
49 - logger.info "reindexing model #{model.name}"  
50 -  
51 - model.records_for_rebuild(@batch_size) do |records, offset|  
52 - bulk_indexer.index_records(records, offset)  
53 - end  
54 - end  
55 -  
56 - def bulk_index(model, ids, options = {})  
57 - options.reverse_merge! :optimize => true  
58 - orig_flush = @auto_flush  
59 - @auto_flush = false  
60 - bulk_indexer = ActsAsFerret::BulkIndexer.new(:batch_size => @batch_size, :logger => logger,  
61 - :model => model, :index => self, :total => ids.size)  
62 - model.records_for_bulk_index(ids, @batch_size) do |records, offset|  
63 - logger.debug "#{model} bulk indexing #{records.size} at #{offset}"  
64 - bulk_indexer.index_records(records, offset)  
65 - end  
66 - logger.info 'finishing bulk index...'  
67 - flush  
68 - if options[:optimize]  
69 - logger.info 'optimizing...'  
70 - optimize  
71 - end  
72 - @auto_flush = orig_flush  
73 - end  
74 -  
75 - end  
76 -  
77 - # add marshalling support to SortFields  
78 - class Search::SortField  
79 - def _dump(depth)  
80 - to_s  
81 - end  
82 -  
83 - def self._load(string)  
84 - case string  
85 - when /<DOC(_ID)?>!/ : Ferret::Search::SortField::DOC_ID_REV  
86 - when /<DOC(_ID)?>/ : Ferret::Search::SortField::DOC_ID  
87 - when '<SCORE>!' : Ferret::Search::SortField::SCORE_REV  
88 - when '<SCORE>' : Ferret::Search::SortField::SCORE  
89 - when /^(\w+):<(\w+)>(!)?$/ : new($1.to_sym, :type => $2.to_sym, :reverse => !$3.nil?)  
90 - else raise "invalid value: #{string}"  
91 - end  
92 - end  
93 - end  
94 -  
95 - # add marshalling support to Sort  
96 - class Search::Sort  
97 - def _dump(depth)  
98 - to_s  
99 - end  
100 -  
101 - def self._load(string)  
102 - # we exclude the last <DOC> sorting as it is appended by new anyway  
103 - if string =~ /^Sort\[(.*?)(<DOC>(!)?)?\]$/  
104 - sort_fields = $1.split(',').map do |value|  
105 - value.strip!  
106 - Ferret::Search::SortField._load value unless value.blank?  
107 - end  
108 - new sort_fields.compact  
109 - else  
110 - raise "invalid value: #{string}"  
111 - end  
112 - end  
113 - end  
114 -  
115 -end  
vendor/plugins/acts_as_ferret/lib/ferret_find_methods.rb
@@ -1,118 +0,0 @@ @@ -1,118 +0,0 @@
1 -module ActsAsFerret  
2 - # Ferret search logic common to single-class indexes, shared indexes and  
3 - # multi indexes.  
4 - module FerretFindMethods  
5 -  
6 - def find_records(q, options = {}, ar_options = {})  
7 - if options[:lazy]  
8 - logger.warn "find_options #{ar_options} are ignored because :lazy => true" unless ar_options.empty?  
9 - lazy_find q, options  
10 - else  
11 - ar_find q, options, ar_options  
12 - end  
13 - end  
14 -  
15 - def lazy_find(q, options = {})  
16 - logger.debug "lazy_find: #{q}"  
17 - result = []  
18 - rank = 0  
19 - total_hits = find_ids(q, options) do |model, id, score, data|  
20 - logger.debug "model: #{model}, id: #{id}, data: #{data}"  
21 - result << FerretResult.new(model, id, score, rank += 1, data)  
22 - end  
23 - [ total_hits, result ]  
24 - end  
25 -  
26 - def ar_find(q, options = {}, ar_options = {})  
27 - total_hits, id_arrays = find_id_model_arrays q, options  
28 - result = ActsAsFerret::retrieve_records(id_arrays, ar_options)  
29 -  
30 - # count total_hits via sql when using conditions, multiple models, or when we're called  
31 - # from an ActiveRecord association.  
32 - if id_arrays.size > 1 or ar_options[:conditions]  
33 - # chances are the ferret result count is not our total_hits value, so  
34 - # we correct this here.  
35 - if options[:limit] != :all || options[:page] || options[:offset] || ar_options[:limit] || ar_options[:offset]  
36 - # our ferret result has been limited, so we need to re-run that  
37 - # search to get the full result set from ferret.  
38 - new_th, id_arrays = find_id_model_arrays( q, options.merge(:limit => :all, :offset => 0) )  
39 - # Now ask the database for the total size of the final result set.  
40 - total_hits = count_records( id_arrays, ar_options )  
41 - else  
42 - # what we got from the database is our full result set, so take  
43 - # it's size  
44 - total_hits = result.length  
45 - end  
46 - end  
47 - [ total_hits, result ]  
48 - end  
49 -  
50 - def count_records(id_arrays, ar_options = {})  
51 - count_options = ar_options.dup  
52 - count_options.delete :limit  
53 - count_options.delete :offset  
54 - count = 0  
55 - id_arrays.each do |model, id_array|  
56 - next if id_array.empty?  
57 - model = model.constantize  
58 - # merge conditions  
59 - conditions = ActsAsFerret::conditions_for_model model, ar_options[:conditions]  
60 - count_options[:conditions] = ActsAsFerret::combine_conditions([ "#{model.table_name}.#{model.primary_key} in (?)", id_array.keys ], conditions)  
61 - count += model.count count_options  
62 - end  
63 - count  
64 - end  
65 -  
66 - def find_id_model_arrays(q, options)  
67 - id_arrays = {}  
68 - rank = 0  
69 - total_hits = find_ids(q, options) do |model, id, score, data|  
70 - id_arrays[model] ||= {}  
71 - id_arrays[model][id] = [ rank += 1, score ]  
72 - end  
73 - [total_hits, id_arrays]  
74 - end  
75 -  
76 - # Queries the Ferret index to retrieve model class, id, score and the  
77 - # values of any fields stored in the index for each hit.  
78 - # If a block is given, these are yielded and the number of total hits is  
79 - # returned. Otherwise [total_hits, result_array] is returned.  
80 - def find_ids(query, options = {})  
81 -  
82 - result = []  
83 - stored_fields = determine_stored_fields options  
84 -  
85 - q = process_query(query, options)  
86 - q = scope_query_to_models q, options[:models] #if shared?  
87 - logger.debug "query: #{query}\n-->#{q}"  
88 - s = searcher  
89 - total_hits = s.search_each(q, options) do |hit, score|  
90 - doc = s[hit]  
91 - model = doc[:class_name]  
92 - # fetch stored fields if lazy loading  
93 - data = extract_stored_fields(doc, stored_fields)  
94 - if block_given?  
95 - yield model, doc[:id], score, data  
96 - else  
97 - result << { :model => model, :id => doc[:id], :score => score, :data => data }  
98 - end  
99 - end  
100 - #logger.debug "id_score_model array: #{result.inspect}"  
101 - return block_given? ? total_hits : [total_hits, result]  
102 - end  
103 -  
104 - def scope_query_to_models(query, models)  
105 - return query if models.nil? or models == :all  
106 - models = [ models ] if Class === models  
107 - q = Ferret::Search::BooleanQuery.new  
108 - q.add_query(query, :must)  
109 - model_query = Ferret::Search::BooleanQuery.new  
110 - models.each do |model|  
111 - model_query.add_query(Ferret::Search::TermQuery.new(:class_name, model.name), :should)  
112 - end  
113 - q.add_query(model_query, :must)  
114 - return q  
115 - end  
116 -  
117 - end  
118 -end  
vendor/plugins/acts_as_ferret/lib/ferret_result.rb
@@ -1,53 +0,0 @@ @@ -1,53 +0,0 @@
1 -module ActsAsFerret  
2 -  
3 - # mixed into the FerretResult and AR classes calling acts_as_ferret  
4 - module ResultAttributes  
5 - # holds the score this record had when it was found via  
6 - # acts_as_ferret  
7 - attr_accessor :ferret_score  
8 -  
9 - attr_accessor :ferret_rank  
10 - end  
11 -  
12 - class FerretResult < ActsAsFerret::BlankSlate  
13 - include ResultAttributes  
14 - attr_accessor :id  
15 - reveal :methods  
16 -  
17 - def initialize(model, id, score, rank, data = {})  
18 - @model = model.constantize  
19 - @id = id  
20 - @ferret_score = score  
21 - @ferret_rank = rank  
22 - @data = data  
23 - @use_record = false  
24 - end  
25 -  
26 - def inspect  
27 - "#<FerretResult wrapper for #{@model} with id #{@id}"  
28 - end  
29 -  
30 - def method_missing(method, *args, &block)  
31 - if (@ar_record && @use_record) || !@data.has_key?(method)  
32 - to_record.send method, *args, &block  
33 - else  
34 - @data[method]  
35 - end  
36 - end  
37 -  
38 - def respond_to?(name)  
39 - methods.include?(name.to_s) || @data.has_key?(name.to_sym) || to_record.respond_to?(name)  
40 - end  
41 -  
42 - def to_record  
43 - unless @ar_record  
44 - @ar_record = @model.find(id)  
45 - @ar_record.ferret_rank = ferret_rank  
46 - @ar_record.ferret_score = ferret_score  
47 - # don't try to fetch attributes from RDig based records  
48 - @use_record = !@ar_record.class.included_modules.include?(ActsAsFerret::RdigAdapter)  
49 - end  
50 - @ar_record  
51 - end  
52 - end  
53 -end  
vendor/plugins/acts_as_ferret/lib/ferret_server.rb
@@ -1,238 +0,0 @@ @@ -1,238 +0,0 @@
1 -require 'drb'  
2 -require 'thread'  
3 -require 'yaml'  
4 -require 'erb'  
5 -  
6 -################################################################################  
7 -module ActsAsFerret  
8 - module Remote  
9 -  
10 - ################################################################################  
11 - class Config  
12 -  
13 - ################################################################################  
14 - DEFAULTS = {  
15 - 'host' => 'localhost',  
16 - 'port' => '9009',  
17 - 'cf' => "#{RAILS_ROOT}/config/ferret_server.yml",  
18 - 'pid_file' => "#{RAILS_ROOT}/log/ferret_server.pid",  
19 - 'log_file' => "#{RAILS_ROOT}/log/ferret_server.log",  
20 - 'log_level' => 'debug',  
21 - 'socket' => nil,  
22 - 'script' => nil  
23 - }  
24 -  
25 - ################################################################################  
26 - # load the configuration file and apply default settings  
27 - def initialize (file=DEFAULTS['cf'])  
28 - @everything = YAML.load(ERB.new(IO.read(file)).result)  
29 - raise "malformed ferret server config" unless @everything.is_a?(Hash)  
30 - @config = DEFAULTS.merge(@everything[RAILS_ENV] || {})  
31 - if @everything[RAILS_ENV]  
32 - @config['uri'] = socket.nil? ? "druby://#{host}:#{port}" : "drbunix:#{socket}"  
33 - end  
34 - end  
35 -  
36 - ################################################################################  
37 - # treat the keys of the config data as methods  
38 - def method_missing (name, *args)  
39 - @config.has_key?(name.to_s) ? @config[name.to_s] : super  
40 - end  
41 -  
42 - end  
43 -  
44 - #################################################################################  
45 - # This class acts as a drb server listening for indexing and  
46 - # search requests from models declared to 'acts_as_ferret :remote => true'  
47 - #  
48 - # Usage:  
49 - # - modify RAILS_ROOT/config/ferret_server.yml to suit your needs.  
50 - # - environments for which no section in the config file exists will use  
51 - # the index locally (good for unit tests/development mode)  
52 - # - run script/ferret_server to start the server:  
53 - # script/ferret_server -e production start  
54 - # - to stop the server run  
55 - # script/ferret_server -e production stop  
56 - #  
57 - class Server  
58 -  
59 - #################################################################################  
60 - # FIXME include detection of OS and include the correct file  
61 - require 'unix_daemon'  
62 - include(ActsAsFerret::Remote::UnixDaemon)  
63 -  
64 -  
65 - ################################################################################  
66 - cattr_accessor :running  
67 -  
68 - ################################################################################  
69 - def initialize  
70 - ActiveRecord::Base.allow_concurrency = true  
71 - require 'ar_mysql_auto_reconnect_patch'  
72 - @cfg = ActsAsFerret::Remote::Config.new  
73 - ActiveRecord::Base.logger = @logger = Logger.new(@cfg.log_file)  
74 - ActiveRecord::Base.logger.level = Logger.const_get(@cfg.log_level.upcase) rescue Logger::DEBUG  
75 - if @cfg.script  
76 - path = File.join(RAILS_ROOT, @cfg.script)  
77 - load path  
78 - @logger.info "loaded custom startup script from #{path}"  
79 - end  
80 - end  
81 -  
82 - ################################################################################  
83 - # start the server as a daemon process  
84 - def start  
85 - raise "ferret_server not configured for #{RAILS_ENV}" unless (@cfg.uri rescue nil)  
86 - platform_daemon { run_drb_service }  
87 - end  
88 -  
89 - ################################################################################  
90 - # run the server and block until it exits  
91 - def run  
92 - raise "ferret_server not configured for #{RAILS_ENV}" unless (@cfg.uri rescue nil)  
93 - run_drb_service  
94 - end  
95 -  
96 - def run_drb_service  
97 - $stdout.puts("starting ferret server...")  
98 - self.class.running = true  
99 - DRb.start_service(@cfg.uri, self)  
100 - DRb.thread.join  
101 - rescue Exception => e  
102 - @logger.error(e.to_s)  
103 - raise  
104 - end  
105 -  
106 - #################################################################################  
107 - # handles all incoming method calls, and sends them on to the correct local index  
108 - # instance.  
109 - #  
110 - # Calls are not queued, so this will block until the call returned.  
111 - #  
112 - def method_missing(name, *args)  
113 - @logger.debug "\#method_missing(#{name.inspect}, #{args.inspect})"  
114 -  
115 -  
116 - index_name = args.shift  
117 - index = if name.to_s =~ /^multi_(.+)/  
118 - name = $1  
119 - ActsAsFerret::multi_index(index_name)  
120 - else  
121 - ActsAsFerret::get_index(index_name)  
122 - end  
123 -  
124 - if index.nil?  
125 - @logger.error "\#index with name #{index_name} not found in call to #{name} with args #{args.inspect}"  
126 - raise ActsAsFerret::IndexNotDefined.new(index_name)  
127 - end  
128 -  
129 -  
130 - # TODO find another way to implement the reconnection logic (maybe in  
131 - # local_index or class_methods)  
132 - # reconnect_when_needed(clazz) do  
133 -  
134 - # using respond_to? here so we not have to catch NoMethodError  
135 - # which would silently catch those from deep inside the indexing  
136 - # code, too...  
137 -  
138 - if index.respond_to?(name)  
139 - index.send name, *args  
140 - # TODO check where we need this:  
141 - #elsif clazz.respond_to?(name)  
142 - # @logger.debug "no luck, trying to call class method instead"  
143 - # clazz.send name, *args  
144 - else  
145 - raise NoMethodError.new("method #{name} not supported by DRb server")  
146 - end  
147 - rescue => e  
148 - @logger.error "ferret server error #{$!}\n#{$!.backtrace.join "\n"}"  
149 - raise e  
150 - end  
151 -  
152 - def register_class(class_name)  
153 - @logger.debug "############ registerclass #{class_name}"  
154 - class_name.constantize  
155 - @logger.debug "index for class #{class_name}: #{ActsAsFerret::ferret_indexes[class_name.underscore.to_sym]}"  
156 -  
157 - end  
158 -  
159 - # make sure we have a versioned index in place, building one if necessary  
160 - def ensure_index_exists(index_name)  
161 - @logger.debug "DRb server: ensure_index_exists for index #{index_name}"  
162 - definition = ActsAsFerret::get_index(index_name).index_definition  
163 - dir = definition[:index_dir]  
164 - unless File.directory?(dir) && File.file?(File.join(dir, 'segments')) && dir =~ %r{/\d+(_\d+)?$}  
165 - rebuild_index(index_name)  
166 - end  
167 - end  
168 -  
169 - # disconnects the db connection for the class specified by class_name  
170 - # used only in unit tests to check the automatic reconnection feature  
171 - def db_disconnect!(class_name)  
172 - with_class class_name do |clazz|  
173 - clazz.connection.disconnect!  
174 - end  
175 - end  
176 -  
177 - # hides LocalIndex#rebuild_index to implement index versioning  
178 - def rebuild_index(index_name)  
179 - definition = ActsAsFerret::get_index(index_name).index_definition.dup  
180 - models = definition[:registered_models]  
181 - index = new_index_for(definition)  
182 - # TODO fix reconnection stuff  
183 - # reconnect_when_needed(clazz) do  
184 - # @logger.debug "DRb server: rebuild index for class(es) #{models.inspect} in #{index.options[:path]}"  
185 - index.index_models models  
186 - # end  
187 - new_version = File.join definition[:index_base_dir], Time.now.utc.strftime('%Y%m%d%H%M%S')  
188 - # create a unique directory name (needed for unit tests where  
189 - # multiple rebuilds per second may occur)  
190 - if File.exists?(new_version)  
191 - i = 0  
192 - i+=1 while File.exists?("#{new_version}_#{i}")  
193 - new_version << "_#{i}"  
194 - end  
195 -  
196 - File.rename index.options[:path], new_version  
197 - ActsAsFerret::change_index_dir index_name, new_version  
198 - end  
199 -  
200 -  
201 - protected  
202 -  
203 - def reconnect_when_needed(clazz)  
204 - retried = false  
205 - begin  
206 - yield  
207 - rescue ActiveRecord::StatementInvalid => e  
208 - if e.message =~ /MySQL server has gone away/  
209 - if retried  
210 - raise e  
211 - else  
212 - @logger.info "StatementInvalid caught, trying to reconnect..."  
213 - clazz.connection.reconnect!  
214 - retried = true  
215 - retry  
216 - end  
217 - else  
218 - @logger.error "StatementInvalid caught, but unsure what to do with it: #{e}"  
219 - raise e  
220 - end  
221 - end  
222 - end  
223 -  
224 - def new_index_for(index_definition)  
225 - ferret_cfg = index_definition[:ferret].dup  
226 - ferret_cfg.update :auto_flush => false,  
227 - :create => true,  
228 - :field_infos => ActsAsFerret::field_infos(index_definition),  
229 - :path => File.join(index_definition[:index_base_dir], 'rebuild')  
230 - returning Ferret::Index::Index.new(ferret_cfg) do |i|  
231 - i.batch_size = index_definition[:reindex_batch_size]  
232 - i.logger = @logger  
233 - end  
234 - end  
235 -  
236 - end  
237 - end  
238 -end  
vendor/plugins/acts_as_ferret/lib/index.rb
@@ -1,99 +0,0 @@ @@ -1,99 +0,0 @@
1 -module ActsAsFerret  
2 -  
3 - class IndexLogger  
4 - def initialize(logger, name)  
5 - @logger = logger  
6 - @index_name = name  
7 - end  
8 - %w(debug info warn error).each do |m|  
9 - define_method(m) do |message|  
10 - @logger.send m, "[#{@index_name}] #{message}"  
11 - end  
12 - question = :"#{m}?"  
13 - define_method(question) do  
14 - @logger.send question  
15 - end  
16 - end  
17 - end  
18 -  
19 - # base class for local and remote indexes  
20 - class AbstractIndex  
21 - include FerretFindMethods  
22 -  
23 - attr_reader :logger, :index_name, :index_definition, :registered_models_config  
24 - def initialize(index_definition)  
25 - @index_definition = index_definition  
26 - @registered_models_config = {}  
27 - @index_name = index_definition[:name]  
28 - @logger = IndexLogger.new(ActsAsFerret::logger, @index_name)  
29 - end  
30 -  
31 - # TODO allow for per-class field configuration (i.e. different via, boosts  
32 - # for the same field among different models)  
33 - def register_class(clazz, options = {})  
34 - logger.info "register class #{clazz} with index #{index_name}"  
35 -  
36 - if force = options.delete(:force_re_registration)  
37 - index_definition[:registered_models].delete(clazz)  
38 - end  
39 -  
40 - if index_definition[:registered_models].map(&:name).include?(clazz.name)  
41 - logger.info("refusing re-registration of class #{clazz}")  
42 - else  
43 - index_definition[:registered_models] << clazz  
44 - @registered_models_config[clazz] = options  
45 -  
46 - # merge fields from this acts_as_ferret call with predefined fields  
47 - already_defined_fields = index_definition[:ferret_fields]  
48 - field_config = ActsAsFerret::build_field_config options[:fields]  
49 - field_config.update ActsAsFerret::build_field_config( options[:additional_fields] )  
50 - field_config.each do |field, config|  
51 - if already_defined_fields.has_key?(field)  
52 - logger.info "ignoring redefinition of ferret field #{field}" if shared?  
53 - else  
54 - already_defined_fields[field] = config  
55 - logger.info "adding new field #{field} from class #{clazz.name} to index #{index_name}"  
56 - end  
57 - end  
58 -  
59 - # update default field list to be used by the query parser, unless it  
60 - # was explicitly given by user.  
61 - #  
62 - # It will include all content fields *not* marked as :untokenized.  
63 - # This fixes the otherwise failing CommentTest#test_stopwords. Basically  
64 - # this means that by default only tokenized fields (which all fields are  
65 - # by default) will be searched. If you want to search inside the contents  
66 - # of an untokenized field, you'll have to explicitly specify it in your  
67 - # query.  
68 - unless index_definition[:user_default_field]  
69 - # grab all tokenized fields  
70 - ferret_fields = index_definition[:ferret_fields]  
71 - index_definition[:ferret][:default_field] = ferret_fields.keys.select do |field|  
72 - ferret_fields[field][:index] != :untokenized  
73 - end  
74 - logger.info "default field list for index #{index_name}: #{index_definition[:ferret][:default_field].inspect}"  
75 - end  
76 - end  
77 -  
78 - return index_definition  
79 - end  
80 -  
81 - # true if this index is used by more than one model class  
82 - def shared?  
83 - index_definition[:registered_models].size > 1  
84 - end  
85 -  
86 - # Switches the index to a new index directory.  
87 - # Used by the DRb server when switching to a new index version.  
88 - def change_index_dir(new_dir)  
89 - logger.debug "[#{index_name}] changing index dir to #{new_dir}"  
90 - index_definition[:index_dir] = index_definition[:ferret][:path] = new_dir  
91 - reopen!  
92 - logger.debug "[#{index_name}] index dir is now #{new_dir}"  
93 - end  
94 -  
95 - protected  
96 -  
97 - end  
98 -  
99 -end  
vendor/plugins/acts_as_ferret/lib/instance_methods.rb
@@ -1,165 +0,0 @@ @@ -1,165 +0,0 @@
1 -module ActsAsFerret #:nodoc:  
2 -  
3 - module InstanceMethods  
4 - include ResultAttributes  
5 -  
6 - # Returns an array of strings with the matches highlighted. The +query+ can  
7 - # either be a String or a Ferret::Search::Query object.  
8 - #  
9 - # === Options  
10 - #  
11 - # field:: field to take the content from. This field has  
12 - # to have it's content stored in the index  
13 - # (:store => :yes in your call to aaf). If not  
14 - # given, all stored fields are searched, and the  
15 - # highlighted content found in all of them is returned.  
16 - # set :highlight => :no in the field options to  
17 - # avoid highlighting of contents from a :stored field.  
18 - # excerpt_length:: Default: 150. Length of excerpt to show. Highlighted  
19 - # terms will be in the centre of the excerpt.  
20 - # num_excerpts:: Default: 2. Number of excerpts to return.  
21 - # pre_tag:: Default: "<em>". Tag to place to the left of the  
22 - # match.  
23 - # post_tag:: Default: "</em>". This tag should close the  
24 - # +:pre_tag+.  
25 - # ellipsis:: Default: "...". This is the string that is appended  
26 - # at the beginning and end of excerpts (unless the  
27 - # excerpt hits the start or end of the field. You'll  
28 - # probably want to change this to a Unicode elipsis  
29 - # character.  
30 - def highlight(query, options = {})  
31 - self.class.aaf_index.highlight(self.send(self.class.primary_key), self.class.name, query, options)  
32 - end  
33 -  
34 - # re-eneable ferret indexing for this instance after a call to #disable_ferret  
35 - def enable_ferret  
36 - @ferret_disabled = nil  
37 - end  
38 - alias ferret_enable enable_ferret # compatibility  
39 -  
40 - # returns true if ferret indexing is enabled for this record.  
41 - #  
42 - # The optional is_bulk_index parameter will be true if the method is called  
43 - # by rebuild_index or bulk_index, and false otherwise.  
44 - #  
45 - # If is_bulk_index is true, the class level ferret_enabled state will be  
46 - # ignored by this method (per-instance ferret_enabled checks however will  
47 - # take place, so if you override this method to forbid indexing of certain  
48 - # records you're still safe).  
49 - def ferret_enabled?(is_bulk_index = false)  
50 - @ferret_disabled.nil? && (is_bulk_index || self.class.ferret_enabled?) && (aaf_configuration[:if].nil? || aaf_configuration[:if].call(self))  
51 - end  
52 -  
53 - # Returns the analyzer to use when adding this record to the index.  
54 - #  
55 - # Override to return a specific analyzer for any record that is to be  
56 - # indexed, i.e. specify a different analyzer based on language. Returns nil  
57 - # by default so the global analyzer (specified with the acts_as_ferret  
58 - # call) is used.  
59 - def ferret_analyzer  
60 - nil  
61 - end  
62 -  
63 - # Disable Ferret for this record for a specified amount of time. ::once will  
64 - # disable Ferret for the next call to #save (this is the default), ::always  
65 - # will do so for all subsequent calls.  
66 - #  
67 - # Note that this will turn off only the create and update hooks, but not the  
68 - # destroy hook. I think that's reasonable, if you think the opposite, please  
69 - # tell me.  
70 - #  
71 - # To manually trigger reindexing of a record after you're finished modifying  
72 - # it, you can call #ferret_update directly instead of #save (remember to  
73 - # enable ferret again before).  
74 - #  
75 - # When given a block, this will be executed without any ferret indexing of  
76 - # this object taking place. The optional argument in this case can be used  
77 - # to indicate if the object should be indexed after executing the block  
78 - # (::index_when_finished). Automatic Ferret indexing of this object will be  
79 - # turned on after the block has been executed. If passed ::index_when_true,  
80 - # the index will only be updated if the block evaluated not to false or nil.  
81 - #  
82 - def disable_ferret(option = :once)  
83 - if block_given?  
84 - @ferret_disabled = :always  
85 - result = yield  
86 - ferret_enable  
87 - ferret_update if option == :index_when_finished || (option == :index_when_true && result)  
88 - result  
89 - elsif [:once, :always].include?(option)  
90 - @ferret_disabled = option  
91 - else  
92 - raise ArgumentError.new("Invalid Argument #{option}")  
93 - end  
94 - end  
95 -  
96 - # add to index  
97 - def ferret_create  
98 - if ferret_enabled?  
99 - logger.debug "ferret_create/update: #{self.class.name} : #{self.id}"  
100 - self.class.aaf_index << self  
101 - else  
102 - ferret_enable if @ferret_disabled == :once  
103 - end  
104 - true # signal success to AR  
105 - end  
106 - alias :ferret_update :ferret_create  
107 -  
108 -  
109 - # remove from index  
110 - def ferret_destroy  
111 - logger.debug "ferret_destroy: #{self.class.name} : #{self.id}"  
112 - begin  
113 - self.class.aaf_index.remove self.id, self.class.name  
114 - rescue  
115 - logger.warn("Could not find indexed value for this object: #{$!}\n#{$!.backtrace}")  
116 - end  
117 - true # signal success to AR  
118 - end  
119 -  
120 - # turn this instance into a ferret document (which basically is a hash of  
121 - # fieldname => value pairs)  
122 - def to_doc  
123 - logger.debug "creating doc for class: #{self.class.name}, id: #{self.id}"  
124 - returning Ferret::Document.new do |doc|  
125 - # store the id and class name of each item  
126 - doc[:id] = self.id  
127 - doc[:class_name] = self.class.name  
128 -  
129 - # iterate through the fields and add them to the document  
130 - aaf_configuration[:defined_fields].each_pair do |field, config|  
131 - doc[field] = self.send("#{field}_to_ferret") unless config[:ignore]  
132 - end  
133 - if aaf_configuration[:boost]  
134 - if self.respond_to?(aaf_configuration[:boost])  
135 - boost = self.send aaf_configuration[:boost]  
136 - doc.boost = boost.to_i if boost  
137 - else  
138 - logger.error "boost option should point to an instance method: #{aaf_configuration[:boost]}"  
139 - end  
140 - end  
141 - end  
142 - end  
143 -  
144 - def document_number  
145 - self.class.aaf_index.document_number(id, self.class.name)  
146 - end  
147 -  
148 - def query_for_record  
149 - self.class.aaf_index.query_for_record(id, self.class.name)  
150 - end  
151 -  
152 - def content_for_field_name(field, via = field, dynamic_boost = nil)  
153 - return nil if field.to_sym == :type  
154 - field_data = self.send(via) || self.instance_variable_get("@#{via}")  
155 - if (dynamic_boost && boost_value = self.send(dynamic_boost))  
156 - field_data = Ferret::Field.new(field_data)  
157 - field_data.boost = boost_value.to_i  
158 - end  
159 - field_data  
160 - end  
161 -  
162 -  
163 - end  
164 -  
165 -end  
vendor/plugins/acts_as_ferret/lib/local_index.rb
@@ -1,199 +0,0 @@ @@ -1,199 +0,0 @@
1 -module ActsAsFerret  
2 - class LocalIndex < AbstractIndex  
3 - include MoreLikeThis::IndexMethods  
4 -  
5 - def initialize(index_name)  
6 - super  
7 - ensure_index_exists  
8 - end  
9 -  
10 - def reopen!  
11 - logger.debug "reopening index at #{index_definition[:ferret][:path]}"  
12 - close  
13 - ferret_index  
14 - end  
15 -  
16 - # The 'real' Ferret Index instance  
17 - def ferret_index  
18 - ensure_index_exists  
19 - returning @ferret_index ||= Ferret::Index::Index.new(index_definition[:ferret]) do  
20 - @ferret_index.batch_size = index_definition[:reindex_batch_size]  
21 - @ferret_index.logger = logger  
22 - end  
23 - end  
24 -  
25 - # Checks for the presence of a segments file in the index directory  
26 - # Rebuilds the index if none exists.  
27 - def ensure_index_exists  
28 - #logger.debug "LocalIndex: ensure_index_exists at #{index_definition[:index_dir]}"  
29 - unless File.file? "#{index_definition[:index_dir]}/segments"  
30 - ActsAsFerret::ensure_directory(index_definition[:index_dir])  
31 - rebuild_index  
32 - end  
33 - end  
34 -  
35 - # Closes the underlying index instance  
36 - def close  
37 - @ferret_index.close if @ferret_index  
38 - rescue StandardError  
39 - # is raised when index already closed  
40 - ensure  
41 - @ferret_index = nil  
42 - end  
43 -  
44 - # rebuilds the index from all records of the model classes associated with this index  
45 - def rebuild_index  
46 - models = index_definition[:registered_models]  
47 - logger.debug "rebuild index with models: #{models.inspect}"  
48 - close  
49 - index = Ferret::Index::Index.new(index_definition[:ferret].dup.update(:auto_flush => false,  
50 - :field_infos => ActsAsFerret::field_infos(index_definition),  
51 - :create => true))  
52 - index.batch_size = index_definition[:reindex_batch_size]  
53 - index.logger = logger  
54 - index.index_models models  
55 - reopen!  
56 - end  
57 -  
58 - def bulk_index(class_name, ids, options)  
59 - ferret_index.bulk_index(class_name.constantize, ids, options)  
60 - end  
61 -  
62 - # Parses the given query string into a Ferret Query object.  
63 - def process_query(query, options = {})  
64 - return query unless String === query  
65 - ferret_index.synchronize do  
66 - if options[:analyzer]  
67 - # use per-query analyzer if present  
68 - qp = Ferret::QueryParser.new ferret_index.instance_variable_get('@options').merge(options)  
69 - reader = ferret_index.reader  
70 - qp.fields =  
71 - reader.fields unless options[:all_fields] || options[:fields]  
72 - qp.tokenized_fields =  
73 - reader.tokenized_fields unless options[:tokenized_fields]  
74 - return qp.parse query  
75 - else  
76 - # work around ferret bug in #process_query (doesn't ensure the  
77 - # reader is open)  
78 - ferret_index.send(:ensure_reader_open)  
79 - return ferret_index.process_query(query)  
80 - end  
81 - end  
82 - end  
83 -  
84 - # Total number of hits for the given query.  
85 - def total_hits(query, options = {})  
86 - ferret_index.search(query, options).total_hits  
87 - end  
88 -  
89 - def searcher  
90 - ferret_index  
91 - end  
92 -  
93 -  
94 - ######################################  
95 - # methods working on a single record  
96 - # called from instance_methods, here to simplify interfacing with the  
97 - # remote ferret server  
98 - # TODO having to pass id and class_name around like this isn't nice  
99 - ######################################  
100 -  
101 - # add record to index  
102 - # record may be the full AR object, a Ferret document instance or a Hash  
103 - def add(record, analyzer = nil)  
104 - unless Hash === record || Ferret::Document === record  
105 - analyzer = record.ferret_analyzer  
106 - record = record.to_doc  
107 - end  
108 - ferret_index.add_document(record, analyzer)  
109 - end  
110 - alias << add  
111 -  
112 - # delete record from index  
113 - def remove(id, class_name)  
114 - ferret_index.query_delete query_for_record(id, class_name)  
115 - end  
116 -  
117 - # highlight search terms for the record with the given id.  
118 - def highlight(id, class_name, query, options = {})  
119 - logger.debug("highlight: #{class_name} / #{id} query: #{query}")  
120 - options.reverse_merge! :num_excerpts => 2, :pre_tag => '<em>', :post_tag => '</em>'  
121 - highlights = []  
122 - ferret_index.synchronize do  
123 - doc_num = document_number(id, class_name)  
124 -  
125 - if options[:field]  
126 - highlights << ferret_index.highlight(query, doc_num, options)  
127 - else  
128 - query = process_query(query) # process only once  
129 - index_definition[:ferret_fields].each_pair do |field, config|  
130 - next if config[:store] == :no || config[:highlight] == :no  
131 - options[:field] = field  
132 - highlights << ferret_index.highlight(query, doc_num, options)  
133 - end  
134 - end  
135 - end  
136 - return highlights.compact.flatten[0..options[:num_excerpts]-1]  
137 - end  
138 -  
139 - # retrieves the ferret document number of the record with the given id.  
140 - def document_number(id, class_name)  
141 - hits = ferret_index.search(query_for_record(id, class_name))  
142 - return hits.hits.first.doc if hits.total_hits == 1  
143 - raise "cannot determine document number for class #{class_name} / primary key: #{id}\nresult was: #{hits.inspect}"  
144 - end  
145 -  
146 - # build a ferret query matching only the record with the given id  
147 - # the class name only needs to be given in case of a shared index configuration  
148 - def query_for_record(id, class_name = nil)  
149 - if shared?  
150 - raise InvalidArgumentError.new("shared index needs class_name argument") if class_name.nil?  
151 - returning bq = Ferret::Search::BooleanQuery.new do  
152 - bq.add_query(Ferret::Search::TermQuery.new(:id, id.to_s), :must)  
153 - bq.add_query(Ferret::Search::TermQuery.new(:class_name, class_name), :must)  
154 - end  
155 - else  
156 - Ferret::Search::TermQuery.new(:id, id.to_s)  
157 - end  
158 - end  
159 -  
160 -  
161 -  
162 - def determine_stored_fields(options = {})  
163 - stored_fields = options[:lazy]  
164 - if stored_fields && !(Array === stored_fields)  
165 - stored_fields = index_definition[:ferret_fields].select { |field, config| config[:store] == :yes }.map(&:first)  
166 - end  
167 - logger.debug "stored_fields: #{stored_fields.inspect}"  
168 - return stored_fields  
169 - end  
170 -  
171 - # loads data for fields declared as :lazy from the Ferret document  
172 - def extract_stored_fields(doc, stored_fields)  
173 - fields = index_definition[:ferret_fields]  
174 - data = {}  
175 - logger.debug "extracting stored fields #{stored_fields.inspect} from document #{doc[:class_name]} / #{doc[:id]}"  
176 - stored_fields.each do |field|  
177 - if field_cfg = fields[field]  
178 - data[field_cfg[:via]] = doc[field]  
179 - end  
180 - end if stored_fields  
181 - logger.debug "done: #{data.inspect}"  
182 - return data  
183 - end  
184 -  
185 - protected  
186 -  
187 - # returns a MultiIndex instance operating on a MultiReader  
188 - #def multi_index(model_classes)  
189 - # model_classes.map!(&:constantize) if String === model_classes.first  
190 - # model_classes.sort! { |a, b| a.name <=> b.name }  
191 - # key = model_classes.inject("") { |s, clazz| s + clazz.name }  
192 - # multi_config = index_definition[:ferret].dup  
193 - # multi_config.delete :default_field # we don't want the default field list of *this* class for multi_searching  
194 - # ActsAsFerret::multi_indexes[key] ||= MultiIndex.new(model_classes, multi_config)  
195 - #end  
196 -  
197 - end  
198 -  
199 -end  
vendor/plugins/acts_as_ferret/lib/more_like_this.rb
@@ -1,217 +0,0 @@ @@ -1,217 +0,0 @@
1 -module ActsAsFerret #:nodoc:  
2 -  
3 - module MoreLikeThis  
4 -  
5 - module InstanceMethods  
6 -  
7 - # returns other instances of this class, which have similar contents  
8 - # like this one. Basically works like this: find out n most interesting  
9 - # (i.e. characteristic) terms from this document, and then build a  
10 - # query from those which is run against the whole index. Which terms  
11 - # are interesting is decided on variour criteria which can be  
12 - # influenced by the given options.  
13 - #  
14 - # The algorithm used here is a quite straight port of the MoreLikeThis class  
15 - # from Apache Lucene.  
16 - #  
17 - # options are:  
18 - # :field_names : Array of field names to use for similarity search (mandatory)  
19 - # :min_term_freq => 2, # Ignore terms with less than this frequency in the source doc.  
20 - # :min_doc_freq => 5, # Ignore words which do not occur in at least this many docs  
21 - # :min_word_length => nil, # Ignore words shorter than this length (longer words tend to  
22 - # be more characteristic for the document they occur in).  
23 - # :max_word_length => nil, # Ignore words if greater than this len.  
24 - # :max_query_terms => 25, # maximum number of terms in the query built  
25 - # :max_num_tokens => 5000, # maximum number of tokens to examine in a single field  
26 - # :boost => false, # when true, a boost according to the relative score of  
27 - # a term is applied to this Term's TermQuery.  
28 - # :similarity => 'DefaultAAFSimilarity' # the similarity implementation to use (the default  
29 - # equals Ferret's internal similarity implementation)  
30 - # :analyzer => 'Ferret::Analysis::StandardAnalyzer' # class name of the analyzer to use  
31 - # :append_to_query => nil # proc taking a query object as argument, which will be called after generating the query. can be used to further manipulate the query used to find related documents, i.e. to constrain the search to a given class in single table inheritance scenarios  
32 - # ferret_options : Ferret options handed over to find_by_contents (i.e. for limits and sorting)  
33 - # ar_options : options handed over to find_by_contents for AR scoping  
34 - def more_like_this(options = {}, ferret_options = {}, ar_options = {})  
35 - options = {  
36 - :field_names => nil, # Default field names  
37 - :min_term_freq => 2, # Ignore terms with less than this frequency in the source doc.  
38 - :min_doc_freq => 5, # Ignore words which do not occur in at least this many docs  
39 - :min_word_length => 0, # Ignore words if less than this len. Default is not to ignore any words.  
40 - :max_word_length => 0, # Ignore words if greater than this len. Default is not to ignore any words.  
41 - :max_query_terms => 25, # maximum number of terms in the query built  
42 - :max_num_tokens => 5000, # maximum number of tokens to analyze when analyzing contents  
43 - :boost => false,  
44 - :similarity => 'ActsAsFerret::MoreLikeThis::DefaultAAFSimilarity', # class name of the similarity implementation to use  
45 - :analyzer => 'Ferret::Analysis::StandardAnalyzer', # class name of the analyzer to use  
46 - :append_to_query => nil,  
47 - :base_class => self.class # base class to use for querying, useful in STI scenarios where BaseClass.find_by_contents can be used to retrieve results from other classes, too  
48 - }.update(options)  
49 - #index.search_each('id:*') do |doc, score|  
50 - # puts "#{doc} == #{index[doc][:description]}"  
51 - #end  
52 - clazz = options[:base_class]  
53 - options[:base_class] = clazz.name  
54 - query = clazz.aaf_index.build_more_like_this_query(self.id, self.class.name, options)  
55 - options[:append_to_query].call(query) if options[:append_to_query]  
56 - clazz.find_with_ferret(query, ferret_options, ar_options)  
57 - end  
58 -  
59 - end  
60 -  
61 - module IndexMethods  
62 -  
63 - # TODO to allow morelikethis for unsaved records, we have to give the  
64 - # unsaved record's data to this method. check how this will work out  
65 - # via drb...  
66 - def build_more_like_this_query(id, class_name, options)  
67 - [:similarity, :analyzer].each { |sym| options[sym] = options[sym].constantize.new }  
68 - ferret_index.synchronize do # avoid that concurrent writes close our reader  
69 - ferret_index.send(:ensure_reader_open)  
70 - reader = ferret_index.send(:reader)  
71 - term_freq_map = retrieve_terms(id, class_name, reader, options)  
72 - priority_queue = create_queue(term_freq_map, reader, options)  
73 - create_query(id, class_name, priority_queue, options)  
74 - end  
75 - end  
76 -  
77 - protected  
78 -  
79 - def create_query(id, class_name, priority_queue, options={})  
80 - query = Ferret::Search::BooleanQuery.new  
81 - qterms = 0  
82 - best_score = nil  
83 - while(cur = priority_queue.pop)  
84 - term_query = Ferret::Search::TermQuery.new(cur.field, cur.word)  
85 -  
86 - if options[:boost]  
87 - # boost term according to relative score  
88 - # TODO untested  
89 - best_score ||= cur.score  
90 - term_query.boost = cur.score / best_score  
91 - end  
92 - begin  
93 - query.add_query(term_query, :should)  
94 - rescue Ferret::Search::BooleanQuery::TooManyClauses  
95 - break  
96 - end  
97 - qterms += 1  
98 - break if options[:max_query_terms] > 0 && qterms >= options[:max_query_terms]  
99 - end  
100 - # exclude the original record  
101 - query.add_query(query_for_record(id, class_name), :must_not)  
102 - return query  
103 - end  
104 -  
105 -  
106 -  
107 - # creates a term/term_frequency map for terms from the fields  
108 - # given in options[:field_names]  
109 - def retrieve_terms(id, class_name, reader, options)  
110 - raise "more_like_this atm only works on saved records" if id.nil?  
111 - document_number = document_number(id, class_name) rescue nil  
112 - field_names = options[:field_names]  
113 - max_num_tokens = options[:max_num_tokens]  
114 - term_freq_map = Hash.new(0)  
115 - doc = nil  
116 - record = nil  
117 - field_names.each do |field|  
118 - #puts "field: #{field}"  
119 - term_freq_vector = reader.term_vector(document_number, field) if document_number  
120 - #if false  
121 - if term_freq_vector  
122 - # use stored term vector  
123 - # puts 'using stored term vector'  
124 - term_freq_vector.terms.each do |term|  
125 - term_freq_map[term.text] += term.positions.size unless noise_word?(term.text, options)  
126 - end  
127 - else  
128 - # puts 'no stored term vector'  
129 - # no term vector stored, but we have stored the contents in the index  
130 - # -> extract terms from there  
131 - content = nil  
132 - if document_number  
133 - doc = reader[document_number]  
134 - content = doc[field]  
135 - end  
136 - unless content  
137 - # no term vector, no stored content, so try content from this instance  
138 - record ||= options[:base_class].constantize.find(id)  
139 - content = record.content_for_field_name(field.to_s)  
140 - end  
141 - puts "have doc: #{doc[:id]} with #{field} == #{content}"  
142 - token_count = 0  
143 -  
144 - ts = options[:analyzer].token_stream(field, content)  
145 - while token = ts.next  
146 - break if (token_count+=1) > max_num_tokens  
147 - next if noise_word?(token.text, options)  
148 - term_freq_map[token.text] += 1  
149 - end  
150 - end  
151 - end  
152 - term_freq_map  
153 - end  
154 -  
155 - # create an ordered(by score) list of word,fieldname,score  
156 - # structures  
157 - def create_queue(term_freq_map, reader, options)  
158 - pq = Array.new(term_freq_map.size)  
159 -  
160 - similarity = options[:similarity]  
161 - num_docs = reader.num_docs  
162 - term_freq_map.each_pair do |word, tf|  
163 - # filter out words that don't occur enough times in the source  
164 - next if options[:min_term_freq] && tf < options[:min_term_freq]  
165 -  
166 - # go through all the fields and find the largest document frequency  
167 - top_field = options[:field_names].first  
168 - doc_freq = 0  
169 - options[:field_names].each do |field_name|  
170 - freq = reader.doc_freq(field_name, word)  
171 - if freq > doc_freq  
172 - top_field = field_name  
173 - doc_freq = freq  
174 - end  
175 - end  
176 - # filter out words that don't occur in enough docs  
177 - next if options[:min_doc_freq] && doc_freq < options[:min_doc_freq]  
178 - next if doc_freq == 0 # index update problem ?  
179 -  
180 - idf = similarity.idf(doc_freq, num_docs)  
181 - score = tf * idf  
182 - pq << FrequencyQueueItem.new(word, top_field, score)  
183 - end  
184 - pq.compact!  
185 - pq.sort! { |a,b| a.score<=>b.score }  
186 - return pq  
187 - end  
188 -  
189 - def noise_word?(text, options)  
190 - len = text.length  
191 - (  
192 - (options[:min_word_length] > 0 && len < options[:min_word_length]) ||  
193 - (options[:max_word_length] > 0 && len > options[:max_word_length]) ||  
194 - (options[:stop_words] && options.include?(text))  
195 - )  
196 - end  
197 -  
198 - end  
199 -  
200 - class DefaultAAFSimilarity  
201 - def idf(doc_freq, num_docs)  
202 - return 0.0 if num_docs == 0  
203 - return Math.log(num_docs.to_f/(doc_freq+1)) + 1.0  
204 - end  
205 - end  
206 -  
207 -  
208 - class FrequencyQueueItem  
209 - attr_reader :word, :field, :score  
210 - def initialize(word, field, score)  
211 - @word = word; @field = field; @score = score  
212 - end  
213 - end  
214 -  
215 - end  
216 -end  
217 -  
vendor/plugins/acts_as_ferret/lib/multi_index.rb
@@ -1,126 +0,0 @@ @@ -1,126 +0,0 @@
1 -module ActsAsFerret #:nodoc:  
2 -  
3 - # Base class for remote and local multi-indexes  
4 - class MultiIndexBase  
5 - include FerretFindMethods  
6 - attr_accessor :logger  
7 -  
8 - def initialize(indexes, options = {})  
9 - # ensure all models indexes exist  
10 - @indexes = indexes  
11 - indexes.each { |i| i.ensure_index_exists }  
12 - default_fields = indexes.inject([]) do |fields, idx|  
13 - fields + [ idx.index_definition[:ferret][:default_field] ]  
14 - end.flatten.uniq  
15 - @options = {  
16 - :default_field => default_fields  
17 - }.update(options)  
18 - @logger = IndexLogger.new(ActsAsFerret::logger, "multi: #{indexes.map(&:index_name).join(',')}")  
19 - end  
20 -  
21 - def ar_find(query, options = {}, ar_options = {})  
22 - limit = options.delete(:limit)  
23 - offset = options.delete(:offset) || 0  
24 - options[:limit] = :all  
25 - total_hits, result = super query, options, ar_options  
26 - total_hits = result.size if ar_options[:conditions]  
27 - if limit && limit != :all  
28 - result = result[offset..limit+offset-1]  
29 - end  
30 - [total_hits, result]  
31 - end  
32 -  
33 - def determine_stored_fields(options)  
34 - return nil unless options.has_key?(:lazy)  
35 - stored_fields = []  
36 - @indexes.each do |index|  
37 - stored_fields += index.determine_stored_fields(options)  
38 - end  
39 - return stored_fields.uniq  
40 - end  
41 -  
42 - def shared?  
43 - false  
44 - end  
45 -  
46 - end  
47 -  
48 - # This class can be used to search multiple physical indexes at once.  
49 - class MultiIndex < MultiIndexBase  
50 -  
51 - def extract_stored_fields(doc, stored_fields)  
52 - ActsAsFerret::get_index_for(doc[:class_name]).extract_stored_fields(doc, stored_fields) unless stored_fields.blank?  
53 - end  
54 -  
55 - def total_hits(q, options = {})  
56 - search(q, options).total_hits  
57 - end  
58 -  
59 - def search(query, options={})  
60 - query = process_query(query, options)  
61 - logger.debug "parsed query: #{query.to_s}"  
62 - searcher.search(query, options)  
63 - end  
64 -  
65 - def search_each(query, options = {}, &block)  
66 - query = process_query(query, options)  
67 - searcher.search_each(query, options, &block)  
68 - end  
69 -  
70 - # checks if all our sub-searchers still are up to date  
71 - def latest?  
72 - #return false unless @reader  
73 - # segfaults with 0.10.4 --> TODO report as bug @reader.latest?  
74 - @reader and @reader.latest?  
75 - #@sub_readers.each do |r|  
76 - # return false unless r.latest?  
77 - #end  
78 - #true  
79 - end  
80 -  
81 - def searcher  
82 - ensure_searcher  
83 - @searcher  
84 - end  
85 -  
86 - def doc(i)  
87 - searcher[i]  
88 - end  
89 - alias :[] :doc  
90 -  
91 - def query_parser  
92 - @query_parser ||= Ferret::QueryParser.new(@options)  
93 - end  
94 -  
95 - def process_query(query, options = {})  
96 - query = query_parser.parse(query) if query.is_a?(String)  
97 - return query  
98 - end  
99 -  
100 - def close  
101 - @searcher.close if @searcher  
102 - @reader.close if @reader  
103 - end  
104 -  
105 - protected  
106 -  
107 - def ensure_searcher  
108 - unless latest?  
109 - @sub_readers = @indexes.map { |idx|  
110 - begin  
111 - reader = Ferret::Index::IndexReader.new(idx.index_definition[:index_dir])  
112 - logger.debug "sub-reader opened: #{reader}"  
113 - reader  
114 - rescue Exception  
115 - raise "error opening reader on index for class #{clazz.inspect}: #{$!}"  
116 - end  
117 - }  
118 - close  
119 - @reader = Ferret::Index::IndexReader.new(@sub_readers)  
120 - @searcher = Ferret::Search::Searcher.new(@reader)  
121 - end  
122 - end  
123 -  
124 - end # of class MultiIndex  
125 -  
126 -end  
vendor/plugins/acts_as_ferret/lib/rdig_adapter.rb
@@ -1,141 +0,0 @@ @@ -1,141 +0,0 @@
1 -begin  
2 - require 'rdig'  
3 -rescue LoadError  
4 -end  
5 -module ActsAsFerret  
6 -  
7 - # The RdigAdapter is automatically included into your model if you specify  
8 - # the +:rdig+ options hash in your call to acts_as_ferret. It overrides  
9 - # several methods declared by aaf to retrieve documents with the help of  
10 - # RDig's http crawler when you call rebuild_index.  
11 - module RdigAdapter  
12 -  
13 - if defined?(RDig)  
14 -  
15 - def self.included(target)  
16 - target.extend ClassMethods  
17 - target.send :include, InstanceMethods  
18 - end  
19 -  
20 - # Indexer class to replace RDig's original indexer  
21 - class Indexer  
22 - include MonitorMixin  
23 - def initialize(batch_size, model_class, &block)  
24 - @batch_size = batch_size  
25 - @model_class = model_class  
26 - @documents = []  
27 - @offset = 0  
28 - @block = block  
29 - super()  
30 - end  
31 -  
32 - def add(doc)  
33 - synchronize do  
34 - @documents << @model_class.new(doc.uri.to_s, doc)  
35 - process_batch if @documents.size >= @batch_size  
36 - end  
37 - end  
38 - alias << add  
39 -  
40 - def close  
41 - synchronize do  
42 - process_batch  
43 - end  
44 - end  
45 -  
46 - protected  
47 - def process_batch  
48 - ActsAsFerret::logger.info "RdigAdapter::Indexer#process_batch: #{@documents.size} docs in queue, offset #{@offset}"  
49 - @block.call @documents, @offset  
50 - @offset += @documents.size  
51 - @documents = []  
52 - end  
53 - end  
54 -  
55 - module ClassMethods  
56 - # overriding aaf to return the documents fetched via RDig  
57 - def records_for_rebuild(batch_size = 1000, &block)  
58 - indexer = Indexer.new(batch_size, self, &block)  
59 - configure_rdig do  
60 - crawler = RDig::Crawler.new RDig.configuration, ActsAsFerret::logger  
61 - crawler.instance_variable_set '@indexer', indexer  
62 - ActsAsFerret::logger.debug "now crawling..."  
63 - crawler.crawl  
64 - end  
65 - rescue => e  
66 - ActsAsFerret::logger.error e  
67 - ActsAsFerret::logger.debug e.backtrace.join("\n")  
68 - ensure  
69 - indexer.close if indexer  
70 - end  
71 -  
72 - # overriding aaf to skip reindexing records changed during the rebuild  
73 - # when rebuilding with the rake task  
74 - def records_modified_since(time)  
75 - []  
76 - end  
77 -  
78 - # unfortunately need to modify global RDig.configuration because it's  
79 - # used everywhere in RDig  
80 - def configure_rdig  
81 - # back up original config  
82 - old_logger = RDig.logger  
83 - old_cfg = RDig.configuration.dup  
84 - RDig.logger = ActsAsFerret.logger  
85 - rdig_configuration[:crawler].each { |k,v| RDig.configuration.crawler.send :"#{k}=", v } if rdig_configuration[:crawler]  
86 - if ce_config = rdig_configuration[:content_extraction]  
87 - RDig.configuration.content_extraction = OpenStruct.new( :hpricot => OpenStruct.new( ce_config ) )  
88 - end  
89 - yield  
90 - ensure  
91 - # restore original config  
92 - RDig.configuration.crawler = old_cfg.crawler  
93 - RDig.configuration.content_extraction = old_cfg.content_extraction  
94 - RDig.logger = old_logger  
95 - end  
96 -  
97 - # overriding aaf to enforce loading page title and content from the  
98 - # ferret index  
99 - def find_with_ferret(q, options = {}, find_options = {})  
100 - options[:lazy] = true  
101 - super  
102 - end  
103 -  
104 - def find_for_id(id)  
105 - new id  
106 - end  
107 - end  
108 -  
109 - module InstanceMethods  
110 - def initialize(uri, rdig_document = nil)  
111 - @id = uri  
112 - @rdig_document = rdig_document  
113 - end  
114 -  
115 - # Title of the document.  
116 - # Use the +:title_tag_selector+ option to declare the hpricot expression  
117 - # that should be used for selecting the content for this field.  
118 - def title  
119 - @rdig_document.title  
120 - end  
121 -  
122 - # Content of the document.  
123 - # Use the +:content_tag_selector+ option to declare the hpricot expression  
124 - # that should be used for selecting the content for this field.  
125 - def content  
126 - @rdig_document.body  
127 - end  
128 -  
129 - # Url of this document.  
130 - def id  
131 - @id  
132 - end  
133 -  
134 - def to_s  
135 - "Page at #{id}, title: #{title}"  
136 - end  
137 - end  
138 - end  
139 - end  
140 -  
141 -end  
vendor/plugins/acts_as_ferret/lib/remote_functions.rb
@@ -1,23 +0,0 @@ @@ -1,23 +0,0 @@
1 -module ActsAsFerret  
2 - module RemoteFunctions  
3 -  
4 - private  
5 -  
6 - def yield_results(total_hits, results)  
7 - results.each do |result|  
8 - yield result[:model], result[:id], result[:score], result[:data]  
9 - end  
10 - total_hits  
11 - end  
12 -  
13 -  
14 - def handle_drb_error(return_value_in_case_of_error = false)  
15 - yield  
16 - rescue DRb::DRbConnError => e  
17 - logger.error "DRb connection error: #{e}"  
18 - logger.warn e.backtrace.join("\n")  
19 - raise e if ActsAsFerret::raise_drb_errors?  
20 - return_value_in_case_of_error  
21 - end  
22 - end  
23 -end  
vendor/plugins/acts_as_ferret/lib/remote_index.rb
@@ -1,54 +0,0 @@ @@ -1,54 +0,0 @@
1 -require 'drb'  
2 -module ActsAsFerret  
3 -  
4 - # This index implementation connects to a remote ferret server instance. It  
5 - # basically forwards all calls to the remote server.  
6 - class RemoteIndex < AbstractIndex  
7 - include RemoteFunctions  
8 -  
9 - def initialize(config)  
10 - super  
11 - @server = DRbObject.new(nil, ActsAsFerret::remote)  
12 - end  
13 -  
14 - # Cause model classes to be loaded (and indexes get declared) on the DRb  
15 - # side of things.  
16 - def register_class(clazz, options)  
17 - handle_drb_error { @server.register_class clazz.name }  
18 - end  
19 -  
20 - def method_missing(method_name, *args)  
21 - args.unshift index_name  
22 - handle_drb_error { @server.send(method_name, *args) }  
23 - end  
24 -  
25 - # Proxy any methods that require special return values in case of errors  
26 - {  
27 - :highlight => []  
28 - }.each do |method_name, default_result|  
29 - define_method method_name do |*args|  
30 - args.unshift index_name  
31 - handle_drb_error(default_result) { @server.send method_name, *args }  
32 - end  
33 - end  
34 -  
35 - def find_ids(q, options = {}, &proc)  
36 - total_hits, results = handle_drb_error([0, []]) { @server.find_ids(index_name, q, options) }  
37 - block_given? ? yield_results(total_hits, results, &proc) : [ total_hits, results ]  
38 - end  
39 -  
40 - # add record to index  
41 - def add(record)  
42 - handle_drb_error { @server.add index_name, record.to_doc }  
43 - end  
44 - alias << add  
45 -  
46 - private  
47 -  
48 - #def model_class_name  
49 - # index_definition[:class_name]  
50 - #end  
51 -  
52 - end  
53 -  
54 -end  
vendor/plugins/acts_as_ferret/lib/remote_multi_index.rb
@@ -1,20 +0,0 @@ @@ -1,20 +0,0 @@
1 -module ActsAsFerret  
2 - class RemoteMultiIndex < MultiIndexBase  
3 - include RemoteFunctions  
4 -  
5 - def initialize(indexes, options = {})  
6 - @index_names = indexes.map(&:index_name)  
7 - @server = DRbObject.new(nil, ActsAsFerret::remote)  
8 - super  
9 - end  
10 -  
11 - def find_ids(query, options, &proc)  
12 - total_hits, results = handle_drb_error([0, []]) { @server.multi_find_ids(@index_names, query, options) }  
13 - block_given? ? yield_results(total_hits, results, &proc) : [ total_hits, results ]  
14 - end  
15 -  
16 - def method_missing(name, *args)  
17 - handle_drb_error { @server.send(:"multi_#{name}", @index_names, *args) }  
18 - end  
19 - end  
20 -end  
vendor/plugins/acts_as_ferret/lib/search_results.rb
@@ -1,50 +0,0 @@ @@ -1,50 +0,0 @@
1 -module ActsAsFerret  
2 -  
3 - # decorator that adds a total_hits accessor and will_paginate compatible  
4 - # paging support to search result arrays  
5 - class SearchResults < ActsAsFerret::BlankSlate  
6 - reveal :methods  
7 - attr_reader :current_page, :per_page, :total_hits, :total_pages  
8 - alias total_entries total_hits # will_paginate compatibility  
9 - alias page_count total_pages # will_paginate backwards compatibility  
10 -  
11 - def initialize(results, total_hits, current_page = 1, per_page = nil)  
12 - @results = results  
13 - @total_hits = total_hits  
14 - @current_page = current_page  
15 - @per_page = (per_page || total_hits)  
16 - @total_pages = @per_page > 0 ? (@total_hits / @per_page.to_f).ceil : 0  
17 - end  
18 -  
19 - def method_missing(symbol, *args, &block)  
20 - @results.send(symbol, *args, &block)  
21 - end  
22 -  
23 - def respond_to?(name)  
24 - methods.include?(name.to_s) || @results.respond_to?(name)  
25 - end  
26 -  
27 -  
28 - # code from here on was directly taken from will_paginate's collection.rb  
29 -  
30 - # Current offset of the paginated collection. If we're on the first page,  
31 - # it is always 0. If we're on the 2nd page and there are 30 entries per page,  
32 - # the offset is 30. This property is useful if you want to render ordinals  
33 - # besides your records: simply start with offset + 1.  
34 - #  
35 - def offset  
36 - (current_page - 1) * per_page  
37 - end  
38 -  
39 - # current_page - 1 or nil if there is no previous page  
40 - def previous_page  
41 - current_page > 1 ? (current_page - 1) : nil  
42 - end  
43 -  
44 - # current_page + 1 or nil if there is no next page  
45 - def next_page  
46 - current_page < total_pages ? (current_page + 1) : nil  
47 - end  
48 - end  
49 -  
50 -end  
vendor/plugins/acts_as_ferret/lib/server_manager.rb
@@ -1,58 +0,0 @@ @@ -1,58 +0,0 @@
1 -################################################################################  
2 -require 'optparse'  
3 -  
4 -################################################################################  
5 -$ferret_server_options = {  
6 - 'environment' => nil,  
7 - 'debug' => nil,  
8 - 'root' => nil  
9 -}  
10 -  
11 -################################################################################  
12 -OptionParser.new do |optparser|  
13 - optparser.banner = "Usage: #{File.basename($0)} [options] {start|stop|run}"  
14 -  
15 - optparser.on('-h', '--help', "This message") do  
16 - puts optparser  
17 - exit  
18 - end  
19 -  
20 - optparser.on('-R', '--root=PATH', 'Set RAILS_ROOT to the given string') do |r|  
21 - $ferret_server_options['root'] = r  
22 - end  
23 -  
24 - optparser.on('-e', '--environment=NAME', 'Set RAILS_ENV to the given string') do |e|  
25 - $ferret_server_options['environment'] = e  
26 - end  
27 -  
28 - optparser.on('--debug', 'Include full stack traces on exceptions') do  
29 - $ferret_server_options['debug'] = true  
30 - end  
31 -  
32 - $ferret_server_action = optparser.permute!(ARGV)  
33 - (puts optparser; exit(1)) unless $ferret_server_action.size == 1  
34 -  
35 - $ferret_server_action = $ferret_server_action.first  
36 - (puts optparser; exit(1)) unless %w(start stop run).include?($ferret_server_action)  
37 -end  
38 -  
39 -################################################################################  
40 -begin  
41 - ENV['FERRET_USE_LOCAL_INDEX'] = 'true'  
42 - ENV['RAILS_ENV'] = $ferret_server_options['environment']  
43 -  
44 - # determine RAILS_ROOT unless already set  
45 - RAILS_ROOT = $ferret_server_options['root'] || File.join(File.dirname(__FILE__), *(['..']*4)) unless defined? RAILS_ROOT  
46 - # check if environment.rb is present  
47 - rails_env_file = File.join(RAILS_ROOT, 'config', 'environment')  
48 - raise "Unable to find Rails environment.rb at \n#{rails_env_file}.rb\nPlease use the --root option of ferret_server to point it to your RAILS_ROOT." unless File.exists?(rails_env_file+'.rb')  
49 - # load it  
50 - require rails_env_file  
51 -  
52 - require 'acts_as_ferret'  
53 - ActsAsFerret::Remote::Server.new.send($ferret_server_action)  
54 -rescue Exception => e  
55 - $stderr.puts(e.message)  
56 - $stderr.puts(e.backtrace.join("\n")) if $ferret_server_options['debug']  
57 - exit(1)  
58 -end  
vendor/plugins/acts_as_ferret/lib/unix_daemon.rb
@@ -1,64 +0,0 @@ @@ -1,64 +0,0 @@
1 -################################################################################  
2 -module ActsAsFerret  
3 - module Remote  
4 -  
5 - ################################################################################  
6 - # methods for becoming a daemon on Unix-like operating systems  
7 - module UnixDaemon  
8 -  
9 - ################################################################################  
10 - def platform_daemon (&block)  
11 - safefork do  
12 - write_pid_file  
13 - trap("TERM") { exit(0) }  
14 - sess_id = Process.setsid  
15 - STDIN.reopen("/dev/null")  
16 - STDOUT.reopen("#{RAILS_ROOT}/log/ferret_server.out", "a")  
17 - STDERR.reopen(STDOUT)  
18 - block.call  
19 - end  
20 - end  
21 -  
22 - ################################################################################  
23 - # stop the daemon, nicely at first, and then forcefully if necessary  
24 - def stop  
25 - pid = read_pid_file  
26 - raise "ferret_server doesn't appear to be running" unless pid  
27 - $stdout.puts("stopping ferret server...")  
28 - Process.kill("TERM", pid)  
29 - 30.times { Process.kill(0, pid); sleep(0.5) }  
30 - $stdout.puts("using kill -9 #{pid}")  
31 - Process.kill(9, pid)  
32 - rescue Errno::ESRCH => e  
33 - $stdout.puts("process #{pid} has stopped")  
34 - ensure  
35 - File.unlink(@cfg.pid_file) if File.exist?(@cfg.pid_file)  
36 - end  
37 -  
38 - ################################################################################  
39 - def safefork (&block)  
40 - @fork_tries ||= 0  
41 - fork(&block)  
42 - rescue Errno::EWOULDBLOCK  
43 - raise if @fork_tries >= 20  
44 - @fork_tries += 1  
45 - sleep 5  
46 - retry  
47 - end  
48 -  
49 - #################################################################################  
50 - # create the PID file and install an at_exit handler  
51 - def write_pid_file  
52 - raise "ferret_server may already be running, a pid file exists: #{@cfg.pid_file}" if read_pid_file  
53 - open(@cfg.pid_file, "w") {|f| f << Process.pid << "\n"}  
54 - at_exit { File.unlink(@cfg.pid_file) if read_pid_file == Process.pid }  
55 - end  
56 -  
57 - #################################################################################  
58 - def read_pid_file  
59 - File.read(@cfg.pid_file).to_i if File.exist?(@cfg.pid_file)  
60 - end  
61 -  
62 - end  
63 - end  
64 -end  
vendor/plugins/acts_as_ferret/lib/without_ar.rb
@@ -1,49 +0,0 @@ @@ -1,49 +0,0 @@
1 -module ActsAsFerret  
2 -  
3 - # Include this module to use acts_as_ferret with model classes  
4 - # not based on ActiveRecord.  
5 - #  
6 - # Implement the find_for_id(id) class method in your model class in  
7 - # order to make search work.  
8 - module WithoutAR  
9 - def self.included(target)  
10 - target.extend ClassMethods  
11 - target.extend ActsAsFerret::ActMethods  
12 - target.send :include, InstanceMethods  
13 - end  
14 -  
15 - module ClassMethods  
16 - def logger  
17 - RAILS_DEFAULT_LOGGER  
18 - end  
19 - def table_name  
20 - self.name.underscore  
21 - end  
22 - def primary_key  
23 - 'id'  
24 - end  
25 - def find(what, args = {})  
26 - case what  
27 - when :all  
28 - ids = args[:conditions][1]  
29 - ids.map { |id| find id }  
30 - else  
31 - find_for_id what  
32 - end  
33 - end  
34 - def find_for_id(id)  
35 - raise NotImplementedError.new("implement find_for_id in class #{self.name}")  
36 - end  
37 - def count  
38 - 0  
39 - end  
40 - end  
41 -  
42 - module InstanceMethods  
43 - def logger  
44 - self.class.logger  
45 - end  
46 - end  
47 - end  
48 -  
49 -end  
vendor/plugins/acts_as_ferret/rakefile
@@ -1,134 +0,0 @@ @@ -1,134 +0,0 @@
1 -# rakefile for acts_as_ferret.  
2 -# use to create a gem or generate rdoc api documentation.  
3 -#  
4 -# RELEASE creation:  
5 -# rake release REL=x.y.z  
6 -  
7 -require 'rake'  
8 -require 'rake/rdoctask'  
9 -require 'rake/packagetask'  
10 -require 'rake/gempackagetask'  
11 -require 'rake/testtask'  
12 -require 'rake/contrib/rubyforgepublisher'  
13 -  
14 -def announce(msg='')  
15 - STDERR.puts msg  
16 -end  
17 -  
18 -  
19 -PKG_NAME = 'acts_as_ferret'  
20 -PKG_VERSION = ENV['REL']  
21 -PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"  
22 -RUBYFORGE_PROJECT = 'actsasferret'  
23 -RUBYFORGE_USER = 'jkraemer'  
24 -  
25 -desc 'Default: run unit tests.'  
26 -task :default => :test  
27 -  
28 -desc 'Test the acts_as_ferret plugin.'  
29 -Rake::TestTask.new(:test) do |t|  
30 - t.libs << 'lib'  
31 - t.pattern = 'test/**/*_test.rb'  
32 - t.verbose = true  
33 -end  
34 -  
35 -desc 'Generate documentation for the acts_as_ferret plugin.'  
36 -Rake::RDocTask.new(:rdoc) do |rdoc|  
37 - rdoc.rdoc_dir = 'html'  
38 - rdoc.title = "acts_as_ferret - Ferret based full text search for any ActiveRecord model"  
39 - rdoc.options << '--line-numbers' << '--inline-source'  
40 - rdoc.options << '--main' << 'README'  
41 - rdoc.rdoc_files.include('README', 'LICENSE')  
42 - rdoc.template = "#{ENV['template']}.rb" if ENV['template']  
43 - rdoc.rdoc_files.include('lib/**/*.rb')  
44 -end  
45 -  
46 -desc "Publish the API documentation"  
47 -task :pdoc => [:rdoc] do  
48 - Rake::RubyForgePublisher.new(RUBYFORGE_PROJECT, RUBYFORGE_USER).upload  
49 -end  
50 -  
51 -if PKG_VERSION  
52 - spec = Gem::Specification.new do |s|  
53 - s.name = PKG_NAME  
54 - s.version = PKG_VERSION  
55 - s.platform = Gem::Platform::RUBY  
56 - s.summary = "acts_as_ferret - Ferret based full text search for any ActiveRecord model"  
57 - s.files = Dir.glob('**/*', File::FNM_DOTMATCH).reject do |f|  
58 - [ /\.$/, /sqlite$/, /\.log$/, /^pkg/, /\.svn/, /\.\w+\.sw.$/,  
59 - /^html/, /\~$/, /\/\._/, /\/#/ ].any? {|regex| f =~ regex }  
60 - end  
61 - #s.files = FileList["{lib,test}/**/*"].to_a + %w(README MIT-LICENSE CHANGELOG)  
62 - # s.files.delete ...  
63 - s.require_path = 'lib'  
64 - s.bindir = "bin"  
65 - s.executables = ["aaf_install"]  
66 - s.default_executable = "aaf_install"  
67 - s.autorequire = 'acts_as_ferret'  
68 - s.has_rdoc = true  
69 - # s.test_files = Dir['test/**/*_test.rb']  
70 - s.author = "Jens Kraemer"  
71 - s.email = "jk@jkraemer.net"  
72 - s.homepage = "http://projects.jkraemer.net/acts_as_ferret"  
73 - end  
74 -  
75 - package_task = Rake::GemPackageTask.new(spec) do |pkg|  
76 - pkg.need_tar = true  
77 - end  
78 -  
79 - # Validate that everything is ready to go for a release.  
80 - task :prerelease do  
81 - announce  
82 - announce "**************************************************************"  
83 - announce "* Making RubyGem Release #{PKG_VERSION}"  
84 - announce "**************************************************************"  
85 - announce  
86 - # Are all source files checked in?  
87 - if ENV['RELTEST']  
88 - announce "Release Task Testing, skipping checked-in file test"  
89 - else  
90 - announce "Pulling in svn..."  
91 - `svk pull .`  
92 - announce "Checking for unchecked-in files..."  
93 - data = `svk st`  
94 - unless data =~ /^$/  
95 - fail "SVK status is not clean ... do you have unchecked-in files?"  
96 - end  
97 - announce "No outstanding checkins found ... OK"  
98 -# announce "Pushing to svn..."  
99 -# `svk push .`  
100 - end  
101 - end  
102 -  
103 -  
104 - desc "tag the new release"  
105 - task :tag => [ :prerelease ] do  
106 - reltag = "REL_#{PKG_VERSION.gsub(/\./, '_')}"  
107 - reltag << ENV['REUSE'].gsub(/\./, '_') if ENV['REUSE']  
108 - announce "Tagging with [#{PKG_VERSION}]"  
109 - if ENV['RELTEST']  
110 - announce "Release Task Testing, skipping tagging"  
111 - else  
112 - `svn copy -m 'tagging version #{PKG_VERSION}' svn://projects.jkraemer.net/acts_as_ferret/trunk/plugin svn://projects.jkraemer.net/acts_as_ferret/tags/#{PKG_VERSION}`  
113 - `svn del -m 'remove old stable' svn://projects.jkraemer.net/acts_as_ferret/tags/stable`  
114 - `svn copy -m 'tagging version #{PKG_VERSION} as stable' svn://projects.jkraemer.net/acts_as_ferret/tags/#{PKG_VERSION} svn://projects.jkraemer.net/acts_as_ferret/tags/stable`  
115 - end  
116 - end  
117 -  
118 - # Upload release to rubyforge  
119 - desc "Upload release to rubyforge"  
120 - task :prel => [ :tag, :prerelease, :package ] do  
121 - `rubyforge login`  
122 - release_command = "rubyforge add_release #{RUBYFORGE_PROJECT} #{PKG_NAME} '#{PKG_VERSION}' pkg/#{PKG_NAME}-#{PKG_VERSION}.gem"  
123 - puts release_command  
124 - system(release_command)  
125 - `rubyforge config #{RUBYFORGE_PROJECT}`  
126 - release_command = "rubyforge add_file #{RUBYFORGE_PROJECT} #{PKG_NAME} '#{PKG_VERSION}' pkg/#{PKG_NAME}-#{PKG_VERSION}.tgz"  
127 - puts release_command  
128 - system(release_command)  
129 - end  
130 -  
131 - desc 'Publish the gem and API docs'  
132 - task :release => [:pdoc, :prel ]  
133 -  
134 -end  
vendor/plugins/acts_as_ferret/recipes/aaf_recipes.rb
@@ -1,97 +0,0 @@ @@ -1,97 +0,0 @@
1 -# Ferret DRb server Capistrano tasks  
2 -#  
3 -# Usage:  
4 -# in your Capfile, add acts_as_ferret's recipes directory to your load path and  
5 -# load the ferret tasks:  
6 -#  
7 -# load_paths << 'vendor/plugins/acts_as_ferret/recipes'  
8 -# load 'aaf_recipes'  
9 -#  
10 -# This will hook aaf's DRb start/stop tasks into the standard  
11 -# deploy:{start|restart|stop} tasks so the server will be restarted along with  
12 -# the rest of your application.  
13 -# Also an index directory in the shared folder will be created and symlinked  
14 -# into current/ when you deploy.  
15 -#  
16 -# In order to use the ferret:index:rebuild task, declare the indexes you intend to  
17 -# rebuild remotely in config/deploy.rb:  
18 -#  
19 -# set :ferret_indexes, %w( model another_model shared )  
20 -#  
21 -# HINT: To be very sure that your DRb server and application are always using  
22 -# the same model and schema versions, and you never lose any index updates because  
23 -# of the DRb server being restarted in that moment, use the following sequence  
24 -# to update your application:  
25 -#  
26 -# cap deploy:stop deploy:update deploy:migrate deploy:start  
27 -#  
28 -# That will stop the DRb server after stopping your application, and bring it  
29 -# up before starting the application again. Plus they'll never use different  
30 -# versions of model classes (which might happen otherwise)  
31 -# Downside: Your downtime is a bit longer than with the usual deploy, so be sure to  
32 -# put up some maintenance page for the meantime. Obviously this won't work if  
33 -# your migrations need acts_as_ferret (i.e. if you update model instances which  
34 -# would lead to index updates). In this case bring up the DRb server before  
35 -# running your migrations:  
36 -#  
37 -# cap deploy:stop deploy:update ferret:start deploy:migrate ferret:stop deploy:start  
38 -#  
39 -# Chances are that you're still not safe if your migrations not only modify the index,  
40 -# but also change the structure of your models. So just don't do both things in  
41 -# one go - I can't think of an easy way to handle this case automatically.  
42 -# Suggestions and patches are of course very welcome :-)  
43 -  
44 -namespace :ferret do  
45 -  
46 - desc "Stop the Ferret DRb server"  
47 - task :stop, :roles => :app do  
48 - rails_env = fetch(:rails_env, 'production')  
49 - run "cd #{current_path}; script/ferret_server -e #{rails_env} stop || true"  
50 - end  
51 -  
52 - desc "Start the Ferret DRb server"  
53 - task :start, :roles => :app do  
54 - rails_env = fetch(:rails_env, 'production')  
55 - run "cd #{current_path}; script/ferret_server -e #{rails_env} start"  
56 - end  
57 -  
58 - desc "Restart the Ferret DRb server"  
59 - task :restart, :roles => :app do  
60 - top.ferret.stop  
61 - sleep 1  
62 - top.ferret.start  
63 - end  
64 -  
65 - namespace :index do  
66 -  
67 - desc "Rebuild the Ferret index. See aaf_recipes.rb for instructions."  
68 - task :rebuild => :environment, :roles => :app do  
69 - rake = fetch(:rake, 'rake')  
70 - rails_env = fetch(:rails_env, 'production')  
71 - indexes = fetch(:ferret_indexes, nil)  
72 - if indexes and indexes.any?  
73 - run "cd #{current_path}; RAILS_ENV=#{rails_env} INDEXES='#{indexes.join(' ')}' #{rake} ferret:rebuild"  
74 - end  
75 - end  
76 -  
77 - desc "purges all indexes for the current environment"  
78 - task :purge, :roles => :app do  
79 - run "rm -fr #{shared_path}/index/#{rails_env}"  
80 - end  
81 -  
82 - desc "symlinks index folder"  
83 - task :symlink, :roles => :app do  
84 - run "mkdir -p #{shared_path}/index && rm -rf #{release_path}/index && ln -nfs #{shared_path}/index #{release_path}/index"  
85 - end  
86 -  
87 - end  
88 -  
89 -end  
90 -  
91 -after "deploy:stop", "ferret:stop"  
92 -before "deploy:start", "ferret:start"  
93 -  
94 -before "deploy:restart", "ferret:stop"  
95 -after "deploy:restart", "ferret:start"  
96 -after "deploy:symlink", "ferret:index:symlink"  
97 -  
vendor/plugins/acts_as_ferret/script/ferret_daemon
@@ -1,94 +0,0 @@ @@ -1,94 +0,0 @@
1 -# Ferret Win32 Service Daemon, called by Win 32 service,  
2 -# created by Herryanto Siatono <herryanto@pluitsolutions.com>  
3 -#  
4 -# see doc/README.win32 for usage instructions  
5 -#  
6 -require 'optparse'  
7 -require 'win32/service'  
8 -include Win32  
9 -  
10 -# Read options  
11 -options = {}  
12 -ARGV.options do |opts|  
13 - opts.banner = 'Usage: ferret_daemon [options]'  
14 - opts.on("-l", "--log FILE", "Daemon log file") {|file| options[:log] = file }  
15 - opts.on("-c","--console","Run Ferret server on console.") {options[:console] = true}  
16 - opts.on_tail("-h","--help", "Show this help message") {puts opts; exit}  
17 - opts.on("-e", "--environment ENV ", "Rails environment") {|env|  
18 - options[:environment] = env  
19 - ENV['RAILS_ENV'] = env  
20 - }  
21 - opts.parse!  
22 -end  
23 -  
24 -require File.dirname(__FILE__) + '/../config/environment'  
25 -  
26 -# Ferret Win32 Service Daemon, called by Win 32 service,  
27 -# to run on the console, use -c or --console option.  
28 -module Ferret  
29 - class FerretDaemon < Daemon  
30 - # Standard logger to redirect STDOUT and STDERR to a log file  
31 - class FerretStandardLogger  
32 - def initialize(logger)  
33 - @logger = logger  
34 - end  
35 -  
36 - def write(s)  
37 - @logger.info s  
38 - end  
39 - end  
40 -  
41 - def initialize(options={})  
42 - @options = options  
43 -  
44 - # initialize logger  
45 - if options[:log]  
46 - @logger = Logger.new @options[:log]  
47 - else  
48 - @logger = Logger.new RAILS_ROOT + "/log/ferret_service_#{RAILS_ENV}.log"  
49 - end  
50 -  
51 - # redirect stout and stderr to Ferret logger if running as windows service  
52 - $stdout = $stderr = FerretStandardLogger.new(@logger) unless @options[:console]  
53 -  
54 - log "Initializing FerretDaemon..."  
55 - if @options[:console]  
56 - self.service_init  
57 - self.service_main  
58 - end  
59 - end  
60 -  
61 - def service_main  
62 - log "Service main enterred..."  
63 -  
64 - while running?  
65 - log "Listening..."  
66 - sleep  
67 - end  
68 -  
69 - log "Service main exit..."  
70 - end  
71 -  
72 - def service_init  
73 - log "Starting Ferret DRb server..."  
74 - ActsAsFerret::Remote::Server.start  
75 - log "FerretDaemon started."  
76 - end  
77 -  
78 - def service_stop  
79 - log "Stopping service..."  
80 - DRb.stop_service  
81 - log "FerretDaemon stopped."  
82 - end  
83 -  
84 - def log(msg)  
85 - @logger.info msg  
86 - puts msg if @options[:console]  
87 - end  
88 - end  
89 -end  
90 -  
91 -if __FILE__ == $0  
92 - d = Ferret::FerretDaemon.new(options)  
93 - d.mainloop  
94 -end  
vendor/plugins/acts_as_ferret/script/ferret_server
@@ -1,10 +0,0 @@ @@ -1,10 +0,0 @@
1 -#!/usr/bin/env ruby  
2 -  
3 -begin  
4 - require File.join(File.dirname(__FILE__), '../vendor/plugins/acts_as_ferret/lib/server_manager')  
5 -rescue LoadError  
6 - # try the gem  
7 - require 'rubygems'  
8 - gem 'acts_as_ferret'  
9 - require 'server_manager'  
10 -end  
vendor/plugins/acts_as_ferret/script/ferret_service
@@ -1,178 +0,0 @@ @@ -1,178 +0,0 @@
1 -# Ferret Win32 Service Daemon install script  
2 -# created by Herryanto Siatono <herryanto@pluitsolutions.com>  
3 -#  
4 -# see doc/README.win32 for usage instructions  
5 -#  
6 -require 'optparse'  
7 -require 'win32/service'  
8 -include Win32  
9 -  
10 -module Ferret  
11 - # Parse and validate service command and options  
12 - class FerretServiceCommand  
13 - COMMANDS = ['install', 'remove', 'start', 'stop', 'help']  
14 - BANNER = "Usage: ruby script/ferret_service <command> [options]"  
15 -  
16 - attr_reader :options, :command  
17 -  
18 - def initialize  
19 - @options = {}  
20 - end  
21 -  
22 - def valid_command?  
23 - COMMANDS.include?@command  
24 - end  
25 -  
26 - def valid_options?  
27 - @options[:name] and !@options[:name].empty?  
28 - end  
29 -  
30 - def print_command_list  
31 - puts BANNER  
32 - puts "\nAvailable commands:\n"  
33 - puts COMMANDS.map {|cmd| " - #{cmd}\n"}  
34 - puts "\nUse option -h for each command to help."  
35 - exit  
36 - end  
37 -  
38 - def validate_options  
39 - errors = []  
40 - errors << "Service name is required." unless @options[:name]  
41 -  
42 - if (errors.size > 0)  
43 - errors << "Error found. Use: 'ruby script/ferret_service #{@command} -h' for to get help."  
44 - puts errors.join("\n")  
45 - exit  
46 - end  
47 - end  
48 -  
49 - def run(args)  
50 - @command = args.shift  
51 - @command = @command.dup.downcase if @command  
52 -  
53 - # validate command and options  
54 - print_command_list unless valid_command? or @command == 'help'  
55 -  
56 - opts_parser = create_options_parser  
57 - begin  
58 - opts_parser.parse!(args)  
59 - rescue OptionParser::ParseError => e  
60 - puts e  
61 - puts opts_parser  
62 - end  
63 -  
64 - # validate required options  
65 - validate_options  
66 - end  
67 -  
68 - def create_options_parser  
69 - opts_parser = OptionParser.new  
70 - opts_parser.banner = BANNER  
71 - opts_parser.on("-n", "--name=NAME", "Service name") {|name| @options[:name] = name }  
72 - opts_parser.on_tail("-t", "--trace", "Display stack trace when exception thrown") { @options[:trace] = true }  
73 - opts_parser.on_tail("-h", "--help", "Show this help message") { puts opts_parser; exit }  
74 -  
75 - if ['install'].include?@command  
76 - opts_parser.on("-d", "--display=NAME", "Service display name") {|name| @options[:display] = name }  
77 -  
78 - opts_parser.on("-l", "--log FILE", "Service log file") {|file| @options[:log] = file }  
79 - opts_parser.on("-e", "--environment ENV ", "Rails environment") { |env|  
80 - @options[:environment] = env  
81 - ENV['RAILS_ENV'] = env  
82 - }  
83 - end  
84 - opts_parser  
85 - end  
86 - end  
87 -  
88 - # Install, Remove, Start and Stop Ferret DRb server Win32 service  
89 - class FerretService  
90 - FERRET_DAEMON = 'ferret_daemon'  
91 -  
92 - def initialize  
93 - end  
94 -  
95 - def install  
96 - svc = Service.new  
97 -  
98 - begin  
99 - if Service.exists?(@options[:name])  
100 - puts "Service name '#{@options[:name]}' already exists."  
101 - return  
102 - end  
103 -  
104 - svc.create_service do |s|  
105 - s.service_name = @options[:name]  
106 - s.display_name = @options[:display]  
107 - s.binary_path_name = binary_path_name  
108 - s.dependencies = []  
109 - end  
110 -  
111 - svc.close  
112 - puts "'#{@options[:name]}' service installed."  
113 - rescue => e  
114 - handle_error(e)  
115 - end  
116 - end  
117 -  
118 - def remove  
119 - begin  
120 - Service.stop(@options[:name])  
121 - rescue  
122 - end  
123 -  
124 - begin  
125 - Service.delete(@options[:name])  
126 - puts "'#{@options[:name]}' service removed."  
127 - rescue => e  
128 - handle_error(e)  
129 - end  
130 - end  
131 -  
132 - def start  
133 - begin  
134 - Service.start(@options[:name])  
135 - puts "'#{@options[:name]}' successfully started."  
136 - rescue => e  
137 - handle_error(e)  
138 - end  
139 - end  
140 -  
141 - def stop  
142 - begin  
143 - Service.stop(@options[:name])  
144 - puts "'#{@options[:name]}' successfully stopped.\n"  
145 - rescue => e  
146 - handle_error(e)  
147 - end  
148 - end  
149 -  
150 - def run(args)  
151 - svc_cmd = FerretServiceCommand.new  
152 - svc_cmd.run(args)  
153 - @options = svc_cmd.options  
154 - self.send(svc_cmd.command.to_sym)  
155 - end  
156 -  
157 - protected  
158 - def handle_error(e)  
159 - if @options[:trace]  
160 - raise e  
161 - else  
162 - puts e  
163 - end  
164 - end  
165 -  
166 - def binary_path_name  
167 - path = ""  
168 - path << "#{ENV['RUBY_HOME']}/bin/" if ENV['RUBY_HOME']  
169 - path << "ruby.exe "  
170 - path << File.expand_path("script/" + FERRET_DAEMON)  
171 - path << " -e #{@options[:environment]} " if @options[:environment]  
172 - path << " -l #{@options[:log]} " if @options[:log]  
173 - path  
174 - end  
175 - end  
176 -end  
177 -  
178 -Ferret::FerretService.new.run(ARGV)  
vendor/plugins/acts_as_ferret/tasks/ferret.rake
@@ -1,24 +0,0 @@ @@ -1,24 +0,0 @@
1 -namespace :ferret do  
2 -  
3 - # Rebuild index task. Declare the indexes to be rebuilt with the INDEXES  
4 - # environment variable:  
5 - #  
6 - # INDEXES="my_model shared" rake ferret:rebuild  
7 - desc "Rebuild a Ferret index. Specify what model to rebuild with the MODEL environment variable."  
8 - task :rebuild do  
9 - require File.join(RAILS_ROOT, 'config', 'environment')  
10 -  
11 - indexes = ENV['INDEXES'].split  
12 - indexes.each do |index_name|  
13 - start = 1.minute.ago  
14 - ActsAsFerret::rebuild_index index_name  
15 - idx = ActsAsFerret::get_index index_name  
16 - # update records that have changed since the rebuild started  
17 - idx.index_definition[:registered_models].each do |m|  
18 - m.records_modified_since(start).each do |object|  
19 - object.ferret_update  
20 - end  
21 - end  
22 - end  
23 - end  
24 -end  
vendor/plugins/acts_as_solr_reloaded/.gitignore 0 → 100644
@@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
  1 +*.log
  2 +*.log
  3 +*_pid
  4 +coverage/*
  5 +coverage.data
  6 +solr/solr/data/*
  7 +.svn
  8 +test/db/*.db
  9 +test/log/*.log
  10 +pkg/*
  11 +*.sw?
  12 +.DS_Store
  13 +coverage
  14 +rdoc
  15 +pkg
  16 +acts_as_solr_reloaded-*.gem
  17 +tags
vendor/plugins/acts_as_solr_reloaded/LICENSE 0 → 100644
@@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
  1 +(The MIT License)
  2 +
  3 +Copyright © 2010
  4 +
  5 +Permission is hereby granted, free of charge, to any person obtaining
  6 +a copy of this software and associated documentation files (the
  7 +‘Software’), to deal in the Software without restriction, including
  8 +without limitation the rights to use, copy, modify, merge, publish,
  9 +distribute, sublicense, and/or sell copies of the Software, and to
  10 +permit persons to whom the Software is furnished to do so, subject to
  11 +the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be
  14 +included in all copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND,
  17 +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  18 +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  19 +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  20 +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  21 +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  22 +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
vendor/plugins/acts_as_solr_reloaded/README.markdown 0 → 100644
@@ -0,0 +1,64 @@ @@ -0,0 +1,64 @@
  1 +Description
  2 +======
  3 +This plugin adds full text search capabilities and many other nifty features from Apache's [Solr](http://lucene.apache.org/solr/) to any Rails model.
  4 +It was based on the first draft by Erik Hatcher.
  5 +
  6 +This plugin is intended for use in old versions of Rails. For newer versions, I strongly advice using Sunspot!
  7 +Nevertheless, this plugin is used for Noosfero project in production. Any problem please open an issue.
  8 +
  9 +Installation
  10 +======
  11 +
  12 +Install as a plugin
  13 +
  14 + script/plugin install git://github.com/brauliobo/acts_as_solr_reloaded.git
  15 +
  16 +Download Solr 3.1
  17 +
  18 + rake solr:download
  19 +
  20 +Requirements
  21 +------
  22 +* Java Runtime Environment(JRE) 1.6 aka 6.0 or newer [http://www.java.com/en/download/index.jsp](http://www.java.com/en/download/index.jsp) (use default-jre for Debian like distribution)
  23 +* (Recommended) If you have libxml-ruby installed, make sure it's at least version 0.7
  24 +
  25 +Configuration
  26 +======
  27 +See config/solr.yml file.
  28 +
  29 +Basic Usage
  30 +======
  31 +<pre><code>
  32 +# Just include the line below to any of your ActiveRecord models:
  33 + acts_as_solr
  34 +
  35 +# Or if you want, you can specify only the fields that should be indexed:
  36 + acts_as_solr :fields => [:name, :author]
  37 +
  38 +# Then to find instances of your model, just do:
  39 + Model.search(query) #query is a string representing your query
  40 +
  41 +# Please see ActsAsSolr::ActsMethods for a complete info
  42 +
  43 +</code></pre>
  44 +
  45 +
  46 +`acts_as_solr` in your tests
  47 +======
  48 +To test code that uses `acts_as_solr` you must start a Solr server for the test environment. You can do that with `rake solr:start RAILS_ENV=test`
  49 +
  50 +However, if you would like to mock out Solr calls so that a Solr server is not needed (and your tests will run much faster), just add this to your `test_helper.rb` or similar:
  51 +
  52 +<pre><code>
  53 +class ActsAsSolr::Post
  54 + def self.execute(request)
  55 + true
  56 + end
  57 +end
  58 +</pre></code>
  59 +
  60 +([via](http://www.subelsky.com/2007/10/actsassolr-capistranhttpwwwbloggercomim.html#c1646308013209805416))
  61 +
  62 +Release Information
  63 +======
  64 +Released under the MIT license.
vendor/plugins/acts_as_solr_reloaded/README.rdoc 0 → 100644
@@ -0,0 +1,96 @@ @@ -0,0 +1,96 @@
  1 += DESCRIPTION
  2 +
  3 +This plugin adds full text search capabilities and many other nifty features from Apache's Solr[http://lucene.apache.org/solr/] to any Rails model, like:
  4 +
  5 +* faceting
  6 +* dynamic attributes
  7 +* integration with acts_as_taggable_on
  8 +* integration with will_paginate
  9 +* highlighting
  10 +* geolocation
  11 +* relevance
  12 +* suggest
  13 +
  14 +Watch this screencast for a short demo of the latests features:
  15 +
  16 +http://www.vimeo.com/8728276
  17 +
  18 +== INSTALLATION
  19 +
  20 + script/plugin install git://github.com/brauliobo/acts_as_solr_reloaded.git
  21 + rake solr:download
  22 +
  23 +== REQUIREMENTS
  24 +
  25 +* Java Runtime Environment(JRE) 1.5 aka 5.0 [http://www.java.com/en/download/index.jsp](http://www.java.com/en/download/index.jsp) (use default-jre for Debian like distribution)
  26 +* (Recommended) If you have libxml-ruby installed, make sure it's at least version 0.7
  27 +
  28 +== CONFIGURATION
  29 +
  30 +See config/solr.yml file.
  31 +
  32 +== USAGE
  33 +
  34 +Just include the line below to any of your ActiveRecord models:
  35 + acts_as_solr
  36 +
  37 +Or if you want, you can specify only the fields that should be indexed:
  38 + acts_as_solr :fields => [:name, :author]
  39 +
  40 +Then to find instances of your model, just do:
  41 + Model.search(query) #query is a string representing your query
  42 +
  43 +Case you want to use dynamic attributes or geolocalization, you can use this generators that setup the database:
  44 +
  45 + script/generate dynamic_attributes_migration
  46 + script/generate local_migration
  47 +
  48 +and then configure your model like this:
  49 +
  50 + acts_as_solr :dynamic_attributes => true,
  51 + :spatial => true
  52 +
  53 +If you want to integrate the model with acts_as_taggable_on, just add the option :taggable => true :
  54 +
  55 + acts_as_solr :taggable => true
  56 +
  57 +Please see ActsAsSolr::ActsMethods for a complete info
  58 +
  59 +== PAGINATION
  60 +
  61 +In your controller:
  62 +
  63 + @search = Product.search "beer", :page => 2, :per_page => 20
  64 +
  65 +And in your view:
  66 +
  67 + will_paginate @search
  68 +
  69 +== TESTING
  70 +
  71 +To test code that uses acts_as_solr_reloaded you must start a Solr server for the test environment and also start MongoDB.
  72 +
  73 +== LICENSE
  74 +
  75 +(The MIT License)
  76 +
  77 +Copyright © 2010
  78 +
  79 +Permission is hereby granted, free of charge, to any person obtaining
  80 +a copy of this software and associated documentation files (the
  81 +‘Software’), to deal in the Software without restriction, including
  82 +without limitation the rights to use, copy, modify, merge, publish,
  83 +distribute, sublicense, and/or sell copies of the Software, and to
  84 +permit persons to whom the Software is furnished to do so, subject to
  85 +the following conditions:
  86 +
  87 +The above copyright notice and this permission notice shall be
  88 +included in all copies or substantial portions of the Software.
  89 +
  90 +THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND,
  91 +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  92 +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  93 +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  94 +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  95 +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  96 +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
vendor/plugins/acts_as_solr_reloaded/Rakefile 0 → 100644
@@ -0,0 +1,71 @@ @@ -0,0 +1,71 @@
  1 +require 'rubygems'
  2 +require 'rake'
  3 +require 'rake/testtask'
  4 +require 'rake/rdoctask'
  5 +
  6 +Dir["#{File.dirname(__FILE__)}/lib/tasks/*.rake"].sort.each { |ext| load ext }
  7 +
  8 +desc "Default Task"
  9 +task :default => [:test]
  10 +
  11 +desc "Runs the unit tests"
  12 +task :test => "test:unit"
  13 +
  14 +namespace :test do
  15 + task :setup do
  16 + RAILS_ROOT = File.expand_path("#{File.dirname(__FILE__)}/test") unless defined? RAILS_ROOT
  17 + ENV['RAILS_ENV'] = "test"
  18 + ENV["ACTS_AS_SOLR_TEST"] = "true"
  19 + require File.expand_path("#{File.dirname(__FILE__)}/config/solr_environment")
  20 + puts "Using " + DB
  21 + %x(mysql -u#{MYSQL_USER} < #{File.dirname(__FILE__) + "/test/fixtures/db_definitions/mysql.sql"}) if DB == 'mysql'
  22 +
  23 + Rake::Task["test:migrate"].invoke
  24 + end
  25 +
  26 + desc 'Measures test coverage using rcov'
  27 + task :rcov => :setup do
  28 + rm_f "coverage"
  29 + rm_f "coverage.data"
  30 + rcov = "rcov --rails --aggregate coverage.data --text-summary -Ilib"
  31 +
  32 + system("#{rcov} --html #{Dir.glob('test/**/*_shoulda.rb').join(' ')}")
  33 + system("open coverage/index.html") if PLATFORM['darwin']
  34 + end
  35 +
  36 + desc 'Runs the functional tests, testing integration with Solr'
  37 + Rake::TestTask.new('functional' => :setup) do |t|
  38 + t.pattern = "test/functional/*_test.rb"
  39 + t.verbose = true
  40 + end
  41 +
  42 + desc "Unit tests"
  43 + Rake::TestTask.new(:unit) do |t|
  44 + t.libs << 'test/unit'
  45 + t.pattern = "test/unit/*_shoulda.rb"
  46 + t.verbose = true
  47 + end
  48 +end
  49 +
  50 +Rake::RDocTask.new do |rd|
  51 + rd.main = "README.rdoc"
  52 + rd.rdoc_dir = "rdoc"
  53 + rd.rdoc_files.exclude("lib/solr/**/*.rb", "lib/solr.rb")
  54 + rd.rdoc_files.include("README.rdoc", "lib/**/*.rb")
  55 +end
  56 +
  57 +begin
  58 + require 'jeweler'
  59 + Jeweler::Tasks.new do |s|
  60 + s.name = "acts_as_solr_reloaded"
  61 + s.summary = "This gem adds full text search capabilities and many other nifty features from Apache Solr to any Rails model."
  62 + s.email = "dc.rec1@gmail.com"
  63 + s.homepage = "http://github.com/dcrec1/acts_as_solr_reloaded"
  64 + s.description = "This gem adds full text search capabilities and many other nifty features from Apache Solr to any Rails model."
  65 + s.authors = ["Diego Carrion"]
  66 + s.files = FileList["[A-Z]*", "{bin,generators,config,lib,solr}/**/*"] +
  67 + FileList["test/**/*"].reject {|f| f.include?("test/log")}.reject {|f| f.include?("test/tmp")}
  68 + end
  69 +rescue LoadError
  70 + puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install jeweler"
  71 +end
vendor/plugins/acts_as_solr_reloaded/TESTING_THE_PLUGIN 0 → 100644
@@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
  1 +acts_as_solr comes with a quick and fast unit test suite, and with a longer-running
  2 +functional test suite, the latter testing the actual integration with Solr.
  3 +
  4 +The unit test suite is written using Shoulda, so make sure you have a recent version
  5 +installed.
  6 +
  7 +Running `rake test` or just `rake` will run both test suites. Use `rake test:unit` to
  8 +just run the unit test suite.
  9 +
  10 +== How to run functional tests for this plugin:
  11 +To run the acts_as_solr's plugin tests run the following steps:
  12 +
  13 +- create a MySQL database called "actsassolr_test" (if you want to use MySQL)
  14 +
  15 +- create a new Rails project, if needed (the plugin can only be tested from within a Rails project); move/checkout acts_as_solr into its vendor/plugins/, as usual
  16 +
  17 +- copy vendor/plugins/acts_as_solr_reloaded/config/solr.yml to config/ (the Rails config folder)
  18 +
  19 +- rake solr:start RAILS_ENV=test
  20 +
  21 +- rake test:functional (Accepts the following arguments: DB=sqlite|mysql and MYSQL_USER=user)
  22 +
  23 +== Troubleshooting:
  24 +If for some reason the tests don't run and you get MySQL errors, make sure you edit the MYSQL_USER entry under
  25 +config/environment.rb. It's recommended to create or use a MySQL user with no password.
vendor/plugins/acts_as_solr_reloaded/VERSION 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +1.6.0
0 \ No newline at end of file 2 \ No newline at end of file
vendor/plugins/acts_as_solr_reloaded/acts_as_solr_reloaded.gemspec 0 → 100644
@@ -0,0 +1,205 @@ @@ -0,0 +1,205 @@
  1 +# Generated by jeweler
  2 +# DO NOT EDIT THIS FILE DIRECTLY
  3 +# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
  4 +# -*- encoding: utf-8 -*-
  5 +
  6 +Gem::Specification.new do |s|
  7 + s.name = %q{acts_as_solr_reloaded}
  8 + s.version = "1.6.0"
  9 +
  10 + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
  11 + s.authors = ["Diego Carrion"]
  12 + s.date = %q{2011-03-20}
  13 + s.description = %q{This gem adds full text search capabilities and many other nifty features from Apache Solr to any Rails model.}
  14 + s.email = %q{dc.rec1@gmail.com}
  15 + s.extra_rdoc_files = [
  16 + "LICENSE",
  17 + "README.markdown",
  18 + "README.rdoc"
  19 + ]
  20 + s.files = [
  21 + "LICENSE",
  22 + "README.markdown",
  23 + "README.rdoc",
  24 + "Rakefile",
  25 + "TESTING_THE_PLUGIN",
  26 + "VERSION",
  27 + "config/solr.yml",
  28 + "config/solr_environment.rb",
  29 + "generators/dynamic_attributes_migration/dynamic_attributes_migration_generator.rb",
  30 + "generators/dynamic_attributes_migration/templates/migration.rb",
  31 + "generators/local_migration/local_migration_generator.rb",
  32 + "generators/local_migration/templates/migration.rb",
  33 + "lib/acts_as_solr.rb",
  34 + "lib/acts_as_solr/acts_methods.rb",
  35 + "lib/acts_as_solr/class_methods.rb",
  36 + "lib/acts_as_solr/common_methods.rb",
  37 + "lib/acts_as_solr/deprecation.rb",
  38 + "lib/acts_as_solr/dynamic_attribute.rb",
  39 + "lib/acts_as_solr/instance_methods.rb",
  40 + "lib/acts_as_solr/lazy_document.rb",
  41 + "lib/acts_as_solr/local.rb",
  42 + "lib/acts_as_solr/mongo_mapper.rb",
  43 + "lib/acts_as_solr/parser_methods.rb",
  44 + "lib/acts_as_solr/search_results.rb",
  45 + "lib/acts_as_solr/solr_fixtures.rb",
  46 + "lib/acts_as_solr/tasks.rb",
  47 + "lib/acts_as_solr_reloaded.rb",
  48 + "lib/solr.rb",
  49 + "lib/solr/connection.rb",
  50 + "lib/solr/document.rb",
  51 + "lib/solr/exception.rb",
  52 + "lib/solr/field.rb",
  53 + "lib/solr/importer.rb",
  54 + "lib/solr/importer/array_mapper.rb",
  55 + "lib/solr/importer/delimited_file_source.rb",
  56 + "lib/solr/importer/hpricot_mapper.rb",
  57 + "lib/solr/importer/mapper.rb",
  58 + "lib/solr/importer/solr_source.rb",
  59 + "lib/solr/importer/xpath_mapper.rb",
  60 + "lib/solr/indexer.rb",
  61 + "lib/solr/request.rb",
  62 + "lib/solr/request/add_document.rb",
  63 + "lib/solr/request/base.rb",
  64 + "lib/solr/request/commit.rb",
  65 + "lib/solr/request/delete.rb",
  66 + "lib/solr/request/dismax.rb",
  67 + "lib/solr/request/index_info.rb",
  68 + "lib/solr/request/modify_document.rb",
  69 + "lib/solr/request/optimize.rb",
  70 + "lib/solr/request/ping.rb",
  71 + "lib/solr/request/select.rb",
  72 + "lib/solr/request/spellcheck.rb",
  73 + "lib/solr/request/standard.rb",
  74 + "lib/solr/request/update.rb",
  75 + "lib/solr/response.rb",
  76 + "lib/solr/response/add_document.rb",
  77 + "lib/solr/response/base.rb",
  78 + "lib/solr/response/commit.rb",
  79 + "lib/solr/response/delete.rb",
  80 + "lib/solr/response/dismax.rb",
  81 + "lib/solr/response/index_info.rb",
  82 + "lib/solr/response/modify_document.rb",
  83 + "lib/solr/response/optimize.rb",
  84 + "lib/solr/response/ping.rb",
  85 + "lib/solr/response/ruby.rb",
  86 + "lib/solr/response/select.rb",
  87 + "lib/solr/response/spellcheck.rb",
  88 + "lib/solr/response/standard.rb",
  89 + "lib/solr/response/xml.rb",
  90 + "lib/solr/solrtasks.rb",
  91 + "lib/solr/util.rb",
  92 + "lib/solr/xml.rb",
  93 + "lib/tasks/database.rake",
  94 + "lib/tasks/solr.rake",
  95 + "lib/tasks/test.rake",
  96 + "test/config/solr.yml",
  97 + "test/db/connections/mysql/connection.rb",
  98 + "test/db/connections/sqlite/connection.rb",
  99 + "test/db/migrate/001_create_books.rb",
  100 + "test/db/migrate/002_create_movies.rb",
  101 + "test/db/migrate/003_create_categories.rb",
  102 + "test/db/migrate/004_create_electronics.rb",
  103 + "test/db/migrate/005_create_authors.rb",
  104 + "test/db/migrate/006_create_postings.rb",
  105 + "test/db/migrate/007_create_posts.rb",
  106 + "test/db/migrate/008_create_gadgets.rb",
  107 + "test/db/migrate/009_create_dynamic_attributes.rb",
  108 + "test/db/migrate/010_create_advertises.rb",
  109 + "test/db/migrate/011_create_locals.rb",
  110 + "test/db/test.db",
  111 + "test/fixtures/advertises.yml",
  112 + "test/fixtures/authors.yml",
  113 + "test/fixtures/books.yml",
  114 + "test/fixtures/categories.yml",
  115 + "test/fixtures/db_definitions/mysql.sql",
  116 + "test/fixtures/dynamic_attributes.yml",
  117 + "test/fixtures/electronics.yml",
  118 + "test/fixtures/locals.yml",
  119 + "test/fixtures/movies.yml",
  120 + "test/fixtures/postings.yml",
  121 + "test/functional/acts_as_solr_test.rb",
  122 + "test/functional/association_indexing_test.rb",
  123 + "test/functional/faceted_search_test.rb",
  124 + "test/functional/multi_solr_search_test.rb",
  125 + "test/models/advertise.rb",
  126 + "test/models/author.rb",
  127 + "test/models/book.rb",
  128 + "test/models/category.rb",
  129 + "test/models/document.rb",
  130 + "test/models/dynamic_attribute.rb",
  131 + "test/models/electronic.rb",
  132 + "test/models/gadget.rb",
  133 + "test/models/local.rb",
  134 + "test/models/movie.rb",
  135 + "test/models/novel.rb",
  136 + "test/models/post.rb",
  137 + "test/models/posting.rb",
  138 + "test/test_helper.rb",
  139 + "test/unit/acts_methods_shoulda.rb",
  140 + "test/unit/class_methods_shoulda.rb",
  141 + "test/unit/common_methods_shoulda.rb",
  142 + "test/unit/instance_methods_shoulda.rb",
  143 + "test/unit/lazy_document_shoulda.rb",
  144 + "test/unit/parser_instance.rb",
  145 + "test/unit/parser_methods_shoulda.rb",
  146 + "test/unit/solr_instance.rb",
  147 + "test/unit/test_helper.rb"
  148 + ]
  149 + s.homepage = %q{http://github.com/dcrec1/acts_as_solr_reloaded}
  150 + s.require_paths = ["lib"]
  151 + s.rubygems_version = %q{1.5.0}
  152 + s.summary = %q{This gem adds full text search capabilities and many other nifty features from Apache Solr to any Rails model.}
  153 + s.test_files = [
  154 + "test/db/connections/mysql/connection.rb",
  155 + "test/db/connections/sqlite/connection.rb",
  156 + "test/db/migrate/001_create_books.rb",
  157 + "test/db/migrate/002_create_movies.rb",
  158 + "test/db/migrate/003_create_categories.rb",
  159 + "test/db/migrate/004_create_electronics.rb",
  160 + "test/db/migrate/005_create_authors.rb",
  161 + "test/db/migrate/006_create_postings.rb",
  162 + "test/db/migrate/007_create_posts.rb",
  163 + "test/db/migrate/008_create_gadgets.rb",
  164 + "test/db/migrate/009_create_dynamic_attributes.rb",
  165 + "test/db/migrate/010_create_advertises.rb",
  166 + "test/db/migrate/011_create_locals.rb",
  167 + "test/functional/acts_as_solr_test.rb",
  168 + "test/functional/association_indexing_test.rb",
  169 + "test/functional/faceted_search_test.rb",
  170 + "test/functional/multi_solr_search_test.rb",
  171 + "test/models/advertise.rb",
  172 + "test/models/author.rb",
  173 + "test/models/book.rb",
  174 + "test/models/category.rb",
  175 + "test/models/document.rb",
  176 + "test/models/dynamic_attribute.rb",
  177 + "test/models/electronic.rb",
  178 + "test/models/gadget.rb",
  179 + "test/models/local.rb",
  180 + "test/models/movie.rb",
  181 + "test/models/novel.rb",
  182 + "test/models/post.rb",
  183 + "test/models/posting.rb",
  184 + "test/test_helper.rb",
  185 + "test/unit/acts_methods_shoulda.rb",
  186 + "test/unit/class_methods_shoulda.rb",
  187 + "test/unit/common_methods_shoulda.rb",
  188 + "test/unit/instance_methods_shoulda.rb",
  189 + "test/unit/lazy_document_shoulda.rb",
  190 + "test/unit/parser_instance.rb",
  191 + "test/unit/parser_methods_shoulda.rb",
  192 + "test/unit/solr_instance.rb",
  193 + "test/unit/test_helper.rb"
  194 + ]
  195 +
  196 + if s.respond_to? :specification_version then
  197 + s.specification_version = 3
  198 +
  199 + if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
  200 + else
  201 + end
  202 + else
  203 + end
  204 +end
  205 +
vendor/plugins/acts_as_solr_reloaded/config/solr.yml 0 → 100644
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
  1 +# Config file for the acts_as_solr_reloaded plugin.
  2 +#
  3 +# If you change the host or port number here, make sure you update
  4 +# them in your Solr config file
  5 +
  6 +development:
  7 + url: http://127.0.0.1:8982/solr
  8 +
  9 +test:
  10 + url: http://127.0.0.1:8981/solr
  11 +
  12 +production:
  13 + url: http://127.0.0.1:8983/solr
  14 + jvm_options: -server -d64 -Xmx1024M -Xms64M
0 \ No newline at end of file 15 \ No newline at end of file
vendor/plugins/acts_as_solr_reloaded/config/solr_environment.rb 0 → 100644
@@ -0,0 +1,43 @@ @@ -0,0 +1,43 @@
  1 +ENV['RAILS_ENV'] = (ENV['RAILS_ENV'] || 'development').dup
  2 +require "uri"
  3 +require "fileutils"
  4 +require "yaml"
  5 +dir = File.dirname(__FILE__)
  6 +SOLR_PATH = File.expand_path("#{dir}/../solr") unless defined? SOLR_PATH
  7 +
  8 +# RAILS_ROOT isn't defined yet, so figure it out.
  9 +unless defined? RAILS_ROOT
  10 + RAILS_ROOT = File.expand_path("#{File.dirname(__FILE__)}/../test")
  11 +end
  12 +unless defined? SOLR_LOGS_PATH
  13 + SOLR_LOGS_PATH = ENV["SOLR_LOGS_PATH"] || "#{RAILS_ROOT}/log"
  14 +end
  15 +unless defined? SOLR_PIDS_PATH
  16 + SOLR_PIDS_PATH = ENV["SOLR_PIDS_PATH"] || "#{RAILS_ROOT}/tmp/pids"
  17 +end
  18 +unless defined? SOLR_DATA_PATH
  19 + SOLR_DATA_PATH = ENV["SOLR_DATA_PATH"] || "#{RAILS_ROOT}/solr/#{ENV['RAILS_ENV']}"
  20 +end
  21 +unless defined? SOLR_CONFIG_PATH
  22 + SOLR_CONFIG_PATH = ENV["SOLR_CONFIG_PATH"] || "#{SOLR_PATH}/solr"
  23 +end
  24 +unless defined? SOLR_PID_FILE
  25 + SOLR_PID_FILE="#{SOLR_PIDS_PATH}/solr.#{ENV['RAILS_ENV']}.pid"
  26 +end
  27 +
  28 +unless defined? SOLR_PORT
  29 + config = YAML::load_file(RAILS_ROOT+'/config/solr.yml')
  30 + raise("No solr environment defined for RAILS_ENV the #{ENV['RAILS_ENV'].inspect}") unless config[ENV['RAILS_ENV']]
  31 +
  32 + SOLR_HOST = ENV['HOST'] || URI.parse(config[ENV['RAILS_ENV']]['url']).host
  33 + SOLR_PORT = ENV['PORT'] || URI.parse(config[ENV['RAILS_ENV']]['url']).port
  34 +end
  35 +
  36 +SOLR_JVM_OPTIONS = config[ENV['RAILS_ENV']]['jvm_options'] unless defined? SOLR_JVM_OPTIONS
  37 +
  38 +if ENV["ACTS_AS_SOLR_TEST"]
  39 + require "activerecord"
  40 + DB = (ENV['DB'] ? ENV['DB'] : 'sqlite') unless defined?(DB)
  41 + MYSQL_USER = (ENV['MYSQL_USER'].nil? ? 'root' : ENV['MYSQL_USER']) unless defined? MYSQL_USER
  42 + require File.join(File.dirname(File.expand_path(__FILE__)), '..', 'test', 'db', 'connections', DB, 'connection.rb')
  43 +end
vendor/plugins/acts_as_solr_reloaded/generators/dynamic_attributes_migration/dynamic_attributes_migration_generator.rb 0 → 100644
@@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
  1 +class DynamicAttributesMigrationGenerator < Rails::Generator::Base
  2 + def manifest
  3 + record do |m|
  4 + m.migration_template 'migration.rb', 'db/migrate', :migration_file_name => "dynamic_attributes_migration"
  5 + end
  6 + end
  7 +end
0 \ No newline at end of file 8 \ No newline at end of file
vendor/plugins/acts_as_solr_reloaded/generators/dynamic_attributes_migration/templates/migration.rb 0 → 100644
@@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
  1 +class DynamicAttributesMigration < ActiveRecord::Migration
  2 + def self.up
  3 + create_table :dynamic_attributes do |t|
  4 + t.integer :dynamicable_id
  5 + t.string :dynamicable_type
  6 + t.string :name
  7 + t.text :value
  8 + t.timestamps
  9 + end
  10 + add_index :dynamic_attributes, [:dynamicable_id, :dynamicable_type, :name], :unique => true, :name => 'da_pk'
  11 + end
  12 +
  13 + def self.down
  14 + remove_index 'da_pk'
  15 + drop_table :dynamic_attributes
  16 + end
  17 +end