spree_sphinx_search 0.30.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,28 @@
1
+ Sphinx Search
2
+ =============
3
+
4
+ ### Installation
5
+
6
+ 1. Install Sphinx 0.9.9
7
+ 1. Install Aspell 0.6 and at least one Aspell dictionary
8
+ Mac:
9
+ sudo port install aspell aspell-dict-en
10
+
11
+ Ubuntu:
12
+ sudo apt-get install aspell libaspell-dev aspell-en
13
+
14
+ 1. `script/extension install git://github.com/pronix/spree-sphinx-search.git`
15
+ 1. Copy config/sphinx.yml to RAILS_ROOT/config/sphinx.yml
16
+
17
+ **NOTE:** This extension works only with Spree 0.30 and higher.
18
+
19
+ ### Usage
20
+
21
+ To perform the indexing:
22
+
23
+ rake ts:index
24
+
25
+ To start Sphinx for development:
26
+
27
+ cd RAILS_ROOT/config
28
+ sphinxd --config development.sphinx.conf
@@ -0,0 +1,137 @@
1
+ # I think this is the one that should be moved to the extension Rakefile template
2
+
3
+ # In rails 1.2, plugins aren't available in the path until they're loaded.
4
+ # Check to see if the rspec plugin is installed first and require
5
+ # it if it is. If not, use the gem version.
6
+
7
+ # Determine where the RSpec plugin is by loading the boot
8
+ unless defined? SPREE_ROOT
9
+ ENV["RAILS_ENV"] = "test"
10
+ case
11
+ when ENV["SPREE_ENV_FILE"]
12
+ require File.dirname(ENV["SPREE_ENV_FILE"]) + "/boot"
13
+ when File.dirname(__FILE__) =~ %r{vendor/SPREE/vendor/extensions}
14
+ require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../../")}/config/boot"
15
+ else
16
+ require "#{File.expand_path(File.dirname(__FILE__) + "/../../../")}/config/boot"
17
+ end
18
+ end
19
+
20
+ require 'rake'
21
+ require 'rake/rdoctask'
22
+ require 'rake/testtask'
23
+
24
+ rspec_base = File.expand_path(SPREE_ROOT + '/vendor/plugins/rspec/lib')
25
+ $LOAD_PATH.unshift(rspec_base) if File.exist?(rspec_base)
26
+ require 'spec/rake/spectask'
27
+ # require 'spec/translator'
28
+
29
+ # Cleanup the SPREE_ROOT constant so specs will load the environment
30
+ Object.send(:remove_const, :SPREE_ROOT)
31
+
32
+ extension_root = File.expand_path(File.dirname(__FILE__))
33
+
34
+ task :default => :spec
35
+ task :stats => "spec:statsetup"
36
+
37
+ desc "Run all specs in spec directory"
38
+ Spec::Rake::SpecTask.new(:spec) do |t|
39
+ t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
40
+ t.spec_files = FileList["#{extension_root}/spec/**/*_spec.rb"]
41
+ end
42
+
43
+ namespace :spec do
44
+ desc "Run all specs in spec directory with RCov"
45
+ Spec::Rake::SpecTask.new(:rcov) do |t|
46
+ t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
47
+ t.spec_files = FileList['spec/**/*_spec.rb']
48
+ t.rcov = true
49
+ t.rcov_opts = ['--exclude', 'spec', '--rails']
50
+ end
51
+
52
+ desc "Print Specdoc for all specs"
53
+ Spec::Rake::SpecTask.new(:doc) do |t|
54
+ t.spec_opts = ["--format", "specdoc", "--dry-run"]
55
+ t.spec_files = FileList['spec/**/*_spec.rb']
56
+ end
57
+
58
+ [:models, :controllers, :views, :helpers].each do |sub|
59
+ desc "Run the specs under spec/#{sub}"
60
+ Spec::Rake::SpecTask.new(sub) do |t|
61
+ t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
62
+ t.spec_files = FileList["spec/#{sub}/**/*_spec.rb"]
63
+ end
64
+ end
65
+
66
+ # Hopefully no one has written their extensions in pre-0.9 style
67
+ # desc "Translate specs from pre-0.9 to 0.9 style"
68
+ # task :translate do
69
+ # translator = ::Spec::Translator.new
70
+ # dir = RAILS_ROOT + '/spec'
71
+ # translator.translate(dir, dir)
72
+ # end
73
+
74
+ # Setup specs for stats
75
+ task :statsetup do
76
+ require 'code_statistics'
77
+ ::STATS_DIRECTORIES << %w(Model\ specs spec/models)
78
+ ::STATS_DIRECTORIES << %w(View\ specs spec/views)
79
+ ::STATS_DIRECTORIES << %w(Controller\ specs spec/controllers)
80
+ ::STATS_DIRECTORIES << %w(Helper\ specs spec/views)
81
+ ::CodeStatistics::TEST_TYPES << "Model specs"
82
+ ::CodeStatistics::TEST_TYPES << "View specs"
83
+ ::CodeStatistics::TEST_TYPES << "Controller specs"
84
+ ::CodeStatistics::TEST_TYPES << "Helper specs"
85
+ ::STATS_DIRECTORIES.delete_if {|a| a[0] =~ /test/}
86
+ end
87
+
88
+ namespace :db do
89
+ namespace :fixtures do
90
+ desc "Load fixtures (from spec/fixtures) into the current environment's database. Load specific fixtures using FIXTURES=x,y"
91
+ task :load => :environment do
92
+ require 'active_record/fixtures'
93
+ ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
94
+ (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir.glob(File.join(RAILS_ROOT, 'spec', 'fixtures', '*.{yml,csv}'))).each do |fixture_file|
95
+ Fixtures.create_fixtures('spec/fixtures', File.basename(fixture_file, '.*'))
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+
102
+ desc 'Generate documentation for the sphinx_search extension.'
103
+ Rake::RDocTask.new(:rdoc) do |rdoc|
104
+ rdoc.rdoc_dir = 'rdoc'
105
+ rdoc.title = 'SphinxSearchExtension'
106
+ rdoc.options << '--line-numbers' << '--inline-source'
107
+ rdoc.rdoc_files.include('README')
108
+ rdoc.rdoc_files.include('lib/**/*.rb')
109
+ end
110
+
111
+ # For extensions that are in transition
112
+ desc 'Test the sphinx_search extension.'
113
+ Rake::TestTask.new(:test) do |t|
114
+ t.libs << 'lib'
115
+ t.pattern = 'test/**/*_test.rb'
116
+ t.verbose = true
117
+ end
118
+
119
+ namespace :test do
120
+ desc 'Functional test the sphinx_search extension.'
121
+ Rake::TestTask.new(:functionals) do |t|
122
+ t.libs << 'lib'
123
+ t.pattern = 'test/functional/*_test.rb'
124
+ t.verbose = true
125
+ end
126
+
127
+ desc 'Unit test the sphinx_search extension.'
128
+ Rake::TestTask.new(:units) do |t|
129
+ t.libs << 'lib'
130
+ t.pattern = 'test/unit/*_test.rb'
131
+ t.verbose = true
132
+ end
133
+ end
134
+
135
+
136
+ # Load any custom rakefiles for extension
137
+ Dir[File.dirname(__FILE__) + '/tasks/*.rake'].sort.each { |f| require f }
@@ -0,0 +1,15 @@
1
+ ProductsController.class_eval do
2
+ helper :sphinx
3
+ helper_method :option_values
4
+ private
5
+ def option_values(ids = [])
6
+ @option_values ||= {}
7
+ return @option_values if ids.empty?
8
+ option_values_for_ids = {}
9
+ OptionValue.find(ids).each do |ov|
10
+ option_values_for_ids[ov.id] = ov.presentation
11
+ end
12
+ @option_values.merge!(option_values_for_ids)
13
+ return option_values_for_ids
14
+ end
15
+ end
@@ -0,0 +1,8 @@
1
+ module SphinxHelper
2
+ def link_to_facet(name, value, count, link_name = "#{value} (#{count})")
3
+ facets_hash = params[:facets]
4
+ facets_hash = {} unless facets_hash.is_a?(Hash)
5
+ facets_hash = facets_hash.merge({name => [value, facets_hash[name]].join(', ')})
6
+ link_to(link_name, :overwrite_params => params.merge({:facets => facets_hash}))
7
+ end
8
+ end
@@ -0,0 +1,36 @@
1
+ Product.class_eval do
2
+
3
+ define_index do
4
+ is_active_sql = "(products.deleted_at IS NULL AND products.available_on <= NOW() #{'AND (products.count_on_hand > 0)' unless Spree::Config[:allow_backorders]} )"
5
+ option_sql = lambda do |option_name|
6
+ sql = <<-eos
7
+ SELECT DISTINCT p.id, ov.id
8
+ FROM option_values AS ov
9
+ LEFT JOIN option_types AS ot ON (ov.option_type_id = ot.id)
10
+ LEFT JOIN option_values_variants AS ovv ON (ovv.option_value_id = ov.id)
11
+ LEFT JOIN variants AS v ON (ovv.variant_id = v.id)
12
+ LEFT JOIN products AS p ON (v.product_id = p.id)
13
+ WHERE (ot.name = '#{option_name}' AND p.id>=$start AND p.id<=$end);
14
+ eos
15
+ sql.gsub("\n", ' ').gsub(' ', '')
16
+ end
17
+
18
+ brand_sql = option_sql.call('brand')
19
+ color_sql = option_sql.call('color')
20
+ size_sql = option_sql.call('size')
21
+
22
+ set_property :sql_range_step => 1000000
23
+ indexes :name
24
+ indexes :description
25
+ indexes :meta_description
26
+ indexes :meta_keywords
27
+ indexes taxons.name, :as => :taxon, :facet => true
28
+ has taxons(:id), :as => :taxon_ids
29
+ group_by :deleted_at
30
+ group_by :available_on
31
+ has is_active_sql, :as => :is_active, :type => :boolean
32
+ has brand_sql , :as => :brand_option, :source => :ranged_query, :type => :multi, :facet => true
33
+ # has color_sql , :as => :color_option, :source => :ranged_query, :type => :multi, :facet => true
34
+ # has size_sql , :as => :size_option, :source => :ranged_query, :type => :multi, :facet => true
35
+ end
36
+ end
@@ -0,0 +1,23 @@
1
+ <%
2
+ facets = @searcher.facets || []
3
+ price_ranges = YAML::load(Spree::Config[:product_price_ranges])
4
+ for facet in facets
5
+ options = facet.options
6
+ options = options.sort{|x,y| y.count <=> x.count} unless facet.name == :price_range
7
+ unless options.empty? %>
8
+ <h4><%= t "#{facet.name}_facet" %></h4>
9
+ <ul><%
10
+ for option in options %>
11
+ <li>
12
+ <% if facet.name == :price_range -%>
13
+ <%= link_to_facet(facet.name, option.name, option.count,
14
+ "#{price_ranges[option.name.to_i]} (#{option.count})") -%>
15
+ <% else -%>
16
+ <%= link_to_facet(facet.name, option.name, option.count) -%>
17
+ <% end -%>
18
+ </li><%
19
+ end %>
20
+ </ul><%
21
+ end
22
+ end
23
+ %>
@@ -0,0 +1,6 @@
1
+ <% if suggestion = @searcher.suggest %>
2
+ <p>
3
+ <%= t(:did_you_mean, :default => "Did you mean") %>
4
+ <%= link_to h(suggestion), :overwrite_params => { :keywords => suggestion } %>?
5
+ </p>
6
+ <% end %>
@@ -0,0 +1,6 @@
1
+ en-US:
2
+ taxon_facet: "Category"
3
+ price_range_facet: "Price"
4
+ brand_option_facet: "Brand"
5
+ color_option_facet: "Color"
6
+ size_option_facet: "Size"
@@ -0,0 +1,4 @@
1
+ ru-RU:
2
+ taxon_facet: "Категория"
3
+ price_range_facet: "Цена"
4
+ did_you_mean: "Вы имели в виду"
@@ -0,0 +1,5 @@
1
+ # Put your extension routes here.
2
+
3
+ # map.namespace :admin do |admin|
4
+ # admin.resources :whatever
5
+ # end
@@ -0,0 +1,15 @@
1
+ development:
2
+ sql_range_step: 10000000
3
+ enable_star: 1
4
+ min_infix_len: 1
5
+ morphology: stem_en
6
+ mem_limit: 128M
7
+ max_matches: 25000
8
+
9
+ production:
10
+ sql_range_step: 10000000
11
+ enable_star: 1
12
+ min_infix_len: 1
13
+ morphology: stem_en
14
+ mem_limit: 128M
15
+ max_matches: 25000
@@ -0,0 +1,101 @@
1
+ module Spree::Search
2
+ class ThinkingSphinx < Spree::Search::Base
3
+ protected
4
+ # method should return AR::Relations with conditions {:conditions=> "..."} for Product model
5
+ def get_products_conditions_for(base_scope,query)
6
+ search_options = {:page => page, :per_page => per_page}
7
+ if order_by_price
8
+ search_options.merge!(:order => :price,
9
+ :sort_mode => (order_by_price == 'descend' ? :desc : :asc))
10
+ end
11
+ if facets_hash
12
+ search_options.merge!(:conditions => facets_hash)
13
+ end
14
+ with_opts = {:is_active => 1}
15
+ if taxon
16
+ taxon_ids = taxon.self_and_descendants.map(&:id)
17
+ with_opts.merge!(:taxon_ids => taxon_ids)
18
+ end
19
+ search_options.merge!(:with => with_opts)
20
+ facets = Product.facets(query, search_options)
21
+ products = facets.for
22
+
23
+ @properties[:products] = products
24
+ @properties[:facets] = parse_facets_hash(facets)
25
+ @properties[:suggest] = nil if @properties[:suggest] == query
26
+
27
+ Product.where("id IN (?)", products.map(&:id))
28
+ end
29
+
30
+ def prepare(params)
31
+ @properties[:facets_hash] = params[:facets] || {}
32
+ @properties[:taxon] = params[:taxon].blank? ? nil : Taxon.find(params[:taxon])
33
+ @properties[:keywords] = params[:keywords]
34
+ per_page = params[:per_page].to_i
35
+ @properties[:per_page] = per_page > 0 ? per_page : Spree::Config[:products_per_page]
36
+ @properties[:page] = (params[:page].to_i <= 0) ? 1 : params[:page].to_i
37
+ @properties[:manage_pagination] = true
38
+ @properties[:order_by_price] = params[:order_by_price]
39
+ if !params[:order_by_price].blank?
40
+ @product_group = ProductGroup.new.from_route([params[:order_by_price]+"_by_master_price"])
41
+ elsif params[:product_group_name]
42
+ @cached_product_group = ProductGroup.find_by_permalink(params[:product_group_name])
43
+ @product_group = ProductGroup.new
44
+ elsif params[:product_group_query]
45
+ @product_group = ProductGroup.new.from_route(params[:product_group_query].split("/"))
46
+ else
47
+ @product_group = ProductGroup.new
48
+ end
49
+ @product_group = @product_group.from_search(params[:search]) if params[:search]
50
+ end
51
+
52
+ private
53
+
54
+ # method should return new scope based on base_scope
55
+ def parse_facets_hash(facets_hash = {})
56
+ facets = []
57
+ price_ranges = YAML::load(Spree::Config[:product_price_ranges])
58
+ facets_hash.each do |name, options|
59
+ next if options.size <= 1
60
+ facet = Facet.new(name)
61
+ options.each do |value, count|
62
+ next if value.blank?
63
+ facet.options << FacetOption.new(value, count)
64
+ end
65
+ facets << facet
66
+ end
67
+ facets
68
+ end
69
+ end
70
+
71
+ class Facet
72
+ attr_accessor :options
73
+ attr_accessor :name
74
+ def initialize(name, options = [])
75
+ self.name = name
76
+ self.options = options
77
+ end
78
+
79
+ def self.translate?(property)
80
+ return true if property.is_a?(ThinkingSphinx::Field)
81
+
82
+ case property.type
83
+ when :string
84
+ true
85
+ when :integer, :boolean, :datetime, :float
86
+ false
87
+ when :multi
88
+ false # !property.all_ints?
89
+ end
90
+ end
91
+ end
92
+
93
+ class FacetOption
94
+ attr_accessor :name
95
+ attr_accessor :count
96
+ def initialize(name, count)
97
+ self.name = name
98
+ self.count = count
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,23 @@
1
+ require 'spree_core'
2
+ require 'spree_sphinx_search_hooks'
3
+ require 'thinking-sphinx'
4
+
5
+ module SpreeSphinxSearch
6
+ class Engine < Rails::Engine
7
+ def self.activate
8
+ ENV['RAILS_ENV'] = Rails.env
9
+
10
+ if Spree::Config.instance
11
+ Spree::Config.searcher_class = Spree::Search::ThinkingSphinx
12
+ Spree::Config.set(:product_price_ranges =>
13
+ ["Under $25", "$25 to $50", "$50 to $100", "$100 to $200", "$200 and above"])
14
+ end
15
+
16
+ Dir.glob(File.join(File.dirname(__FILE__), "../app/**/*_decorator*.rb")) do |c|
17
+ Rails.env == "production" ? require(c) : load(c)
18
+ end
19
+ end
20
+ config.to_prepare &method(:activate).to_proc
21
+ config.autoload_paths += %W(#{config.root}/lib)
22
+ end
23
+ end
@@ -0,0 +1,4 @@
1
+ class SphinxSearchHooks < Spree::ThemeSupport::HookListener
2
+ insert_before :search_results, 'products/facets'
3
+ insert_before :search_results, 'products/suggestion'
4
+ end
@@ -0,0 +1,5 @@
1
+ begin
2
+ require 'thinking_sphinx/tasks'
3
+ rescue LoadError
4
+ puts "WARNING: thinking-sphinx gem appears to be unavailable. Please install with rake gems:install."
5
+ end
@@ -0,0 +1,6 @@
1
+ --colour
2
+ --format
3
+ progress
4
+ --loadby
5
+ mtime
6
+ --reverse
@@ -0,0 +1,37 @@
1
+ unless defined? SPREE_ROOT
2
+ ENV["RAILS_ENV"] = "test"
3
+ case
4
+ when ENV["SPREE_ENV_FILE"]
5
+ require ENV["SPREE_ENV_FILE"]
6
+ when File.dirname(__FILE__) =~ %r{vendor/SPREE/vendor/extensions}
7
+ require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../../../")}/config/environment"
8
+ else
9
+ require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../")}/config/environment"
10
+ end
11
+ end
12
+ require "#{SPREE_ROOT}/spec/spec_helper"
13
+
14
+ if File.directory?(File.dirname(__FILE__) + "/scenarios")
15
+ Scenario.load_paths.unshift File.dirname(__FILE__) + "/scenarios"
16
+ end
17
+ if File.directory?(File.dirname(__FILE__) + "/matchers")
18
+ Dir[File.dirname(__FILE__) + "/matchers/*.rb"].each {|file| require file }
19
+ end
20
+
21
+ Spec::Runner.configure do |config|
22
+ # config.use_transactional_fixtures = true
23
+ # config.use_instantiated_fixtures = false
24
+ # config.fixture_path = RAILS_ROOT + '/spec/fixtures'
25
+
26
+ # You can declare fixtures for each behaviour like this:
27
+ # describe "...." do
28
+ # fixtures :table_a, :table_b
29
+ #
30
+ # Alternatively, if you prefer to declare them only once, you can
31
+ # do so here, like so ...
32
+ #
33
+ # config.global_fixtures = :table_a, :table_b
34
+ #
35
+ # If you declare global fixtures, be aware that they will be declared
36
+ # for all of your examples, even those that don't use them.
37
+ end
@@ -0,0 +1,29 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{spree_sphinx_search}
8
+ s.version = "0.30.0.beta1"
9
+ s.authors = ["Roman Smirnov"]
10
+ s.description = "Search for Spree via Sphinx."
11
+ s.summary = "Search for Spree via Sphinx."
12
+ s.required_ruby_version = '>= 1.8.7'
13
+
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.homepage = %q{http://github.com/romul/spree-sphinx-search}
18
+ s.rdoc_options = ["--charset=UTF-8"]
19
+ s.require_paths = ["lib"]
20
+
21
+
22
+ if s.respond_to? :specification_version then
23
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
24
+ s.add_dependency(%q<spree_core>, [">= 0.30.0"])
25
+ s.add_dependency(%q<thinking-sphinx>, [">= 2.0.2.1"])
26
+ s.add_dependency(%q<thinking-sphinx-raspell>,[">= 1.1.0"])
27
+ end
28
+ end
29
+
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spree_sphinx_search
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: true
5
+ segments:
6
+ - 0
7
+ - 30
8
+ - 0
9
+ - beta1
10
+ version: 0.30.0.beta1
11
+ platform: ruby
12
+ authors:
13
+ - Roman Smirnov
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-02-09 00:00:00 +03:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: spree_core
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ - 30
31
+ - 0
32
+ version: 0.30.0
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: thinking-sphinx
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ segments:
43
+ - 2
44
+ - 0
45
+ - 2
46
+ - 1
47
+ version: 2.0.2.1
48
+ type: :runtime
49
+ version_requirements: *id002
50
+ - !ruby/object:Gem::Dependency
51
+ name: thinking-sphinx-raspell
52
+ prerelease: false
53
+ requirement: &id003 !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ segments:
58
+ - 1
59
+ - 1
60
+ - 0
61
+ version: 1.1.0
62
+ type: :runtime
63
+ version_requirements: *id003
64
+ description: Search for Spree via Sphinx.
65
+ email:
66
+ executables: []
67
+
68
+ extensions: []
69
+
70
+ extra_rdoc_files: []
71
+
72
+ files:
73
+ - README.markdown
74
+ - Rakefile
75
+ - app/controllers/products_controller_decorator.rb
76
+ - app/helpers/sphinx_helper.rb
77
+ - app/models/product_decorator.rb
78
+ - app/views/products/_facets.html.erb
79
+ - app/views/products/_suggestion.html.erb
80
+ - config/locales/en-US.yml
81
+ - config/locales/ru-RU.yml
82
+ - config/routes.rb
83
+ - config/sphinx.yml
84
+ - lib/spree/search/thinking_sphinx.rb
85
+ - lib/spree_sphinx_search.rb
86
+ - lib/spree_sphinx_search_hooks.rb
87
+ - lib/tasks/thinking_sphinx_tasks.rake
88
+ - spec/spec.opts
89
+ - spec/spec_helper.rb
90
+ - spree_sphinx_search.gemspec
91
+ has_rdoc: true
92
+ homepage: http://github.com/romul/spree-sphinx-search
93
+ licenses: []
94
+
95
+ post_install_message:
96
+ rdoc_options:
97
+ - --charset=UTF-8
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ segments:
105
+ - 1
106
+ - 8
107
+ - 7
108
+ version: 1.8.7
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">"
112
+ - !ruby/object:Gem::Version
113
+ segments:
114
+ - 1
115
+ - 3
116
+ - 1
117
+ version: 1.3.1
118
+ requirements: []
119
+
120
+ rubyforge_project:
121
+ rubygems_version: 1.3.6
122
+ signing_key:
123
+ specification_version: 3
124
+ summary: Search for Spree via Sphinx.
125
+ test_files: []
126
+