freelancing-god-thinking-sphinx 0.9.6 → 0.9.7
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.
- data/README +23 -1
- data/lib/thinking_sphinx.rb +4 -1
- data/lib/thinking_sphinx/active_record.rb +19 -0
- data/lib/thinking_sphinx/active_record/delta.rb +4 -0
- data/lib/thinking_sphinx/association.rb +5 -5
- data/lib/thinking_sphinx/attribute.rb +5 -2
- data/lib/thinking_sphinx/configuration.rb +86 -104
- data/lib/thinking_sphinx/field.rb +17 -5
- data/lib/thinking_sphinx/index.rb +71 -2
- data/lib/thinking_sphinx/index/builder.rb +5 -5
- data/lib/thinking_sphinx/search.rb +7 -1
- data/spec/unit/thinking_sphinx/active_record/delta_spec.rb +4 -0
- data/spec/unit/thinking_sphinx/active_record/search_spec.rb +63 -0
- data/spec/unit/thinking_sphinx/active_record_spec.rb +74 -2
- data/spec/unit/thinking_sphinx/association_spec.rb +247 -0
- data/spec/unit/thinking_sphinx/attribute_spec.rb +285 -2
- data/spec/unit/thinking_sphinx/configuration_spec.rb +431 -0
- data/spec/unit/thinking_sphinx/field_spec.rb +169 -5
- data/spec/unit/thinking_sphinx/index_spec.rb +186 -1
- data/spec/unit/thinking_sphinx_spec.rb +25 -0
- metadata +2 -2
@@ -37,6 +37,57 @@ module ThinkingSphinx
|
|
37
37
|
initialize_from_builder(&block) if block_given?
|
38
38
|
end
|
39
39
|
|
40
|
+
def to_config(index, database_conf, charset_type)
|
41
|
+
# Set up associations and joins
|
42
|
+
link!
|
43
|
+
|
44
|
+
attr_sources = attributes.collect { |attrib|
|
45
|
+
attrib.to_sphinx_clause
|
46
|
+
}.join("\n ")
|
47
|
+
|
48
|
+
db_adapter = case adapter
|
49
|
+
when :postgres
|
50
|
+
"pgsql"
|
51
|
+
when :mysql
|
52
|
+
"mysql"
|
53
|
+
else
|
54
|
+
raise "Unsupported Database Adapter: Sphinx only supports MySQL and PosgreSQL"
|
55
|
+
end
|
56
|
+
|
57
|
+
config = <<-SOURCE
|
58
|
+
|
59
|
+
source #{model.name.downcase}_#{index}_core
|
60
|
+
{
|
61
|
+
type = #{db_adapter}
|
62
|
+
sql_host = #{database_conf[:host] || "localhost"}
|
63
|
+
sql_user = #{database_conf[:username]}
|
64
|
+
sql_pass = #{database_conf[:password]}
|
65
|
+
sql_db = #{database_conf[:database]}
|
66
|
+
|
67
|
+
sql_query_pre = #{charset_type == "utf-8" && adapter == :mysql ? "SET NAMES utf8" : ""}
|
68
|
+
sql_query_pre = #{to_sql_query_pre}
|
69
|
+
sql_query = #{to_sql.gsub(/\n/, ' ')}
|
70
|
+
sql_query_range = #{to_sql_query_range}
|
71
|
+
sql_query_info = #{to_sql_query_info}
|
72
|
+
#{attr_sources}
|
73
|
+
}
|
74
|
+
SOURCE
|
75
|
+
|
76
|
+
if delta?
|
77
|
+
config += <<-SOURCE
|
78
|
+
|
79
|
+
source #{model.name.downcase}_#{index}_delta : #{model.name.downcase}_#{index}_core
|
80
|
+
{
|
81
|
+
sql_query_pre =
|
82
|
+
sql_query = #{to_sql(:delta => true).gsub(/\n/, ' ')}
|
83
|
+
sql_query_range = #{to_sql_query_range :delta => true}
|
84
|
+
}
|
85
|
+
SOURCE
|
86
|
+
end
|
87
|
+
|
88
|
+
config
|
89
|
+
end
|
90
|
+
|
40
91
|
# Link all the fields and associations to their corresponding
|
41
92
|
# associations and joins. This _must_ be called before interrogating
|
42
93
|
# the index's fields and associations for anything that may reference
|
@@ -86,7 +137,7 @@ module ThinkingSphinx
|
|
86
137
|
where_clause << " AND " << @conditions.join(" AND ")
|
87
138
|
end
|
88
139
|
|
89
|
-
<<-SQL
|
140
|
+
sql = <<-SQL
|
90
141
|
SELECT #{ (
|
91
142
|
["#{@model.quoted_table_name}.#{quote_column(@model.primary_key)}"] +
|
92
143
|
@fields.collect { |field| field.to_select_sql } +
|
@@ -102,8 +153,13 @@ GROUP BY #{ (
|
|
102
153
|
@fields.collect { |field| field.to_group_sql }.compact +
|
103
154
|
@attributes.collect { |attribute| attribute.to_group_sql }.compact
|
104
155
|
).join(", ") }
|
105
|
-
ORDER BY NULL
|
106
156
|
SQL
|
157
|
+
|
158
|
+
if @model.connection.class.name == "ActiveRecord::ConnectionAdapters::MysqlAdapter"
|
159
|
+
sql += " ORDER BY NULL"
|
160
|
+
end
|
161
|
+
|
162
|
+
sql
|
107
163
|
end
|
108
164
|
|
109
165
|
# Simple helper method for the query info SQL - which is a statement that
|
@@ -152,6 +208,14 @@ ORDER BY NULL
|
|
152
208
|
end
|
153
209
|
end
|
154
210
|
|
211
|
+
def prefix_fields
|
212
|
+
@fields.select { |field| field.prefixes }
|
213
|
+
end
|
214
|
+
|
215
|
+
def infix_fields
|
216
|
+
@fields.select { |field| field.infixes }
|
217
|
+
end
|
218
|
+
|
155
219
|
private
|
156
220
|
|
157
221
|
def quote_column(column)
|
@@ -182,6 +246,11 @@ ORDER BY NULL
|
|
182
246
|
:type => :integer,
|
183
247
|
:as => :class_crc
|
184
248
|
)
|
249
|
+
@attributes << Attribute.new(
|
250
|
+
FauxColumn.new("0"),
|
251
|
+
:type => :integer,
|
252
|
+
:as => :sphinx_deleted
|
253
|
+
)
|
185
254
|
end
|
186
255
|
|
187
256
|
# Returns all associations used amongst all the fields and attributes.
|
@@ -48,14 +48,14 @@ module ThinkingSphinx
|
|
48
48
|
# get access down the associations tree.
|
49
49
|
#
|
50
50
|
# indexes :id, :as => :my_id
|
51
|
+
# indexes :name, :sortable => true
|
51
52
|
# indexes first_name, last_name, :sortable => true
|
52
|
-
# indexes name, :sortable => true
|
53
53
|
# indexes users.posts.content, :as => :post_content
|
54
54
|
# indexes users(:id), :as => :user_ids
|
55
55
|
#
|
56
|
-
# Keep in mind that if any keywords for Ruby methods - such as id
|
57
|
-
# clash with your column names, you need to use the symbol
|
58
|
-
# the first and last examples above).
|
56
|
+
# Keep in mind that if any keywords for Ruby methods - such as id or
|
57
|
+
# name - clash with your column names, you need to use the symbol
|
58
|
+
# version (see the first, second and last examples above).
|
59
59
|
#
|
60
60
|
# If you specify multiple columns (example #2), a field will be created
|
61
61
|
# for each. Don't use the :as option in this case. If you want to merge
|
@@ -194,4 +194,4 @@ module ThinkingSphinx
|
|
194
194
|
end
|
195
195
|
end
|
196
196
|
end
|
197
|
-
end
|
197
|
+
end
|
@@ -15,9 +15,12 @@ module ThinkingSphinx
|
|
15
15
|
def search_for_ids(*args)
|
16
16
|
results, client = search_results(*args.clone)
|
17
17
|
|
18
|
+
options = args.extract_options!
|
19
|
+
page = options[:page] ? options[:page].to_i : 1
|
20
|
+
|
18
21
|
begin
|
19
22
|
pager = WillPaginate::Collection.new(page,
|
20
|
-
client.limit, results[:total])
|
23
|
+
client.limit, results[:total] || 0)
|
21
24
|
pager.replace results[:matches].collect { |match| match[:doc] }
|
22
25
|
rescue
|
23
26
|
results[:matches].collect { |match| match[:doc] }
|
@@ -268,6 +271,9 @@ module ThinkingSphinx
|
|
268
271
|
|
269
272
|
client.anchor = anchor_conditions(klass, options) || {} if client.anchor.empty?
|
270
273
|
|
274
|
+
client.filters << Riddle::Client::Filter.new(
|
275
|
+
"sphinx_deleted", [0]
|
276
|
+
)
|
271
277
|
# class filters
|
272
278
|
client.filters << Riddle::Client::Filter.new(
|
273
279
|
"class_crc", options[:classes].collect { |klass| klass.to_crc32 }
|
@@ -17,6 +17,10 @@ describe "ThinkingSphinx::ActiveRecord::Delta" do
|
|
17
17
|
:after_commit, [:toggle_delta]
|
18
18
|
)
|
19
19
|
end
|
20
|
+
|
21
|
+
it "should have an after_commit method by default" do
|
22
|
+
Person.instance_methods.should include("after_commit")
|
23
|
+
end
|
20
24
|
end
|
21
25
|
|
22
26
|
describe "save_with_after_commit_callback method" do
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe "ThinkingSphinx::ActiveRecord::Search" do
|
4
|
+
it "should add search_for_ids to ActiveRecord::Base" do
|
5
|
+
ActiveRecord::Base.methods.should include("search_for_ids")
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should add search_for_ids to ActiveRecord::Base" do
|
9
|
+
ActiveRecord::Base.methods.should include("search")
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "search_for_ids method" do
|
13
|
+
before :each do
|
14
|
+
ThinkingSphinx::Search.stub_method(:search_for_ids => true)
|
15
|
+
end
|
16
|
+
|
17
|
+
after :each do
|
18
|
+
ThinkingSphinx::Search.unstub_method(:search_for_ids)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should call ThinkingSphinx::Search#search_for_ids with the class option set" do
|
22
|
+
Person.search_for_ids("search")
|
23
|
+
|
24
|
+
ThinkingSphinx::Search.should have_received(:search_for_ids).with(
|
25
|
+
"search", :class => Person
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should override the class option" do
|
30
|
+
Person.search_for_ids("search", :class => Friendship)
|
31
|
+
|
32
|
+
ThinkingSphinx::Search.should have_received(:search_for_ids).with(
|
33
|
+
"search", :class => Person
|
34
|
+
)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "search method" do
|
39
|
+
before :each do
|
40
|
+
ThinkingSphinx::Search.stub_method(:search => true)
|
41
|
+
end
|
42
|
+
|
43
|
+
after :each do
|
44
|
+
ThinkingSphinx::Search.unstub_method(:search)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should call ThinkingSphinx::Search#search with the class option set" do
|
48
|
+
Person.search("search")
|
49
|
+
|
50
|
+
ThinkingSphinx::Search.should have_received(:search).with(
|
51
|
+
"search", :class => Person
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should override the class option" do
|
56
|
+
Person.search("search", :class => Friendship)
|
57
|
+
|
58
|
+
ThinkingSphinx::Search.should have_received(:search).with(
|
59
|
+
"search", :class => Person
|
60
|
+
)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -8,8 +8,9 @@ describe "ThinkingSphinx::ActiveRecord" do
|
|
8
8
|
end
|
9
9
|
|
10
10
|
TestModule::TestModel.stub_methods(
|
11
|
-
:before_save
|
12
|
-
:after_commit
|
11
|
+
:before_save => true,
|
12
|
+
:after_commit => true,
|
13
|
+
:after_destroy => true
|
13
14
|
)
|
14
15
|
|
15
16
|
@index = ThinkingSphinx::Index.stub_instance(:delta? => false)
|
@@ -19,6 +20,8 @@ describe "ThinkingSphinx::ActiveRecord" do
|
|
19
20
|
after :each do
|
20
21
|
# Remove the class so we can redefine it
|
21
22
|
TestModule.send(:remove_const, :TestModel)
|
23
|
+
|
24
|
+
ThinkingSphinx::Index.unstub_method(:new)
|
22
25
|
end
|
23
26
|
|
24
27
|
it "should return nil and do nothing if indexes are disabled" do
|
@@ -72,6 +75,20 @@ describe "ThinkingSphinx::ActiveRecord" do
|
|
72
75
|
TestModule::TestModel.should_not have_received(:after_commit)
|
73
76
|
end
|
74
77
|
|
78
|
+
it "should add an after_destroy hook with delta indexing enabled" do
|
79
|
+
@index.stub_method(:delta? => true)
|
80
|
+
|
81
|
+
TestModule::TestModel.define_index do; end
|
82
|
+
|
83
|
+
TestModule::TestModel.should have_received(:after_destroy).with(:toggle_deleted)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should add an after_destroy hook with delta indexing disabled" do
|
87
|
+
TestModule::TestModel.define_index do; end
|
88
|
+
|
89
|
+
TestModule::TestModel.should have_received(:after_destroy).with(:toggle_deleted)
|
90
|
+
end
|
91
|
+
|
75
92
|
it "should return the new index" do
|
76
93
|
TestModule::TestModel.define_index.should == @index
|
77
94
|
end
|
@@ -82,4 +99,59 @@ describe "ThinkingSphinx::ActiveRecord" do
|
|
82
99
|
Person.to_crc32.should be_a_kind_of(Integer)
|
83
100
|
end
|
84
101
|
end
|
102
|
+
|
103
|
+
describe "toggle_deleted method" do
|
104
|
+
before :each do
|
105
|
+
@configuration = ThinkingSphinx::Configuration.stub_instance(
|
106
|
+
:address => "an address",
|
107
|
+
:port => 123
|
108
|
+
)
|
109
|
+
@client = Riddle::Client.stub_instance(:update => true)
|
110
|
+
@person = Person.new
|
111
|
+
|
112
|
+
ThinkingSphinx::Configuration.stub_method(:new => @configuration)
|
113
|
+
Riddle::Client.stub_method(:new => @client)
|
114
|
+
Person.indexes.each { |index| index.stub_method(:delta? => false) }
|
115
|
+
end
|
116
|
+
|
117
|
+
after :each do
|
118
|
+
ThinkingSphinx::Configuration.unstub_method(:new)
|
119
|
+
Riddle::Client.unstub_method(:new)
|
120
|
+
Person.indexes.each { |index| index.unstub_method(:delta?) }
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should create a client using the Configuration's address and port" do
|
124
|
+
@person.toggle_deleted
|
125
|
+
|
126
|
+
Riddle::Client.should have_received(:new).with(
|
127
|
+
@configuration.address, @configuration.port
|
128
|
+
)
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should update the core index's deleted flag" do
|
132
|
+
@person.toggle_deleted
|
133
|
+
|
134
|
+
@client.should have_received(:update).with(
|
135
|
+
"person_core", ["sphinx_deleted"], {@person.id => 1}
|
136
|
+
)
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should update the delta index's deleted flag if delta indexing is enabled" do
|
140
|
+
Person.indexes.each { |index| index.stub_method(:delta? => true) }
|
141
|
+
|
142
|
+
@person.toggle_deleted
|
143
|
+
|
144
|
+
@client.should have_received(:update).with(
|
145
|
+
"person_delta", ["sphinx_deleted"], {@person.id => 1}
|
146
|
+
)
|
147
|
+
end
|
148
|
+
|
149
|
+
it "shouldn't update the delta index if delta indexing is disabled" do
|
150
|
+
@person.toggle_deleted
|
151
|
+
|
152
|
+
@client.should_not have_received(:update).with(
|
153
|
+
"person_delta", ["sphinx_deleted"], {@person.id => 1}
|
154
|
+
)
|
155
|
+
end
|
156
|
+
end
|
85
157
|
end
|
@@ -0,0 +1,247 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe ThinkingSphinx::Association do
|
4
|
+
describe "class-level children method" do
|
5
|
+
before :each do
|
6
|
+
@normal_reflection = ::ActiveRecord::Reflection::AssociationReflection.stub_instance(
|
7
|
+
:options => {:polymorphic => false}
|
8
|
+
)
|
9
|
+
@normal_association = ThinkingSphinx::Association.stub_instance
|
10
|
+
@poly_reflection = ::ActiveRecord::Reflection::AssociationReflection.stub_instance(
|
11
|
+
:options => {:polymorphic => true},
|
12
|
+
:macro => :has_many,
|
13
|
+
:name => "polly",
|
14
|
+
:active_record => "AR"
|
15
|
+
)
|
16
|
+
@non_poly_reflection = ::ActiveRecord::Reflection::AssociationReflection.stub_instance
|
17
|
+
|
18
|
+
Person.stub_method(:reflect_on_association => @normal_reflection)
|
19
|
+
ThinkingSphinx::Association.stub_methods(
|
20
|
+
:new => @normal_association,
|
21
|
+
:polymorphic_classes => [Person, Person],
|
22
|
+
:casted_options => {:casted => :options}
|
23
|
+
)
|
24
|
+
::ActiveRecord::Reflection::AssociationReflection.stub_method(
|
25
|
+
:new => @non_poly_reflection
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should return an empty array if no association exists" do
|
30
|
+
Person.stub_method(:reflect_on_association => nil)
|
31
|
+
|
32
|
+
ThinkingSphinx::Association.children(Person, :assoc).should == []
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should return a single association instance in an array if assocation isn't polymorphic" do
|
36
|
+
ThinkingSphinx::Association.children(Person, :assoc).should == [@normal_association]
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should return multiple association instances for polymorphic associations" do
|
40
|
+
Person.stub_method(:reflect_on_association => @poly_reflection)
|
41
|
+
|
42
|
+
ThinkingSphinx::Association.children(Person, :assoc).should ==
|
43
|
+
[@normal_association, @normal_association]
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should generate non-polymorphic 'casted' associations for each polymorphic possibility" do
|
47
|
+
Person.stub_method(:reflect_on_association => @poly_reflection)
|
48
|
+
|
49
|
+
ThinkingSphinx::Association.children(Person, :assoc)
|
50
|
+
|
51
|
+
ThinkingSphinx::Association.should have_received(:casted_options).with(
|
52
|
+
Person, @poly_reflection
|
53
|
+
).twice
|
54
|
+
|
55
|
+
::ActiveRecord::Reflection::AssociationReflection.should have_received(:new).with(
|
56
|
+
:has_many, :polly_Person, {:casted => :options}, "AR"
|
57
|
+
).twice
|
58
|
+
|
59
|
+
ThinkingSphinx::Association.should have_received(:new).with(
|
60
|
+
nil, @non_poly_reflection
|
61
|
+
).twice
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "instance-level children method" do
|
66
|
+
it "should return the children associations for the given association" do
|
67
|
+
@reflection = ::ActiveRecord::Reflection::AssociationReflection.stub_instance(
|
68
|
+
:klass => :klass
|
69
|
+
)
|
70
|
+
@association = ThinkingSphinx::Association.new(nil, @reflection)
|
71
|
+
ThinkingSphinx::Association.stub_method(:children => :result)
|
72
|
+
|
73
|
+
@association.children(:assoc).should == :result
|
74
|
+
ThinkingSphinx::Association.should have_received(:children).with(:klass, :assoc, @association)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "join_to method" do
|
79
|
+
before :each do
|
80
|
+
@parent_join = ::ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation.stub_instance
|
81
|
+
@join = ::ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation.stub_instance
|
82
|
+
@parent = ThinkingSphinx::Association.stub_instance(:join_to => true, :join => nil)
|
83
|
+
@base_join = Object.stub_instance(:joins => [:a, :b, :c])
|
84
|
+
|
85
|
+
::ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation.stub_method(:new => @join)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should call the parent's join_to if parent has no join" do
|
89
|
+
@assoc = ThinkingSphinx::Association.new(@parent, :ref)
|
90
|
+
|
91
|
+
@assoc.join_to(@base_join)
|
92
|
+
|
93
|
+
@parent.should have_received(:join_to).with(@base_join)
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should not call the parent's join_to if it already has a join" do
|
97
|
+
@assoc = ThinkingSphinx::Association.new(@parent, :ref)
|
98
|
+
@parent.stub_method(:join => @parent_join)
|
99
|
+
|
100
|
+
@assoc.join_to(@base_join)
|
101
|
+
|
102
|
+
@parent.should_not have_received(:join_to)
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should define the join association with a JoinAssociation instance" do
|
106
|
+
@assoc = ThinkingSphinx::Association.new(@parent, :ref)
|
107
|
+
|
108
|
+
@assoc.join_to(@base_join).should == @join
|
109
|
+
@assoc.join.should == @join
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe "to_sql method" do
|
114
|
+
before :each do
|
115
|
+
@reflection = ::ActiveRecord::Reflection::AssociationReflection.stub_instance(
|
116
|
+
:klass => Person
|
117
|
+
)
|
118
|
+
@association = ThinkingSphinx::Association.new(nil, @reflection)
|
119
|
+
@parent = Object.stub_instance(:aliased_table_name => "ALIAS TABLE NAME")
|
120
|
+
@join = ::ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation.stub_instance(
|
121
|
+
:association_join => "full association join SQL",
|
122
|
+
:parent => @parent
|
123
|
+
)
|
124
|
+
@association.join = @join
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should return the join's association join value" do
|
128
|
+
@association.to_sql.should == "full association join SQL"
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should replace ::ts_join_alias:: with the aliased table name" do
|
132
|
+
@join.stub_method(:association_join => "text with ::ts_join_alias:: gone")
|
133
|
+
|
134
|
+
@association.to_sql.should == "text with `ALIAS TABLE NAME` gone"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe "is_many? method" do
|
139
|
+
before :each do
|
140
|
+
@parent = ThinkingSphinx::Association.stub_instance(
|
141
|
+
:is_many? => :parent_is_many
|
142
|
+
)
|
143
|
+
@reflection = ::ActiveRecord::Reflection::AssociationReflection.stub_instance(
|
144
|
+
:macro => :has_many
|
145
|
+
)
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should return true if association is either a has_many or a habtm" do
|
149
|
+
association = ThinkingSphinx::Association.new(@parent, @reflection)
|
150
|
+
association.is_many?.should be_true
|
151
|
+
|
152
|
+
@reflection.stub_method(:macro => :has_and_belongs_to_many)
|
153
|
+
association.is_many?.should be_true
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should return the parent value if not a has many or habtm and there is a parent" do
|
157
|
+
association = ThinkingSphinx::Association.new(@parent, @reflection)
|
158
|
+
@reflection.stub_method(:macro => :belongs_to)
|
159
|
+
association.is_many?.should == :parent_is_many
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should return false if no parent and not a has many or habtm" do
|
163
|
+
association = ThinkingSphinx::Association.new(nil, @reflection)
|
164
|
+
@reflection.stub_method(:macro => :belongs_to)
|
165
|
+
association.is_many?.should be_false
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
describe "ancestors method" do
|
170
|
+
it "should return an array of associations - including all parents" do
|
171
|
+
parent = ThinkingSphinx::Association.stub_instance(:ancestors => [:all, :ancestors])
|
172
|
+
association = ThinkingSphinx::Association.new(parent, @reflection)
|
173
|
+
association.ancestors.should == [:all, :ancestors, association]
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
describe "polymorphic_classes method" do
|
178
|
+
it "should return all the polymorphic result types as classes" do
|
179
|
+
Person.connection.stub_method(:select_all => [
|
180
|
+
{"person_type" => "Person"},
|
181
|
+
{"person_type" => "Friendship"}
|
182
|
+
])
|
183
|
+
ref = Object.stub_instance(
|
184
|
+
:active_record => Person,
|
185
|
+
:options => {:foreign_type => "person_type"}
|
186
|
+
)
|
187
|
+
|
188
|
+
ThinkingSphinx::Association.send(:polymorphic_classes, ref).should == [Person, Friendship]
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
describe "casted_options method" do
|
193
|
+
before :each do
|
194
|
+
@options = {
|
195
|
+
:foreign_key => "thing_id",
|
196
|
+
:foreign_type => "thing_type",
|
197
|
+
:polymorphic => true
|
198
|
+
}
|
199
|
+
@reflection = ::ActiveRecord::Reflection::AssociationReflection.stub_instance(
|
200
|
+
:options => @options
|
201
|
+
)
|
202
|
+
end
|
203
|
+
|
204
|
+
it "should return a new options set for a specific class" do
|
205
|
+
ThinkingSphinx::Association.send(:casted_options, Person, @reflection).should == {
|
206
|
+
:polymorphic => nil,
|
207
|
+
:class_name => "Person",
|
208
|
+
:foreign_key => "thing_id",
|
209
|
+
:foreign_type => "thing_type",
|
210
|
+
:conditions => "::ts_join_alias::.`thing_type` = 'Person'"
|
211
|
+
}
|
212
|
+
end
|
213
|
+
|
214
|
+
it "should append to existing Array of conditions" do
|
215
|
+
@options[:conditions] = ["first condition"]
|
216
|
+
ThinkingSphinx::Association.send(:casted_options, Person, @reflection).should == {
|
217
|
+
:polymorphic => nil,
|
218
|
+
:class_name => "Person",
|
219
|
+
:foreign_key => "thing_id",
|
220
|
+
:foreign_type => "thing_type",
|
221
|
+
:conditions => ["first condition", "::ts_join_alias::.`thing_type` = 'Person'"]
|
222
|
+
}
|
223
|
+
end
|
224
|
+
|
225
|
+
it "should merge to an existing Hash of conditions" do
|
226
|
+
@options[:conditions] = {"field" => "value"}
|
227
|
+
ThinkingSphinx::Association.send(:casted_options, Person, @reflection).should == {
|
228
|
+
:polymorphic => nil,
|
229
|
+
:class_name => "Person",
|
230
|
+
:foreign_key => "thing_id",
|
231
|
+
:foreign_type => "thing_type",
|
232
|
+
:conditions => {"field" => "value", "thing_type" => "Person"}
|
233
|
+
}
|
234
|
+
end
|
235
|
+
|
236
|
+
it "should append to an existing String of conditions" do
|
237
|
+
@options[:conditions] = "first condition"
|
238
|
+
ThinkingSphinx::Association.send(:casted_options, Person, @reflection).should == {
|
239
|
+
:polymorphic => nil,
|
240
|
+
:class_name => "Person",
|
241
|
+
:foreign_key => "thing_id",
|
242
|
+
:foreign_type => "thing_type",
|
243
|
+
:conditions => "first condition AND ::ts_join_alias::.`thing_type` = 'Person'"
|
244
|
+
}
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|