thinking-sphinx-raspell 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -38,13 +38,28 @@ You can also choose to redo the search using the provided suggestion:
38
38
  # ...
39
39
  end</code></pre>
40
40
 
41
+ h2. Configuration
42
+
43
+ You can customise the following settings - either in your @config/environment.rb@ file, or perhaps in an initializer. Example syntax below highlights the current defaults.
44
+
45
+ <pre><code>config = ThinkingSphinx::Configuration.instance
46
+ config.raspell.dictionary = 'en'
47
+ config.raspell.suggestion_mode = :normal
48
+ config.raspell.options['ignore-case'] = true</code></pre>
49
+
50
+ You can look at the available options using the following two collections:
51
+
52
+ <pre><code>config = ThinkingSphinx::Configuration.instance
53
+ config.raspell.dictionaries #=> ['en', 'en_GB', 'en_US', ... ]
54
+ config.raspell.suggestion_modes #=> [:ultra, :fast, :normal, :badspellers]</code></pre>
55
+
56
+ If you need more documentation, you can check out the YARD files "on rdoc.info":http://rdoc.info/projects/freelancing-god/thinking-sphinx-raspell. This isn't a big library, though - what you see in this readme is pretty much what you get.
57
+
41
58
  h2. Limitations
42
59
 
43
- * Currently only uses (and thus requires) the en_US dictionary.
44
- * Spelling suggestions are done via Raspell's normal mode, and are case insensitive.
45
60
  * Only checks normal query strings, not field-specific queries via the @:conditions@ hash.
46
61
 
47
- Patches are very much welcome - I would like to address all of the above limitations.
62
+ Patches are very much welcome - I would like to address this last remaining limitation.
48
63
 
49
64
  h2. Copyright
50
65
 
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 1
3
- :minor: 0
3
+ :minor: 1
4
4
  :patch: 0
@@ -1,4 +1,5 @@
1
1
  require 'raspell'
2
+ require 'thinking_sphinx/raspell/configuration'
2
3
 
3
4
  module ThinkingSphinx
4
5
  # Module for adding suggestion support into Thinking Sphinx. This gets
@@ -56,19 +57,12 @@ module ThinkingSphinx
56
57
  speller.check(word) ? word : speller.suggest(word).first
57
58
  end
58
59
 
59
- # Aspell instance with all appropriate settings defined (dictionary set to
60
- # en_US, suggestion mode set to Aspell::NORMAL, and ignore-case set to
61
- # true).
60
+ # Aspell instance with all appropriate settings defined.
62
61
  #
63
62
  # @return [Aspell] the prepared Aspell instance
64
63
  #
65
64
  def speller
66
- @speller ||= begin
67
- speller = Aspell.new('en_US')
68
- speller.suggestion_mode = Aspell::NORMAL
69
- speller.set_option "ignore-case", "true"
70
- speller
71
- end
65
+ ThinkingSphinx::Configuration.instance.raspell.speller
72
66
  end
73
67
  end
74
68
  end
@@ -0,0 +1,142 @@
1
+ module ThinkingSphinx
2
+ module Raspell
3
+ # Configuration settings for spelling suggestions in Thinking Sphinx. You
4
+ # can access these either by the singleton instance
5
+ # (ThinkingSphinx::Raspell::Configuration.instance), or through Thinking
6
+ # Sphinx's existing configuration instance
7
+ # (ThinkingSphinx::Configuration.instance.raspell).
8
+ #
9
+ # @author Pat Allan
10
+ #
11
+ class Configuration
12
+ include Singleton
13
+
14
+ attr_reader :dictionary, :suggestion_mode, :options
15
+
16
+ # Creates the instance of the singleton with the following defaults:
17
+ # Dictionary is English (en), suggestion mode is normal, and the
18
+ # ignore-case option is enabled.
19
+ #
20
+ def initialize
21
+ reset
22
+ end
23
+
24
+ # Resets the instance to the default settings. Probably not necessary in
25
+ # general usage, but makes specs easier to run.
26
+ #
27
+ def reset
28
+ @dictionary = 'en'
29
+ @suggestion_mode = :normal
30
+ @options = {'ignore-case' => true}
31
+ @speller = nil
32
+ end
33
+
34
+ # Sets the dictionary for the spelling suggestions. Make sure you have the
35
+ # dictionary installed on your system first.
36
+ #
37
+ # @example
38
+ # config.dictionary = 'en_GB'
39
+ #
40
+ # @param [String] dict dictionary code
41
+ # @raise [ArgumentError] if the dictionary code is not known by Aspell
42
+ #
43
+ def dictionary=(dict)
44
+ unless dictionaries.include?(dict)
45
+ raise ArgumentError, 'unknown dictionary'
46
+ end
47
+
48
+ @dictionary = dict
49
+ end
50
+
51
+ # The list of dictionaries Aspell has on offer.
52
+ #
53
+ # @return [Array] collection of dictionary codes
54
+ #
55
+ def dictionaries
56
+ @dictionaries ||= Aspell.list_dicts.collect { |dict| dict.code }
57
+ end
58
+
59
+ # Set the suggestion mode. Accepts symbols, strings and Aspell constants.
60
+ # The known values are ultra, fast, normal and badspellers/bad-spellers.
61
+ #
62
+ # @param [Symbol, String] mode suggestion mode
63
+ # @raise [ArgumentError] if the suggestion mode is not known by Aspell
64
+ #
65
+ def suggestion_mode=(mode)
66
+ mode = mode.gsub(/-/, '').to_sym if mode.is_a?(String)
67
+
68
+ unless suggestion_modes.include?(mode)
69
+ raise ArgumentError, 'unknown suggestion mode'
70
+ end
71
+
72
+ @suggestion_mode = mode
73
+ end
74
+
75
+ # The allowed suggestion modes.
76
+ #
77
+ # @return [Array] available suggestion modes, as symbols.
78
+ #
79
+ def suggestion_modes
80
+ [:ultra, :fast, :normal, :badspellers]
81
+ end
82
+
83
+ # Aspell instance with all appropriate settings defined.
84
+ #
85
+ # @return [Aspell] the prepared Aspell instance
86
+ #
87
+ def speller
88
+ @speller ||= build_speller
89
+ end
90
+
91
+ private
92
+
93
+ # Convert the suggestion mode symbol to a string, and ensures the dash
94
+ # is added to the bad-spellers mode.
95
+ #
96
+ # @return [String] Aspell-friendly suggestion mode
97
+ #
98
+ def actual_suggestion_mode
99
+ suggestion_mode.to_s.gsub(/badspellers/, 'bad-spellers')
100
+ end
101
+
102
+ # Converts user-defined options to have string keys, as that's what Aspell
103
+ # requires.
104
+ #
105
+ # @return [Hash] options with string keys
106
+ #
107
+ def actual_options
108
+ options.keys.inject({}) do |hash, key|
109
+ hash[key] = options[key].to_s
110
+ hash
111
+ end
112
+ end
113
+
114
+ # Generate the Aspell instance, setting the dictionary, suggestion mode
115
+ # and options as defined in the configuration instance.
116
+ #
117
+ # @return [Aspell] a new prepared Aspell instance
118
+ #
119
+ def build_speller
120
+ speller = Aspell.new(dictionary)
121
+ speller.suggestion_mode = actual_suggestion_mode
122
+ actual_options.each do |key, value|
123
+ speller.set_option key, value
124
+ end
125
+
126
+ speller
127
+ end
128
+ end
129
+
130
+ module Hooks
131
+ # The singleton ThinkingSphinx::Raspell::Configuration instance.
132
+ #
133
+ # @return [ThinkingSphinx::Raspell::Configuration] config instance
134
+ #
135
+ def raspell
136
+ ThinkingSphinx::Raspell::Configuration.instance
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ ThinkingSphinx::Configuration.send(:include, ThinkingSphinx::Raspell::Hooks)
@@ -0,0 +1,122 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe ThinkingSphinx::Configuration do
4
+ describe '#raspell' do
5
+ before :each do
6
+ @config = ThinkingSphinx::Configuration.instance
7
+ end
8
+
9
+ it "should return a raspell configuration instance" do
10
+ @config.raspell.should be_a(ThinkingSphinx::Raspell::Configuration)
11
+ end
12
+ end
13
+ end
14
+
15
+ describe ThinkingSphinx::Raspell::Configuration do
16
+ before :each do
17
+ @config = ThinkingSphinx::Raspell::Configuration.instance
18
+ @config.reset
19
+ end
20
+
21
+ describe '#dictionary' do
22
+ it "should default to 'en'" do
23
+ @config.dictionary.should == 'en'
24
+ end
25
+ end
26
+
27
+ describe '#dictionary=' do
28
+ it "should set the dictionary" do
29
+ @config.dictionary = 'en_GB'
30
+ @config.dictionary.should == 'en_GB'
31
+ end
32
+
33
+ it "should raise an argument error if the dictionary code is invalid" do
34
+ lambda { @config.dictionary = 'zz' }.should raise_error(ArgumentError)
35
+ end
36
+ end
37
+
38
+ describe '#dictionaries' do
39
+ it "should return the names of all registered dictionaries" do
40
+ @config.dictionaries.should == Aspell.list_dicts.collect { |dict|
41
+ dict.code
42
+ }
43
+ end
44
+ end
45
+
46
+ describe '#suggestion_mode' do
47
+ it "should default to normal" do
48
+ @config.suggestion_mode.should == :normal
49
+ end
50
+ end
51
+
52
+ describe '#suggestion_mode=' do
53
+ it "should set the suggestion mode" do
54
+ @config.suggestion_mode = :ultra
55
+ @config.suggestion_mode.should == :ultra
56
+ end
57
+
58
+ it "should raise an argument error if the suggestion mode is invalid" do
59
+ lambda { @config.suggestion_mode = :smart }.
60
+ should raise_error(ArgumentError)
61
+ end
62
+
63
+ it "should translate Aspell constants" do
64
+ @config.suggestion_mode = Aspell::BADSPELLERS
65
+ @config.suggestion_mode.should == :badspellers
66
+ end
67
+ end
68
+
69
+ describe '#options' do
70
+ it "should return a Hash" do
71
+ @config.options.should be_a(Hash)
72
+ end
73
+
74
+ it "should have ignore-case defaulting to true" do
75
+ @config.options['ignore-case'].should == true
76
+ end
77
+ end
78
+
79
+ describe '#suggestion_modes' do
80
+ it "should return ultra, fast, normal and badspellers" do
81
+ @config.suggestion_modes.should == [:ultra, :fast, :normal, :badspellers]
82
+ end
83
+ end
84
+
85
+ describe '#speller' do
86
+ it "should return an Aspell instance" do
87
+ @config.speller.should be_an(Aspell)
88
+ end
89
+
90
+ it "should use the configured dictionary" do
91
+ speller = Aspell.new('en_GB')
92
+ Aspell.should_receive(:new).with('en_GB').and_return(speller)
93
+
94
+ @config.dictionary = 'en_GB'
95
+ @config.speller
96
+ end
97
+
98
+ it "should set the configured suggestion mode" do
99
+ speller = Aspell.new('en')
100
+ speller.should_receive(:suggestion_mode=).with('bad-spellers')
101
+ Aspell.stub!(:new => speller)
102
+
103
+ @config.suggestion_mode = :badspellers
104
+ @config.speller
105
+ end
106
+
107
+ it "should set the configured options" do
108
+ @config.options['ignore-case'] = false
109
+
110
+ @config.speller.get_option('ignore-case').should == 'false'
111
+ end
112
+
113
+ it "should reuse the generated instance" do
114
+ Aspell.should_receive(:new).once.and_return(
115
+ stub('speller').as_null_object
116
+ )
117
+
118
+ @config.speller
119
+ @config.speller
120
+ end
121
+ end
122
+ end
@@ -1,6 +1,10 @@
1
1
  require 'spec/spec_helper'
2
2
 
3
3
  describe ThinkingSphinx::Search do
4
+ before :each do
5
+ ThinkingSphinx::Configuration.instance.raspell.reset
6
+ end
7
+
4
8
  describe '#suggestion' do
5
9
  it "should return a spelling suggestion, if there is one" do
6
10
  search = ThinkingSphinx::Search.new('wodrs incorret on purpose')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: thinking-sphinx-raspell
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pat Allan
@@ -66,6 +66,7 @@ files:
66
66
  - README.textile
67
67
  - VERSION.yml
68
68
  - lib/thinking_sphinx/raspell.rb
69
+ - lib/thinking_sphinx/raspell/configuration.rb
69
70
  has_rdoc: true
70
71
  homepage: http://ts.freelancing-gods.com
71
72
  licenses: []
@@ -96,4 +97,5 @@ specification_version: 3
96
97
  summary: An add-on gem for spelling suggestions in Thinking Sphinx
97
98
  test_files:
98
99
  - spec/spec_helper.rb
100
+ - spec/thinking_sphinx/raspell/configuration_spec.rb
99
101
  - spec/thinking_sphinx/raspell_spec.rb