initforthe-thinking-sphinx 1.1.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. data/LICENCE +20 -0
  2. data/README.textile +141 -0
  3. data/lib/thinking_sphinx.rb +215 -0
  4. data/lib/thinking_sphinx/active_record.rb +278 -0
  5. data/lib/thinking_sphinx/active_record/attribute_updates.rb +48 -0
  6. data/lib/thinking_sphinx/active_record/delta.rb +87 -0
  7. data/lib/thinking_sphinx/active_record/has_many_association.rb +29 -0
  8. data/lib/thinking_sphinx/active_record/search.rb +57 -0
  9. data/lib/thinking_sphinx/adapters/abstract_adapter.rb +42 -0
  10. data/lib/thinking_sphinx/adapters/mysql_adapter.rb +54 -0
  11. data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +135 -0
  12. data/lib/thinking_sphinx/association.rb +164 -0
  13. data/lib/thinking_sphinx/attribute.rb +268 -0
  14. data/lib/thinking_sphinx/class_facet.rb +15 -0
  15. data/lib/thinking_sphinx/collection.rb +148 -0
  16. data/lib/thinking_sphinx/configuration.rb +262 -0
  17. data/lib/thinking_sphinx/core/string.rb +15 -0
  18. data/lib/thinking_sphinx/deltas.rb +30 -0
  19. data/lib/thinking_sphinx/deltas/datetime_delta.rb +50 -0
  20. data/lib/thinking_sphinx/deltas/default_delta.rb +68 -0
  21. data/lib/thinking_sphinx/deltas/delayed_delta.rb +27 -0
  22. data/lib/thinking_sphinx/deltas/delayed_delta/delta_job.rb +24 -0
  23. data/lib/thinking_sphinx/deltas/delayed_delta/flag_as_deleted_job.rb +27 -0
  24. data/lib/thinking_sphinx/deltas/delayed_delta/job.rb +26 -0
  25. data/lib/thinking_sphinx/deploy/capistrano.rb +82 -0
  26. data/lib/thinking_sphinx/facet.rb +108 -0
  27. data/lib/thinking_sphinx/facet_collection.rb +59 -0
  28. data/lib/thinking_sphinx/field.rb +82 -0
  29. data/lib/thinking_sphinx/index.rb +99 -0
  30. data/lib/thinking_sphinx/index/builder.rb +287 -0
  31. data/lib/thinking_sphinx/index/faux_column.rb +110 -0
  32. data/lib/thinking_sphinx/property.rb +160 -0
  33. data/lib/thinking_sphinx/rails_additions.rb +136 -0
  34. data/lib/thinking_sphinx/search.rb +727 -0
  35. data/lib/thinking_sphinx/search/facets.rb +104 -0
  36. data/lib/thinking_sphinx/source.rb +150 -0
  37. data/lib/thinking_sphinx/source/internal_properties.rb +46 -0
  38. data/lib/thinking_sphinx/source/sql.rb +126 -0
  39. data/lib/thinking_sphinx/tasks.rb +162 -0
  40. data/rails/init.rb +14 -0
  41. data/spec/unit/thinking_sphinx/active_record/delta_spec.rb +136 -0
  42. data/spec/unit/thinking_sphinx/active_record/has_many_association_spec.rb +53 -0
  43. data/spec/unit/thinking_sphinx/active_record/search_spec.rb +107 -0
  44. data/spec/unit/thinking_sphinx/active_record_spec.rb +329 -0
  45. data/spec/unit/thinking_sphinx/association_spec.rb +246 -0
  46. data/spec/unit/thinking_sphinx/attribute_spec.rb +338 -0
  47. data/spec/unit/thinking_sphinx/collection_spec.rb +15 -0
  48. data/spec/unit/thinking_sphinx/configuration_spec.rb +222 -0
  49. data/spec/unit/thinking_sphinx/core/string_spec.rb +9 -0
  50. data/spec/unit/thinking_sphinx/facet_collection_spec.rb +64 -0
  51. data/spec/unit/thinking_sphinx/facet_spec.rb +302 -0
  52. data/spec/unit/thinking_sphinx/field_spec.rb +154 -0
  53. data/spec/unit/thinking_sphinx/index/builder_spec.rb +355 -0
  54. data/spec/unit/thinking_sphinx/index/faux_column_spec.rb +30 -0
  55. data/spec/unit/thinking_sphinx/index_spec.rb +45 -0
  56. data/spec/unit/thinking_sphinx/rails_additions_spec.rb +191 -0
  57. data/spec/unit/thinking_sphinx/search_spec.rb +228 -0
  58. data/spec/unit/thinking_sphinx/source_spec.rb +217 -0
  59. data/spec/unit/thinking_sphinx_spec.rb +151 -0
  60. data/tasks/distribution.rb +67 -0
  61. data/tasks/rails.rake +1 -0
  62. data/tasks/testing.rb +78 -0
  63. data/vendor/after_commit/LICENSE +20 -0
  64. data/vendor/after_commit/README +16 -0
  65. data/vendor/after_commit/Rakefile +22 -0
  66. data/vendor/after_commit/init.rb +8 -0
  67. data/vendor/after_commit/lib/after_commit.rb +45 -0
  68. data/vendor/after_commit/lib/after_commit/active_record.rb +114 -0
  69. data/vendor/after_commit/lib/after_commit/connection_adapters.rb +103 -0
  70. data/vendor/after_commit/test/after_commit_test.rb +53 -0
  71. data/vendor/delayed_job/lib/delayed/job.rb +251 -0
  72. data/vendor/delayed_job/lib/delayed/message_sending.rb +7 -0
  73. data/vendor/delayed_job/lib/delayed/performable_method.rb +55 -0
  74. data/vendor/delayed_job/lib/delayed/worker.rb +54 -0
  75. data/vendor/riddle/lib/riddle.rb +30 -0
  76. data/vendor/riddle/lib/riddle/client.rb +619 -0
  77. data/vendor/riddle/lib/riddle/client/filter.rb +53 -0
  78. data/vendor/riddle/lib/riddle/client/message.rb +65 -0
  79. data/vendor/riddle/lib/riddle/client/response.rb +84 -0
  80. data/vendor/riddle/lib/riddle/configuration.rb +33 -0
  81. data/vendor/riddle/lib/riddle/configuration/distributed_index.rb +48 -0
  82. data/vendor/riddle/lib/riddle/configuration/index.rb +142 -0
  83. data/vendor/riddle/lib/riddle/configuration/indexer.rb +19 -0
  84. data/vendor/riddle/lib/riddle/configuration/remote_index.rb +17 -0
  85. data/vendor/riddle/lib/riddle/configuration/searchd.rb +25 -0
  86. data/vendor/riddle/lib/riddle/configuration/section.rb +43 -0
  87. data/vendor/riddle/lib/riddle/configuration/source.rb +23 -0
  88. data/vendor/riddle/lib/riddle/configuration/sql_source.rb +34 -0
  89. data/vendor/riddle/lib/riddle/configuration/xml_source.rb +28 -0
  90. data/vendor/riddle/lib/riddle/controller.rb +44 -0
  91. metadata +190 -0
@@ -0,0 +1,15 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe ThinkingSphinx::Collection do
4
+ it "should behave like WillPaginate::Collection" do
5
+ instance_methods = ThinkingSphinx::Collection.instance_methods.collect { |m| m.to_s }
6
+ instance_methods.should include("previous_page")
7
+ instance_methods.should include("next_page")
8
+ instance_methods.should include("current_page")
9
+ instance_methods.should include("total_pages")
10
+ instance_methods.should include("total_entries")
11
+ instance_methods.should include("offset")
12
+
13
+ ThinkingSphinx::Collection.ancestors.should include(Array)
14
+ end
15
+ end
@@ -0,0 +1,222 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe ThinkingSphinx::Configuration do
4
+ describe "environment class method" do
5
+ before :each do
6
+ ThinkingSphinx::Configuration.send(:class_variable_set, :@@environment, nil)
7
+
8
+ ENV["RAILS_ENV"] = nil
9
+ end
10
+
11
+ it "should use the Merb environment value if set" do
12
+ unless defined?(Merb)
13
+ module ::Merb; end
14
+ end
15
+
16
+ ThinkingSphinx::Configuration.stub_method(:defined? => true)
17
+ Merb.stub!(:environment => "merb_production")
18
+ ThinkingSphinx::Configuration.environment.should == "merb_production"
19
+
20
+ Object.send(:remove_const, :Merb)
21
+ end
22
+
23
+ it "should use the Rails environment value if set" do
24
+ ENV["RAILS_ENV"] = "rails_production"
25
+ ThinkingSphinx::Configuration.environment.should == "rails_production"
26
+ end
27
+
28
+ it "should default to development" do
29
+ ThinkingSphinx::Configuration.environment.should == "development"
30
+ end
31
+ end
32
+
33
+ describe "parse_config method" do
34
+ before :each do
35
+ @settings = {
36
+ "development" => {
37
+ "config_file" => "tmp/config/development.sphinx.conf",
38
+ "searchd_log_file" => "searchd_log_file.log",
39
+ "query_log_file" => "query_log_file.log",
40
+ "pid_file" => "pid_file.pid",
41
+ "searchd_file_path" => "searchd/file/path",
42
+ "address" => "127.0.0.1",
43
+ "port" => 3333,
44
+ "min_prefix_len" => 2,
45
+ "min_infix_len" => 3,
46
+ "mem_limit" => "128M",
47
+ "max_matches" => 1001,
48
+ "morphology" => "stem_ru",
49
+ "charset_type" => "latin1",
50
+ "charset_table" => "table",
51
+ "ignore_chars" => "e",
52
+ "searchd_binary_name" => "searchd",
53
+ "indexer_binary_name" => "indexer"
54
+ }
55
+ }
56
+
57
+ open("#{RAILS_ROOT}/config/sphinx.yml", "w") do |f|
58
+ f.write YAML.dump(@settings)
59
+ end
60
+ end
61
+
62
+ it "should use the accessors to set the configuration values" do
63
+ config = ThinkingSphinx::Configuration.instance
64
+ config.send(:parse_config)
65
+
66
+ %w(config_file searchd_log_file query_log_file pid_file searchd_file_path
67
+ address port searchd_binary_name indexer_binary_name).each do |key|
68
+ config.send(key).should == @settings["development"][key]
69
+ end
70
+ end
71
+
72
+ after :each do
73
+ FileUtils.rm "#{RAILS_ROOT}/config/sphinx.yml"
74
+ end
75
+ end
76
+
77
+ describe "block configuration" do
78
+ it "should let the user set-up a custom app_root" do
79
+ ThinkingSphinx::Configuration.configure do |config|
80
+ config.app_root = "/here/somewhere"
81
+ end
82
+ ThinkingSphinx::Configuration.instance.app_root.should == "/here/somewhere"
83
+ end
84
+ end
85
+
86
+ describe "initialisation" do
87
+ it "should have a default bin_path of nothing" do
88
+ ThinkingSphinx::Configuration.instance.bin_path.should == ""
89
+ end
90
+
91
+ it "should append a / to bin_path if one is supplied" do
92
+ @settings = {
93
+ "development" => {
94
+ "bin_path" => "path/to/somewhere"
95
+ }
96
+ }
97
+
98
+ open("#{RAILS_ROOT}/config/sphinx.yml", "w") do |f|
99
+ f.write YAML.dump(@settings)
100
+ end
101
+
102
+ ThinkingSphinx::Configuration.instance.send(:parse_config)
103
+ ThinkingSphinx::Configuration.instance.bin_path.should match(/\/$/)
104
+ end
105
+ end
106
+
107
+ describe "index options" do
108
+ before :each do
109
+ @settings = {
110
+ "development" => {"disable_range" => true}
111
+ }
112
+
113
+ open("#{RAILS_ROOT}/config/sphinx.yml", "w") do |f|
114
+ f.write YAML.dump(@settings)
115
+ end
116
+
117
+ @config = ThinkingSphinx::Configuration.instance
118
+ @config.send(:parse_config)
119
+ end
120
+
121
+ it "should collect disable_range" do
122
+ @config.index_options[:disable_range].should be_true
123
+ end
124
+ end
125
+
126
+ describe "#load_models" do
127
+ before :each do
128
+ @config = ThinkingSphinx::Configuration.instance
129
+ @config.model_directories = ['']
130
+
131
+ @file_name = 'a.rb'
132
+ @model_name_lower = 'a'
133
+ @class_name = 'A'
134
+
135
+ @file_name.stub!(:gsub).and_return(@model_name_lower)
136
+ @model_name_lower.stub!(:camelize).and_return(@class_name)
137
+ Dir.stub(:[]).and_return([@file_name])
138
+ end
139
+
140
+ it "should load the files by guessing the file name" do
141
+ @class_name.should_receive(:constantize).and_return(true)
142
+
143
+ @config.load_models
144
+ end
145
+
146
+ it "should not raise errors if the model name is nil" do
147
+ @file_name.stub!(:gsub).and_return(nil)
148
+
149
+ lambda {
150
+ @config.load_models
151
+ }.should_not raise_error
152
+ end
153
+
154
+ it "should not raise errors if the file name does not represent a class name" do
155
+ @class_name.should_receive(:constantize).and_raise(NameError)
156
+
157
+ lambda {
158
+ @config.load_models
159
+ }.should_not raise_error
160
+ end
161
+
162
+ it "should retry if the first pass fails and contains a directory" do
163
+ @model_name_lower.stub!(:gsub!).and_return(true, nil)
164
+ @class_name.stub(:constantize).and_raise(LoadError)
165
+ @model_name_lower.should_receive(:camelize).twice
166
+
167
+ lambda {
168
+ @config.load_models
169
+ }.should_not raise_error
170
+ end
171
+
172
+ it "should catch database errors with a warning" do
173
+ @class_name.should_receive(:constantize).and_raise(Mysql::Error)
174
+ @config.should_receive(:puts).with('Warning: Error loading a.rb')
175
+
176
+ lambda {
177
+ @config.load_models
178
+ }.should_not raise_error
179
+ end
180
+ end
181
+
182
+ it "should insert set index options into the configuration file" do
183
+ config = ThinkingSphinx::Configuration.instance
184
+ ThinkingSphinx::Configuration::IndexOptions.each do |option|
185
+ config.index_options[option.to_sym] = "something"
186
+ config.build
187
+
188
+ file = open(config.config_file) { |f| f.read }
189
+ file.should match(/#{option}\s+= something/)
190
+
191
+ config.index_options[option.to_sym] = nil
192
+ end
193
+ end
194
+
195
+ it "should insert set source options into the configuration file" do
196
+ config = ThinkingSphinx::Configuration.instance
197
+ ThinkingSphinx::Configuration::SourceOptions.each do |option|
198
+ config.source_options[option.to_sym] = "something"
199
+ config.build
200
+
201
+ file = open(config.config_file) { |f| f.read }
202
+ file.should match(/#{option}\s+= something/)
203
+
204
+ config.source_options[option.to_sym] = nil
205
+ end
206
+ end
207
+
208
+ it "should set any explicit prefixed or infixed fields" do
209
+ file = open(ThinkingSphinx::Configuration.instance.config_file) { |f|
210
+ f.read
211
+ }
212
+ file.should match(/prefix_fields\s+= city/)
213
+ file.should match(/infix_fields\s+= state/)
214
+ end
215
+
216
+ it "should not have prefix fields in indexes where nothing is set" do
217
+ file = open(ThinkingSphinx::Configuration.instance.config_file) { |f|
218
+ f.read
219
+ }
220
+ file.should_not match(/index alpha_core\s+\{\s+[^\}]*prefix_fields\s+=[^\}]*\}/m)
221
+ end
222
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe String do
4
+ describe "to_crc32 instance method" do
5
+ it "should return an integer" do
6
+ 'to_crc32'.to_crc32.should be_a_kind_of(Integer)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,64 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe ThinkingSphinx::FacetCollection do
4
+ before do
5
+ @facet_collection = ThinkingSphinx::FacetCollection.new([])
6
+ end
7
+
8
+ # TODO fix nasty hack when we have internet!
9
+ def mock_results
10
+ return @results if defined? @results
11
+ @result = Person.find(:first)
12
+ @results = [@result]
13
+ @results.stub!(:each_with_groupby_and_count).and_yield(@result, @result.city.to_crc32, 1)
14
+ @results
15
+ end
16
+
17
+ describe "#add_from_results" do
18
+ describe "with empty result set" do
19
+ before do
20
+ @facet_collection.add_from_results('attribute_facet', [])
21
+ end
22
+
23
+ it "should add key as attribute" do
24
+ @facet_collection.should have_key(:attribute)
25
+ end
26
+
27
+ it "should return an empty hash for the facet results" do
28
+ @facet_collection[:attribute].should be_empty
29
+ end
30
+ end
31
+
32
+ describe "with non-empty result set" do
33
+ before do
34
+ @facet_collection.add_from_results('city_facet', mock_results)
35
+ end
36
+
37
+ it "should return a hash" do
38
+ @facet_collection.should be_a_kind_of(Hash)
39
+ end
40
+
41
+ it "should add key as attribute" do
42
+ @facet_collection.keys.should include(:city)
43
+ end
44
+
45
+ it "should return a hash" do
46
+ @facet_collection[:city].should == {@result.city => 1}
47
+ end
48
+ end
49
+ end
50
+
51
+ describe "#for" do
52
+ before do
53
+ @facet_collection.add_from_results('city_facet', mock_results)
54
+ end
55
+
56
+ it "should return the search results for the attribute and key pair" do
57
+ ThinkingSphinx::Search.should_receive(:search) do |options|
58
+ options[:with].should have_key('city_facet')
59
+ options[:with]['city_facet'].should == @result.city.to_crc32
60
+ end
61
+ @facet_collection.for(:city => @result.city)
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,302 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe ThinkingSphinx::Facet do
4
+ describe ".name_for" do
5
+ it "should remove '_facet' from provided string and return a symbol" do
6
+ ThinkingSphinx::Facet.name_for('attribute_facet').should == :attribute
7
+ end
8
+
9
+ it "should remove '_facet' from provided symbol" do
10
+ ThinkingSphinx::Facet.name_for(:attribute_facet).should == :attribute
11
+ end
12
+
13
+ it "should return the name of the facet if a Facet is passed" do
14
+ facet = ThinkingSphinx::Facet.new(
15
+ ThinkingSphinx::Attribute.stub_instance(:unique_name => :attribute, :columns => ['attribute'])
16
+ )
17
+ ThinkingSphinx::Facet.name_for(facet).should == :attribute
18
+ end
19
+
20
+ it "should return 'class' for special case name 'class_crc'" do
21
+ ThinkingSphinx::Facet.name_for(:class_crc).should == :class
22
+ end
23
+
24
+ it "should cycle" do
25
+ ThinkingSphinx::Facet.name_for(ThinkingSphinx::Facet.attribute_name_for(:attribute)).should == :attribute
26
+ end
27
+ end
28
+
29
+ describe ".attribute_name_for" do
30
+ it "should append '_facet' to provided string" do
31
+ ThinkingSphinx::Facet.attribute_name_for('attribute').should == 'attribute_facet'
32
+ end
33
+
34
+ it "should append '_facet' to provided symbol and return a string" do
35
+ ThinkingSphinx::Facet.attribute_name_for(:attribute).should == 'attribute_facet'
36
+ end
37
+
38
+ it "should return 'class_crc' for special case attribute 'class'" do
39
+ ThinkingSphinx::Facet.attribute_name_for(:class).should == 'class_crc'
40
+ end
41
+
42
+ it "should cycle" do
43
+ ThinkingSphinx::Facet.attribute_name_for(ThinkingSphinx::Facet.name_for('attribute_facet')).should == 'attribute_facet'
44
+ end
45
+ end
46
+
47
+ describe ".attribute_name_from_value" do
48
+ it "should append _facet if the value is a string" do
49
+ ThinkingSphinx::Facet.attribute_name_from_value('attribute', 'string').
50
+ should == 'attribute_facet'
51
+ end
52
+
53
+ it "should not append _facet if the value isn't a string" do
54
+ ThinkingSphinx::Facet.attribute_name_from_value('attribute', 1).
55
+ should == 'attribute'
56
+ ThinkingSphinx::Facet.attribute_name_from_value('attribute', Time.now).
57
+ should == 'attribute'
58
+ ThinkingSphinx::Facet.attribute_name_from_value('attribute', true).
59
+ should == 'attribute'
60
+ ThinkingSphinx::Facet.attribute_name_from_value('attribute', 1.23).
61
+ should == 'attribute'
62
+ end
63
+
64
+ it "should append _facet is the value is an array of strings" do
65
+ ThinkingSphinx::Facet.attribute_name_from_value('attribute', ['a', 'b']).
66
+ should == 'attribute_facet'
67
+ end
68
+
69
+ it "should not append _facet if the value is an array of integers" do
70
+ ThinkingSphinx::Facet.attribute_name_from_value('attribute', [1, 2]).
71
+ should == 'attribute'
72
+ end
73
+ end
74
+
75
+ describe ".translate?" do
76
+ before :each do
77
+ @index = ThinkingSphinx::Index.new(Alpha)
78
+ @source = ThinkingSphinx::Source.new(@index)
79
+ @attribute = ThinkingSphinx::Attribute.new(
80
+ @source, ThinkingSphinx::Index::FauxColumn.new(:name)
81
+ )
82
+ end
83
+
84
+ it "should return true if the property is a field" do
85
+ field = ThinkingSphinx::Field.new(
86
+ @source, ThinkingSphinx::Index::FauxColumn.new(:name)
87
+ )
88
+
89
+ ThinkingSphinx::Facet.translate?(field).should be_true
90
+ end
91
+
92
+ it "should return true if the property is a string attribute" do
93
+ @attribute.stub_method(:type => :string)
94
+
95
+ ThinkingSphinx::Facet.translate?(@attribute).should be_true
96
+ end
97
+
98
+ it "should return false if the property is an integer attribute" do
99
+ @attribute.stub_method(:type => :integer)
100
+
101
+ ThinkingSphinx::Facet.translate?(@attribute).should be_false
102
+ end
103
+
104
+ it "should return false if the property is a boolean attribute" do
105
+ @attribute.stub_method(:type => :boolean)
106
+
107
+ ThinkingSphinx::Facet.translate?(@attribute).should be_false
108
+ end
109
+
110
+ it "should return false if the property is a timestamp attribute" do
111
+ @attribute.stub_method(:type => :datetime)
112
+
113
+ ThinkingSphinx::Facet.translate?(@attribute).should be_false
114
+ end
115
+
116
+ it "should return false if the property is a float attribute" do
117
+ @attribute.stub_method(:type => :float)
118
+
119
+ ThinkingSphinx::Facet.translate?(@attribute).should be_false
120
+ end
121
+
122
+ it "should return false if the property is an MVA of integer values" do
123
+ @attribute.stub_method(:type => :multi, :all_ints? => true)
124
+
125
+ ThinkingSphinx::Facet.translate?(@attribute).should be_false
126
+ end
127
+
128
+ it "should return true if the property is an MVA of string values" do
129
+ @attribute.stub_method(:type => :multi, :all_ints? => false)
130
+
131
+ ThinkingSphinx::Facet.translate?(@attribute).should be_true
132
+ end
133
+ end
134
+
135
+ describe "#translate?" do
136
+ before :each do
137
+ @index = ThinkingSphinx::Index.new(Alpha)
138
+ @source = ThinkingSphinx::Source.new(@index)
139
+ @attribute = ThinkingSphinx::Attribute.new(
140
+ @source, ThinkingSphinx::Index::FauxColumn.new(:name)
141
+ )
142
+ end
143
+
144
+ it "should return true if the property is a field" do
145
+ field = ThinkingSphinx::Field.new(
146
+ @source, ThinkingSphinx::Index::FauxColumn.new(:name)
147
+ )
148
+
149
+ ThinkingSphinx::Facet.new(field).translate?.should be_true
150
+ end
151
+
152
+ it "should return true if the property is a string attribute" do
153
+ @attribute.stub_method(:type => :string)
154
+
155
+ ThinkingSphinx::Facet.new(@attribute).translate?.should be_true
156
+ end
157
+
158
+ it "should return false if the property is an integer attribute" do
159
+ @attribute.stub_method(:type => :integer)
160
+
161
+ ThinkingSphinx::Facet.new(@attribute).translate?.should be_false
162
+ end
163
+
164
+ it "should return false if the property is a boolean attribute" do
165
+ @attribute.stub_method(:type => :boolean)
166
+
167
+ ThinkingSphinx::Facet.new(@attribute).translate?.should be_false
168
+ end
169
+
170
+ it "should return false if the property is a timestamp attribute" do
171
+ @attribute.stub_method(:type => :datetime)
172
+
173
+ ThinkingSphinx::Facet.new(@attribute).translate?.should be_false
174
+ end
175
+
176
+ it "should return false if the property is a float attribute" do
177
+ @attribute.stub_method(:type => :float)
178
+
179
+ ThinkingSphinx::Facet.new(@attribute).translate?.should be_false
180
+ end
181
+
182
+ it "should return false if the property is an MVA of integer values" do
183
+ @attribute.stub_method(:type => :multi, :all_ints? => true)
184
+
185
+ ThinkingSphinx::Facet.new(@attribute).translate?.should be_false
186
+ end
187
+
188
+ it "should return true if the property is an MVA of string values" do
189
+ @attribute.stub_method(:type => :multi, :all_ints? => false)
190
+
191
+ ThinkingSphinx::Facet.new(@attribute).translate?.should be_true
192
+ end
193
+ end
194
+
195
+ describe "#attribute_name" do
196
+ before :each do
197
+ @index = ThinkingSphinx::Index.new(Alpha)
198
+ @source = ThinkingSphinx::Source.new(@index)
199
+ @attribute = ThinkingSphinx::Attribute.new(
200
+ @source, ThinkingSphinx::Index::FauxColumn.new(:name)
201
+ )
202
+ end
203
+
204
+ it "should return the attribute name if built off an integer attribute" do
205
+ @attribute.stub_method(:type => :integer)
206
+
207
+ ThinkingSphinx::Facet.new(@attribute).attribute_name.should == "name"
208
+ end
209
+
210
+ it "should return the attribute name if built off a boolean attribute" do
211
+ @attribute.stub_method(:type => :boolean)
212
+
213
+ ThinkingSphinx::Facet.new(@attribute).attribute_name.should == "name"
214
+ end
215
+
216
+ it "should return the attribute name if built off a float attribute" do
217
+ @attribute.stub_method(:type => :float)
218
+
219
+ ThinkingSphinx::Facet.new(@attribute).attribute_name.should == "name"
220
+ end
221
+
222
+ it "should return the attribute name if built off a timestamp attribute" do
223
+ @attribute.stub_method(:type => :datetime)
224
+
225
+ ThinkingSphinx::Facet.new(@attribute).attribute_name.should == "name"
226
+ end
227
+
228
+ it "should return the attribute name with _facet suffix if built off a string attribute" do
229
+ @attribute.stub_method(:type => :string)
230
+
231
+ ThinkingSphinx::Facet.new(@attribute).attribute_name.should == "name_facet"
232
+ end
233
+
234
+ it "should return the attribute name with _facet suffix if built off a field" do
235
+ field = ThinkingSphinx::Field.new(
236
+ @source, ThinkingSphinx::Index::FauxColumn.new(:name)
237
+ )
238
+
239
+ ThinkingSphinx::Facet.new(field).attribute_name.should == "name_facet"
240
+ end
241
+
242
+ it "should return the attribute name if build off an integer MVA" do
243
+ @attribute.stub_method(:type => :multi, :all_ints? => true)
244
+
245
+ ThinkingSphinx::Facet.new(@attribute).attribute_name.should == "name"
246
+ end
247
+
248
+ it "should return the attribute name with the _facet suffix if build off an non-integer MVA" do
249
+ @attribute.stub_method(:type => :multi, :all_ints? => false)
250
+
251
+ ThinkingSphinx::Facet.new(@attribute).attribute_name.should == "name_facet"
252
+ end
253
+ end
254
+
255
+ describe "#type" do
256
+ before :each do
257
+ @index = ThinkingSphinx::Index.new(Alpha)
258
+ @source = ThinkingSphinx::Source.new(@index)
259
+ end
260
+
261
+ it "should return :string if the property is a field" do
262
+ field = ThinkingSphinx::Field.new(
263
+ @source, ThinkingSphinx::Index::FauxColumn.new(:name)
264
+ )
265
+
266
+ ThinkingSphinx::Facet.new(field).type.should == :string
267
+ end
268
+
269
+ it "should return the attribute type if the property is an attribute" do
270
+ attribute = ThinkingSphinx::Attribute.new(
271
+ @source, ThinkingSphinx::Index::FauxColumn.new(:name)
272
+ )
273
+ attribute.stub_method(:type => :anything)
274
+
275
+ ThinkingSphinx::Facet.new(attribute).type.should == :anything
276
+ end
277
+ end
278
+
279
+ describe "#value" do
280
+ before :each do
281
+ @index = ThinkingSphinx::Index.new(Friendship)
282
+ @source = ThinkingSphinx::Source.new(@index)
283
+ @field = ThinkingSphinx::Field.new(
284
+ @source, ThinkingSphinx::Index::FauxColumn.new(:person, :first_name)
285
+ )
286
+ @facet = ThinkingSphinx::Facet.new(@field)
287
+ end
288
+
289
+ it "should return association values" do
290
+ person = Person.find(:first)
291
+ friendship = Friendship.new(:person => person)
292
+
293
+ @facet.value(friendship, 1).should == person.first_name
294
+ end
295
+
296
+ it "should return nil if the association is nil" do
297
+ friendship = Friendship.new(:person => nil)
298
+
299
+ @facet.value(friendship, 1).should be_nil
300
+ end
301
+ end
302
+ end