outoftime-sunspot 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. data/History.txt +7 -0
  2. data/Manifest.txt +104 -0
  3. data/PostInstall.txt +7 -0
  4. data/README.rdoc +115 -0
  5. data/Rakefile +27 -0
  6. data/config/hoe.rb +74 -0
  7. data/config/requirements.rb +15 -0
  8. data/lib/light_config.rb +40 -0
  9. data/lib/sunspot/adapters.rb +54 -0
  10. data/lib/sunspot/conditions.rb +50 -0
  11. data/lib/sunspot/conditions_builder.rb +37 -0
  12. data/lib/sunspot/configuration.rb +17 -0
  13. data/lib/sunspot/field.rb +108 -0
  14. data/lib/sunspot/field_builder.rb +37 -0
  15. data/lib/sunspot/indexer.rb +65 -0
  16. data/lib/sunspot/query.rb +115 -0
  17. data/lib/sunspot/query_builder.rb +30 -0
  18. data/lib/sunspot/restriction.rb +72 -0
  19. data/lib/sunspot/scope_builder.rb +33 -0
  20. data/lib/sunspot/search.rb +83 -0
  21. data/lib/sunspot/session.rb +43 -0
  22. data/lib/sunspot/type.rb +62 -0
  23. data/lib/sunspot/util.rb +13 -0
  24. data/lib/sunspot/version.rb +10 -0
  25. data/lib/sunspot.rb +50 -0
  26. data/setup.rb +1585 -0
  27. data/solr/README.txt +36 -0
  28. data/solr/etc/jetty.xml +206 -0
  29. data/solr/etc/webdefault.xml +379 -0
  30. data/solr/exampledocs/books.csv +11 -0
  31. data/solr/exampledocs/hd.xml +46 -0
  32. data/solr/exampledocs/ipod_other.xml +50 -0
  33. data/solr/exampledocs/ipod_video.xml +35 -0
  34. data/solr/exampledocs/mem.xml +58 -0
  35. data/solr/exampledocs/monitor.xml +31 -0
  36. data/solr/exampledocs/monitor2.xml +30 -0
  37. data/solr/exampledocs/mp500.xml +39 -0
  38. data/solr/exampledocs/post.jar +0 -0
  39. data/solr/exampledocs/post.sh +28 -0
  40. data/solr/exampledocs/sd500.xml +33 -0
  41. data/solr/exampledocs/solr.xml +38 -0
  42. data/solr/exampledocs/spellchecker.xml +58 -0
  43. data/solr/exampledocs/utf8-example.xml +42 -0
  44. data/solr/exampledocs/vidcard.xml +52 -0
  45. data/solr/lib/jetty-6.1.3.jar +0 -0
  46. data/solr/lib/jetty-util-6.1.3.jar +0 -0
  47. data/solr/lib/jsp-2.1/ant-1.6.5.jar +0 -0
  48. data/solr/lib/jsp-2.1/core-3.1.1.jar +0 -0
  49. data/solr/lib/jsp-2.1/jsp-2.1.jar +0 -0
  50. data/solr/lib/jsp-2.1/jsp-api-2.1.jar +0 -0
  51. data/solr/lib/servlet-api-2.5-6.1.3.jar +0 -0
  52. data/solr/solr/README.txt +52 -0
  53. data/solr/solr/bin/abc +176 -0
  54. data/solr/solr/bin/abo +176 -0
  55. data/solr/solr/bin/backup +108 -0
  56. data/solr/solr/bin/backupcleaner +142 -0
  57. data/solr/solr/bin/commit +128 -0
  58. data/solr/solr/bin/optimize +129 -0
  59. data/solr/solr/bin/readercycle +129 -0
  60. data/solr/solr/bin/rsyncd-disable +77 -0
  61. data/solr/solr/bin/rsyncd-enable +76 -0
  62. data/solr/solr/bin/rsyncd-start +145 -0
  63. data/solr/solr/bin/rsyncd-stop +105 -0
  64. data/solr/solr/bin/scripts-util +83 -0
  65. data/solr/solr/bin/snapcleaner +148 -0
  66. data/solr/solr/bin/snapinstaller +168 -0
  67. data/solr/solr/bin/snappuller +248 -0
  68. data/solr/solr/bin/snappuller-disable +77 -0
  69. data/solr/solr/bin/snappuller-enable +77 -0
  70. data/solr/solr/bin/snapshooter +109 -0
  71. data/solr/solr/conf/admin-extra.html +31 -0
  72. data/solr/solr/conf/protwords.txt +21 -0
  73. data/solr/solr/conf/schema.xml +231 -0
  74. data/solr/solr/conf/scripts.conf +24 -0
  75. data/solr/solr/conf/solrconfig.xml +394 -0
  76. data/solr/solr/conf/stopwords.txt +57 -0
  77. data/solr/solr/conf/synonyms.txt +31 -0
  78. data/solr/start.jar +0 -0
  79. data/solr/webapps/solr.war +0 -0
  80. data/tasks/deployment.rake +34 -0
  81. data/tasks/environment.rake +7 -0
  82. data/tasks/rcov.rake +6 -0
  83. data/tasks/solr.rake +12 -0
  84. data/tasks/website.rake +17 -0
  85. data/test/api/test_build_search.rb +216 -0
  86. data/test/api/test_helper.rb +4 -0
  87. data/test/api/test_indexer.rb +110 -0
  88. data/test/api/test_retrieve_search.rb +114 -0
  89. data/test/api/test_session.rb +46 -0
  90. data/test/custom_expectation.rb +53 -0
  91. data/test/integration/test_field_types.rb +62 -0
  92. data/test/integration/test_helper.rb +1 -0
  93. data/test/integration/test_keyword_search.rb +32 -0
  94. data/test/integration/test_pagination.rb +32 -0
  95. data/test/mocks/base_class.rb +2 -0
  96. data/test/mocks/comment.rb +28 -0
  97. data/test/mocks/mock_adapter.rb +25 -0
  98. data/test/mocks/post.rb +41 -0
  99. data/test/test_helper.rb +31 -0
  100. metadata +191 -0
data/History.txt ADDED
@@ -0,0 +1,7 @@
1
+ == 0.0.1 2008-12-11
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
5
+ * Define indexing for any class using DSL
6
+ * Search indexed classes using DSL
7
+
data/Manifest.txt ADDED
@@ -0,0 +1,104 @@
1
+ History.txt
2
+ Manifest.txt
3
+ PostInstall.txt
4
+ README.rdoc
5
+ Rakefile
6
+ config/hoe.rb
7
+ config/requirements.rb
8
+ lib/light_config.rb
9
+ lib/sunspot.rb
10
+ lib/sunspot/adapters.rb
11
+ lib/sunspot/conditions.rb
12
+ lib/sunspot/conditions_builder.rb
13
+ lib/sunspot/configuration.rb
14
+ lib/sunspot/field.rb
15
+ lib/sunspot/field_builder.rb
16
+ lib/sunspot/indexer.rb
17
+ lib/sunspot/query.rb
18
+ lib/sunspot/query_builder.rb
19
+ lib/sunspot/restriction.rb
20
+ lib/sunspot/scope_builder.rb
21
+ lib/sunspot/search.rb
22
+ lib/sunspot/session.rb
23
+ lib/sunspot/type.rb
24
+ lib/sunspot/util.rb
25
+ lib/sunspot/version.rb
26
+ log/test_solr.log
27
+ setup.rb
28
+ solr/README.txt
29
+ solr/etc/jetty.xml
30
+ solr/etc/webdefault.xml
31
+ solr/exampledocs/books.csv
32
+ solr/exampledocs/hd.xml
33
+ solr/exampledocs/ipod_other.xml
34
+ solr/exampledocs/ipod_video.xml
35
+ solr/exampledocs/mem.xml
36
+ solr/exampledocs/monitor.xml
37
+ solr/exampledocs/monitor2.xml
38
+ solr/exampledocs/mp500.xml
39
+ solr/exampledocs/post.jar
40
+ solr/exampledocs/post.sh
41
+ solr/exampledocs/sd500.xml
42
+ solr/exampledocs/solr.xml
43
+ solr/exampledocs/spellchecker.xml
44
+ solr/exampledocs/utf8-example.xml
45
+ solr/exampledocs/vidcard.xml
46
+ solr/lib/jetty-6.1.3.jar
47
+ solr/lib/jetty-util-6.1.3.jar
48
+ solr/lib/jsp-2.1/ant-1.6.5.jar
49
+ solr/lib/jsp-2.1/core-3.1.1.jar
50
+ solr/lib/jsp-2.1/jsp-2.1.jar
51
+ solr/lib/jsp-2.1/jsp-api-2.1.jar
52
+ solr/lib/servlet-api-2.5-6.1.3.jar
53
+ solr/logs
54
+ solr/solr/README.txt
55
+ solr/solr/bin/abc
56
+ solr/solr/bin/abo
57
+ solr/solr/bin/backup
58
+ solr/solr/bin/backupcleaner
59
+ solr/solr/bin/commit
60
+ solr/solr/bin/optimize
61
+ solr/solr/bin/readercycle
62
+ solr/solr/bin/rsyncd-disable
63
+ solr/solr/bin/rsyncd-enable
64
+ solr/solr/bin/rsyncd-start
65
+ solr/solr/bin/rsyncd-stop
66
+ solr/solr/bin/scripts-util
67
+ solr/solr/bin/snapcleaner
68
+ solr/solr/bin/snapinstaller
69
+ solr/solr/bin/snappuller
70
+ solr/solr/bin/snappuller-disable
71
+ solr/solr/bin/snappuller-enable
72
+ solr/solr/bin/snapshooter
73
+ solr/solr/conf/admin-extra.html
74
+ solr/solr/conf/protwords.txt
75
+ solr/solr/conf/schema.xml
76
+ solr/solr/conf/scripts.conf
77
+ solr/solr/conf/solrconfig.xml
78
+ solr/solr/conf/stopwords.txt
79
+ solr/solr/conf/synonyms.txt
80
+ solr/solr/conf/xslt
81
+ solr/solr/conf/xslt
82
+ solr/solr/data/spell
83
+ solr/start.jar
84
+ solr/webapps/solr.war
85
+ tasks/deployment.rake
86
+ tasks/environment.rake
87
+ tasks/rcov.rake
88
+ tasks/solr.rake
89
+ tasks/website.rake
90
+ test/api/test_build_search.rb
91
+ test/api/test_helper.rb
92
+ test/api/test_indexer.rb
93
+ test/api/test_retrieve_search.rb
94
+ test/api/test_session.rb
95
+ test/custom_expectation.rb
96
+ test/integration/test_field_types.rb
97
+ test/integration/test_helper.rb
98
+ test/integration/test_keyword_search.rb
99
+ test/integration/test_pagination.rb
100
+ test/mocks/base_class.rb
101
+ test/mocks/comment.rb
102
+ test/mocks/mock_adapter.rb
103
+ test/mocks/post.rb
104
+ test/test_helper.rb
data/PostInstall.txt ADDED
@@ -0,0 +1,7 @@
1
+
2
+ For more information on sunspot, see http://sunspot.rubyforge.org
3
+
4
+ NOTE: Change this information in PostInstall.txt
5
+ You can also delete it if you don't want it.
6
+
7
+
data/README.rdoc ADDED
@@ -0,0 +1,115 @@
1
+ = sunspot
2
+
3
+ http://github.com/outoftime/sunspot
4
+
5
+ Sunspot is a Ruby library for expressive, powerful interaction with the Solr search engine.
6
+ Sunspot is built on top of the solr-ruby gem, which provides a low-level interface for Solr
7
+ interaction; Sunspot provides a simple, intuitive, expressive DSL backed by powerful
8
+ features for indexing objects and searching against them.
9
+
10
+ Sunspot is designed to be easily plugged in to any ORM, or even non-database-backed
11
+ objects such as the filesystem.
12
+
13
+ Sunspot is currently under active development and is not feature-complete.
14
+
15
+ === Sunspot already has these features:
16
+
17
+ * Define indexing strategy for each searchable class using intuitive block-based API
18
+ * Clean separation between keyword-searchable fields and fields for scoping/ordering
19
+ * Define fields based on existing attributes or "virtual fields" for custom indexing
20
+ * Indexes each object's entire superclass hierarchy, for easy searching for all objects inheriting from a parent class
21
+ * Intuitive DSL for scoping searches, with all the usual boolean operators available
22
+ * Ability to pass dynamic conditions in as a hash, and define which operator to use for each condition
23
+ * Full compatibility with will_paginate
24
+ * Ordering
25
+
26
+ === Sunspot will have these features:
27
+
28
+ * Adapters for DataMapper, ActiveRecord, and File objects
29
+ * Extensible adapter architecture for easy integration of other ORMs or non-model classes
30
+ * High-power integration with ORM features for maximum efficiency (e.g., specify AR :include argument for eager loading associations when hydrating search results)
31
+ * Intuitive interface for requesting facets on indexed fields
32
+ * Define association facets, which return model objects as row values
33
+ * Access search parameters as hash or object attributes, for easy integration with form helpers or query string builders
34
+ * Plugins for drop-in integration with Merb and Rails
35
+
36
+ == Using Sunspot
37
+
38
+ === Define an index:
39
+
40
+ class Post
41
+ #...
42
+ end
43
+
44
+ Sunspot.setup(Post) do
45
+ text :title, :body
46
+ string :author_name
47
+ integer :blog_id
48
+ integer :category_ids
49
+ float :average_rating
50
+ time :published_at
51
+ string :sort_title do
52
+ title.downcase.sub(/^(an?|the)\W+/, ''/) if title = self.title
53
+ end
54
+ end
55
+
56
+ === Search for objects:
57
+
58
+ search = Sunspot.search Post, :conditions => { :average_rating => 3.0 } do
59
+ keywords 'great pizza'
60
+ with.author_name 'Mark Twain'
61
+ with.blog_id.any_of [2, 14]
62
+ with.category_ids.all_of [4, 10]
63
+ with.published_at.less_than Time.now
64
+
65
+ conditions.interpret :average_rating, :greater_than
66
+ conditions.default :average_rating, 4.0
67
+
68
+ paginate :page => 3, :per_page => 15
69
+ order_by :average_rating, :desc
70
+ end
71
+
72
+ === Get data and parameters from search:
73
+
74
+ search.results
75
+ search.total
76
+ search.page
77
+ search.per_page
78
+ search.keywords
79
+ search.conditions.average_rating
80
+ search.attributes[:conditions]
81
+
82
+ == REQUIREMENTS:
83
+
84
+ 1. extlib
85
+ 2. solr-ruby
86
+ 3. Java
87
+
88
+ == INSTALL:
89
+
90
+ * FIX (sudo gem install, anything else)
91
+
92
+ == LICENSE:
93
+
94
+ (The MIT License)
95
+
96
+ Copyright (c) 2008 Mat Brown
97
+
98
+ Permission is hereby granted, free of charge, to any person obtaining
99
+ a copy of this software and associated documentation files (the
100
+ 'Software'), to deal in the Software without restriction, including
101
+ without limitation the rights to use, copy, modify, merge, publish,
102
+ distribute, sublicense, and/or sell copies of the Software, and to
103
+ permit persons to whom the Software is furnished to do so, subject to
104
+ the following conditions:
105
+
106
+ The above copyright notice and this permission notice shall be
107
+ included in all copies or substantial portions of the Software.
108
+
109
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
110
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
111
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
112
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
113
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
114
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
115
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,27 @@
1
+ %w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
2
+ require File.dirname(__FILE__) + '/lib/sunspot'
3
+
4
+ ENV['RUBYOPT'] = '-W1'
5
+
6
+ # Generate all the Rake tasks
7
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
8
+ $hoe = Hoe.new('sunspot', Sunspot::VERSION) do |p|
9
+ p.developer('Mat Brown', 'mat@patch.com')
10
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
11
+ p.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
12
+ p.rubyforge_name = p.name # TODO this is default value
13
+ # p.extra_deps = [
14
+ # ['activesupport','>= 2.0.2'],
15
+ # ]
16
+ p.extra_dev_deps = [
17
+ ['newgem', ">= #{::Newgem::VERSION}"]
18
+ ]
19
+
20
+ p.clean_globs |= %w[**/.DS_Store tmp *.log]
21
+ path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
22
+ p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
23
+ p.rsync_args = '-av --delete --ignore-errors'
24
+ end
25
+
26
+ require 'newgem/tasks' # load /tasks/*.rake
27
+ Dir['tasks/**/*.rake'].each { |t| load t }
data/config/hoe.rb ADDED
@@ -0,0 +1,74 @@
1
+ require 'sunspot/version'
2
+
3
+ AUTHOR = 'Mat Brown' # can also be an array of Authors
4
+ EMAIL = "mat@patch.com"
5
+ DESCRIPTION = "Awesome Solr interaction for Ruby"
6
+ GEM_NAME = 'sunspot' # what ppl will type to install your gem
7
+ RUBYFORGE_PROJECT = 'sunspot' # The unix name for your project
8
+ HOMEPATH = "http://github.com/outoftime/sunspot"
9
+ DOWNLOAD_PATH = "http://github.com/outoftime/sunspot"
10
+ EXTRA_DEPENDENCIES = [
11
+ ['solr-ruby', '= 0.0.6',
12
+ 'extlib', '>= 0.9.7']
13
+ ] # An array of rubygem dependencies [name, version]
14
+
15
+ @config_file = "~/.rubyforge/user-config.yml"
16
+ @config = nil
17
+ RUBYFORGE_USERNAME = "unknown"
18
+ def rubyforge_username
19
+ unless @config
20
+ begin
21
+ @config = YAML.load(File.read(File.expand_path(@config_file)))
22
+ rescue
23
+ puts <<-EOS
24
+ ERROR: No rubyforge config file found: #{@config_file}
25
+ Run 'rubyforge setup' to prepare your env for access to Rubyforge
26
+ - See http://newgem.rubyforge.org/rubyforge.html for more details
27
+ EOS
28
+ exit
29
+ end
30
+ end
31
+ RUBYFORGE_USERNAME.replace @config["username"]
32
+ end
33
+
34
+
35
+ REV = nil
36
+ # UNCOMMENT IF REQUIRED:
37
+ # REV = YAML.load(`svn info`)['Revision']
38
+ VERS = Sunspot::VERSION::STRING + (REV ? ".#{REV}" : "")
39
+ RDOC_OPTS = ['--quiet', '--title', 'sunspot documentation',
40
+ "--opname", "index.html",
41
+ "--line-numbers",
42
+ "--main", "README.rdoc",
43
+ "--inline-source"]
44
+
45
+ class Hoe
46
+ def extra_deps
47
+ @extra_deps.reject! { |x| Array(x).first == 'hoe' }
48
+ @extra_deps
49
+ end
50
+ end
51
+
52
+ # Generate all the Rake tasks
53
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
54
+ $hoe = Hoe.new(GEM_NAME, VERS) do |p|
55
+ p.developer(AUTHOR, EMAIL)
56
+ p.description = DESCRIPTION
57
+ p.summary = DESCRIPTION
58
+ p.url = HOMEPATH
59
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
60
+ p.test_globs = ["spec/**/*_spec.rb"]
61
+ p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
62
+
63
+ # == Optional
64
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
65
+ #p.extra_deps = EXTRA_DEPENDENCIES
66
+
67
+ #p.spec_extras = {} # A hash of extra values to set in the gemspec.
68
+ end
69
+
70
+ CHANGES = $hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
71
+ PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
72
+ $hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
73
+ $hoe.rsync_args = '-av --delete --ignore-errors'
74
+ $hoe.spec.post_install_message = File.open(File.dirname(__FILE__) + "/../PostInstall.txt").read rescue ""
@@ -0,0 +1,15 @@
1
+ require 'fileutils'
2
+ include FileUtils
3
+
4
+ require 'rubygems'
5
+ %w[rake hoe newgem rubigen].each do |req_gem|
6
+ begin
7
+ require req_gem
8
+ rescue LoadError
9
+ puts "This Rakefile requires the '#{req_gem}' RubyGem."
10
+ puts "Installation: gem install #{req_gem} -y"
11
+ exit
12
+ end
13
+ end
14
+
15
+ $:.unshift(File.join(File.dirname(__FILE__), %w[.. lib]))
@@ -0,0 +1,40 @@
1
+ module LightConfig
2
+ class Configuration
3
+ def initialize(&block)
4
+ @properties = {}
5
+ ::LightConfig::Builder.new(self).instance_eval(&block)
6
+ singleton = (class <<self; self; end)
7
+ @properties.keys.each do |property|
8
+ singleton.module_eval do
9
+ define_method property do
10
+ @properties[property]
11
+ end
12
+
13
+ define_method "#{property}=" do |value|
14
+ @properties[property] = value
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ class Builder
22
+ def initialize(configuration)
23
+ @configuration = configuration
24
+ end
25
+
26
+ def method_missing(method, *args, &block)
27
+ raise ArgumentError("wrong number of arguments(#{args.length} for 1)") unless args.length < 2
28
+ value = if block then ::LightConfig::Configuration.new(&block)
29
+ else args.first
30
+ end
31
+ @configuration.instance_variable_get(:@properties)[method] = value
32
+ end
33
+ end
34
+ end
35
+
36
+ class <<LightConfig
37
+ def build(&block)
38
+ LightConfig::Configuration.new(&block)
39
+ end
40
+ end
@@ -0,0 +1,54 @@
1
+ module Sunspot
2
+ module Adapters
3
+ module InstanceAdapter
4
+ def initialize(instance)
5
+ @instance = instance
6
+ end
7
+
8
+ def index_id
9
+ "#{instance.class.name} #{id}"
10
+ end
11
+
12
+ protected
13
+ attr_accessor :instance
14
+ end
15
+
16
+ module ClassAdapter
17
+ def initialize(clazz)
18
+ @clazz = clazz
19
+ end
20
+
21
+ protected
22
+ attr_reader :clazz
23
+ end
24
+ end
25
+
26
+ class <<Adapters
27
+ def register(adapter, *classes)
28
+ for clazz in classes
29
+ adapters[clazz.name] = adapter
30
+ end
31
+ end
32
+
33
+ def adapt_class(clazz)
34
+ self.for(clazz).const_get('ClassAdapter').new(clazz)
35
+ end
36
+
37
+ def adapt_instance(instance)
38
+ self.for(instance.class).const_get('InstanceAdapter').new(instance)
39
+ end
40
+
41
+ def for(clazz)
42
+ while clazz != Object
43
+ return adapters[clazz.name] if adapters[clazz.name]
44
+ clazz = clazz.superclass
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def adapters
51
+ @adapters ||= {}
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,50 @@
1
+ module Sunspot
2
+ class Conditions
3
+ def initialize(query, conditions_hash)
4
+ @query = query
5
+ @conditions_hash = conditions_hash.inject({}) do |hash, pair|
6
+ field_name, value = pair
7
+ hash[field_name.to_s] = value
8
+ hash
9
+ end
10
+ end
11
+
12
+ def interpret(field_name, condition_type)
13
+ operators_hash[field_name.to_s] = Sunspot::Restriction.const_get condition_type.to_s.camel_case
14
+ end
15
+
16
+ def default(field_name, value)
17
+ conditions_hash[field_name.to_s] ||= value
18
+ end
19
+
20
+ def restrictions
21
+ conditions_hash.map { |field_name, value| condition_for(field_name, value) }.compact
22
+ end
23
+
24
+ protected
25
+ attr_reader :conditions_hash
26
+
27
+ def condition_for(field_name, value)
28
+ operator = operator_for(field_name) || default_operator_for(value)
29
+ begin
30
+ @query.build_condition field_name, operator, value
31
+ rescue ArgumentError
32
+ nil # fail silently if field isn't configured
33
+ end
34
+ end
35
+
36
+ def default_operator_for(value)
37
+ if value.is_a?(Array) then Sunspot::Restriction::AnyOf
38
+ else Sunspot::Restriction::EqualTo
39
+ end
40
+ end
41
+
42
+ def operator_for(field_name)
43
+ operators_hash[field_name.to_s]
44
+ end
45
+
46
+ def operators_hash
47
+ @operators_hash ||= {}
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,37 @@
1
+ module Sunspot
2
+ class Conditions
3
+ def initialize(query, conditions_hash)
4
+ @query, @conditions_hash = query, conditions_hash
5
+ end
6
+
7
+ def interpret(field_name, condition_type)
8
+ operators_hash[field_name.to_s] = Sunspot::Restriction.const_get condition_type.to_s.camel_case
9
+ end
10
+
11
+ def conditions
12
+ conditions_hash.map { |field_name, value| condition_for(field_name, value) }
13
+ end
14
+
15
+ protected
16
+ attr_reader :conditions_hash
17
+
18
+ def condition_for(field_name, value)
19
+ operator = operator_for(field_name) || default_operator_for(value)
20
+ @query.build_condition field_name, operator, value
21
+ end
22
+
23
+ def default_operator_for(value)
24
+ if value.is_a?(Array) then Sunspot::Restriction::AnyOf
25
+ else Sunspot::Restriction::EqualTo
26
+ end
27
+ end
28
+
29
+ def operator_for(field_name)
30
+ operators_hash[field_name.to_s]
31
+ end
32
+
33
+ def operators_hash
34
+ @operators_hash ||= {}
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,17 @@
1
+ module Sunspot
2
+ module Configuration
3
+ end
4
+
5
+ class <<Configuration
6
+ def build
7
+ LightConfig.build do
8
+ solr do
9
+ url 'http://localhost:8983/solr'
10
+ end
11
+ pagination do
12
+ default_per_page 30
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,108 @@
1
+ module Sunspot
2
+ module Field
3
+ class Base
4
+ attr_accessor :name, :type
5
+
6
+ def initialize(name, type, options = {})
7
+ @name, @type = name, type
8
+ @multiple = options.delete(:multiple)
9
+ raise ArgumentError, "Unknown field option #{options.keys.first.inspect} provided for field #{name.inspect}" unless options.empty?
10
+ end
11
+
12
+ def pair_for(model)
13
+ if value = value_for(model)
14
+ { indexed_name.to_sym => to_indexed(value) }
15
+ else
16
+ {}
17
+ end
18
+ end
19
+
20
+ def ==(other)
21
+ other.respond_to?(:name) &&
22
+ other.respond_to?(:type) &&
23
+ self.name == other.name &&
24
+ self.type == other.type
25
+ end
26
+
27
+ def hash
28
+ name.hash + 31 * type.hash
29
+ end
30
+
31
+ def indexed_name
32
+ "#{type.indexed_name(name)}#{'m' if multiple?}"
33
+ end
34
+
35
+ def to_indexed(value)
36
+ if value.kind_of? Array
37
+ if multiple?
38
+ value.map { |val| to_indexed(val) }
39
+ else
40
+ raise ArgumentError, "#{name} is not a multiple-value field, so it cannot index values #{value.inspect}"
41
+ end
42
+ else
43
+ type.to_indexed(value)
44
+ end
45
+ end
46
+
47
+ def multiple?
48
+ !!@multiple
49
+ end
50
+ end
51
+
52
+ class AttributeField < ::Sunspot::Field::Base
53
+ protected
54
+
55
+ def value_for(model)
56
+ model.send(name)
57
+ end
58
+ end
59
+
60
+ class VirtualField < ::Sunspot::Field::Base
61
+ def initialize(name, type, options = {}, &block)
62
+ super(name, type, options)
63
+ @block = block
64
+ end
65
+
66
+ protected
67
+ attr_accessor :block
68
+
69
+ def value_for(model)
70
+ model.instance_eval(&block)
71
+ end
72
+ end
73
+ end
74
+
75
+ class <<Field
76
+ def register(clazz, fields)
77
+ fields = [fields] unless fields.kind_of? Enumerable
78
+ self.for(clazz).concat fields
79
+ end
80
+
81
+ def register_text(clazz, fields)
82
+ fields = [fields] unless fields.kind_of? Enumerable
83
+ self.text_for(clazz).concat fields
84
+ end
85
+
86
+ def text_for(clazz)
87
+ keyword_fields_hash[clazz.object_id] ||= []
88
+ end
89
+
90
+ def for(clazz)
91
+ fields_hash[clazz.object_id] ||= []
92
+ end
93
+
94
+ def unregister_all!
95
+ fields_hash.clear
96
+ end
97
+
98
+ private
99
+
100
+ def fields_hash
101
+ @fields_hash ||= {}
102
+ end
103
+
104
+ def keyword_fields_hash
105
+ @keyword_fields_hash ||= {}
106
+ end
107
+ end
108
+ end