model_set 0.10.6
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.rdoc +39 -0
- data/VERSION.yml +5 -0
- data/lib/model_set/conditioned.rb +33 -0
- data/lib/model_set/conditions.rb +103 -0
- data/lib/model_set/query.rb +132 -0
- data/lib/model_set/raw_query.rb +41 -0
- data/lib/model_set/raw_sql_query.rb +19 -0
- data/lib/model_set/set_query.rb +34 -0
- data/lib/model_set/solr_query.rb +70 -0
- data/lib/model_set/sphinx_query.rb +206 -0
- data/lib/model_set/sql_base_query.rb +52 -0
- data/lib/model_set/sql_query.rb +109 -0
- data/lib/model_set.rb +743 -0
- data/lib/multi_set.rb +67 -0
- data/test/model_set_test.rb +329 -0
- data/test/multi_set_test.rb +65 -0
- data/test/test_helper.rb +23 -0
- data/vendor/sphinx_client/README.rdoc +41 -0
- data/vendor/sphinx_client/Rakefile +21 -0
- data/vendor/sphinx_client/init.rb +1 -0
- data/vendor/sphinx_client/install.rb +5 -0
- data/vendor/sphinx_client/lib/sphinx/client.rb +1093 -0
- data/vendor/sphinx_client/lib/sphinx/request.rb +50 -0
- data/vendor/sphinx_client/lib/sphinx/response.rb +69 -0
- data/vendor/sphinx_client/lib/sphinx.rb +6 -0
- data/vendor/sphinx_client/spec/client_response_spec.rb +112 -0
- data/vendor/sphinx_client/spec/client_spec.rb +469 -0
- data/vendor/sphinx_client/spec/fixtures/default_search.php +8 -0
- data/vendor/sphinx_client/spec/fixtures/default_search_index.php +8 -0
- data/vendor/sphinx_client/spec/fixtures/excerpt_custom.php +11 -0
- data/vendor/sphinx_client/spec/fixtures/excerpt_default.php +8 -0
- data/vendor/sphinx_client/spec/fixtures/excerpt_flags.php +11 -0
- data/vendor/sphinx_client/spec/fixtures/field_weights.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/filter.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/filter_exclude.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/filter_float_range.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/filter_float_range_exclude.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/filter_range.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/filter_range_exclude.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/filter_range_int64.php +10 -0
- data/vendor/sphinx_client/spec/fixtures/filter_ranges.php +10 -0
- data/vendor/sphinx_client/spec/fixtures/filters.php +10 -0
- data/vendor/sphinx_client/spec/fixtures/filters_different.php +13 -0
- data/vendor/sphinx_client/spec/fixtures/geo_anchor.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/group_by_attr.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/group_by_attrpair.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/group_by_day.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/group_by_day_sort.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/group_by_month.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/group_by_week.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/group_by_year.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/group_distinct.php +10 -0
- data/vendor/sphinx_client/spec/fixtures/id_range.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/id_range64.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/index_weights.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/keywords.php +8 -0
- data/vendor/sphinx_client/spec/fixtures/limits.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/limits_cutoff.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/limits_max.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/limits_max_cutoff.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/match_all.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/match_any.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/match_boolean.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/match_extended.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/match_extended2.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/match_fullscan.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/match_phrase.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/max_query_time.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/miltiple_queries.php +12 -0
- data/vendor/sphinx_client/spec/fixtures/ranking_bm25.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/ranking_none.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/ranking_proximity.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/ranking_proximity_bm25.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/ranking_wordcount.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/retries.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/retries_delay.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/select.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/set_override.php +11 -0
- data/vendor/sphinx_client/spec/fixtures/sort_attr_asc.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/sort_attr_desc.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/sort_expr.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/sort_extended.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/sort_relevance.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/sort_time_segments.php +9 -0
- data/vendor/sphinx_client/spec/fixtures/sphinxapi.php +1269 -0
- data/vendor/sphinx_client/spec/fixtures/update_attributes.php +8 -0
- data/vendor/sphinx_client/spec/fixtures/update_attributes_mva.php +8 -0
- data/vendor/sphinx_client/spec/fixtures/weights.php +9 -0
- data/vendor/sphinx_client/spec/sphinx/sphinx-id64.conf +67 -0
- data/vendor/sphinx_client/spec/sphinx/sphinx.conf +67 -0
- data/vendor/sphinx_client/spec/sphinx/sphinx_test.sql +86 -0
- data/vendor/sphinx_client/sphinx.yml.tpl +3 -0
- data/vendor/sphinx_client/tasks/sphinx.rake +75 -0
- metadata +151 -0
data/lib/multi_set.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
class MultiSet
|
2
|
+
include Enumerable
|
3
|
+
deep_clonable
|
4
|
+
|
5
|
+
attr_accessor :sets
|
6
|
+
|
7
|
+
def initialize(*sets)
|
8
|
+
@sets = sets
|
9
|
+
end
|
10
|
+
|
11
|
+
def add!(other)
|
12
|
+
if other.kind_of?(MultiSet)
|
13
|
+
sets.concat(other.sets)
|
14
|
+
else
|
15
|
+
sets << other
|
16
|
+
end
|
17
|
+
self
|
18
|
+
end
|
19
|
+
|
20
|
+
alias << add!
|
21
|
+
|
22
|
+
def method_missing(method_name, *args)
|
23
|
+
method_name = method_name.to_s
|
24
|
+
if method_name =~ /\!$/
|
25
|
+
sets.each do |set|
|
26
|
+
set.send(method_name, *args)
|
27
|
+
end
|
28
|
+
self
|
29
|
+
else
|
30
|
+
sets.collect do |set|
|
31
|
+
set.send(method_name, *args)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def ids_by_class
|
37
|
+
ids_by_class = {}
|
38
|
+
sets.each do |set|
|
39
|
+
ids_by_class[set.model_class] ||= OrderedSet.new
|
40
|
+
ids_by_class[set.model_class].concat(set.ids)
|
41
|
+
end
|
42
|
+
ids_by_class.keys.each do |model_class|
|
43
|
+
ids_by_class[model_class] = ids_by_class[model_class].to_a
|
44
|
+
end
|
45
|
+
ids_by_class
|
46
|
+
end
|
47
|
+
|
48
|
+
def ids
|
49
|
+
ids = OrderedSet.new
|
50
|
+
sets.each do |set|
|
51
|
+
ids.concat(set.ids)
|
52
|
+
end
|
53
|
+
ids.to_a
|
54
|
+
end
|
55
|
+
|
56
|
+
def each
|
57
|
+
sets.each do |set|
|
58
|
+
set.each do |model|
|
59
|
+
yield model
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
clone_method :+, :add!
|
65
|
+
clone_method :-, :subtract!
|
66
|
+
clone_method :&, :intersect!
|
67
|
+
end
|
@@ -0,0 +1,329 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
class ModelSetTest < Test::Unit::TestCase
|
4
|
+
class CreateTables < ActiveRecord::Migration
|
5
|
+
def self.up
|
6
|
+
create_table :heroes do |t|
|
7
|
+
t.column :name, :string
|
8
|
+
t.column :universe, :string
|
9
|
+
end
|
10
|
+
|
11
|
+
create_table :superpowers do |t|
|
12
|
+
t.column :name, :string
|
13
|
+
end
|
14
|
+
|
15
|
+
create_table :mutations do |t|
|
16
|
+
t.column :name, :string
|
17
|
+
end
|
18
|
+
|
19
|
+
create_table :superpets do |t|
|
20
|
+
t.column :name, :string
|
21
|
+
t.column :species, :string
|
22
|
+
t.column :owner_id, :bigint
|
23
|
+
end
|
24
|
+
|
25
|
+
create_table :hero_superpowers do |t|
|
26
|
+
t.column :hero_id, :bigint
|
27
|
+
t.column :power_type, :string
|
28
|
+
t.column :power_id, :bigint
|
29
|
+
end
|
30
|
+
|
31
|
+
create_table :hero_birthdays do |t|
|
32
|
+
t.column :hero_id, :bigint
|
33
|
+
t.column :birthday, :date
|
34
|
+
end
|
35
|
+
|
36
|
+
create_table :robots do |t|
|
37
|
+
t.string :name
|
38
|
+
t.string :classification
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.down
|
43
|
+
drop_table :heroes
|
44
|
+
drop_table :superpowers
|
45
|
+
drop_table :mutations
|
46
|
+
drop_table :superpets
|
47
|
+
drop_table :hero_superpowers
|
48
|
+
drop_table :hero_birthdays
|
49
|
+
drop_table :robots
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class Superpower < ActiveRecord::Base
|
54
|
+
end
|
55
|
+
|
56
|
+
class Mutation < ActiveRecord::Base
|
57
|
+
end
|
58
|
+
|
59
|
+
class Superpet < ActiveRecord::Base
|
60
|
+
end
|
61
|
+
|
62
|
+
class HeroSuperpower < ActiveRecord::Base
|
63
|
+
end
|
64
|
+
|
65
|
+
class Hero < ActiveRecord::Base
|
66
|
+
set_table_name 'heroes'
|
67
|
+
has_set :superpowers, :through => :hero_superpowers, :other_key => :power_id
|
68
|
+
has_set :pets, :class_name => 'Superpet', :own_key => :owner_id do
|
69
|
+
def dogs!
|
70
|
+
add_conditions!("species = 'dog'")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class HeroSet < ModelSet
|
76
|
+
constructor :with_universe
|
77
|
+
clone_method :with_universe
|
78
|
+
def with_universe!(universe)
|
79
|
+
add_conditions!("universe = '#{universe}'")
|
80
|
+
end
|
81
|
+
|
82
|
+
clone_method :add_birthday
|
83
|
+
def add_birthday!
|
84
|
+
add_fields!( "hero_birthdays.birthday" => "LEFT OUTER JOIN hero_birthdays ON heroes.id = hero_birthdays.hero_id" )
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'with a db connection' do
|
89
|
+
setup do
|
90
|
+
CreateTables.verbose = false
|
91
|
+
CreateTables.up
|
92
|
+
end
|
93
|
+
|
94
|
+
teardown do
|
95
|
+
CreateTables.down
|
96
|
+
end
|
97
|
+
|
98
|
+
should "construct a model set" do
|
99
|
+
captain = Hero.create(:name => 'Captain America', :universe => 'Marvel')
|
100
|
+
spidey = Hero.create(:name => 'Spider Man', :universe => 'Marvel')
|
101
|
+
batman = Hero.create(:name => 'Batman', :universe => 'D.C.' )
|
102
|
+
superman = Hero.create(:name => 'Superman', :universe => 'D.C.' )
|
103
|
+
ironman = Hero.create(:name => 'Iron Man', :universe => 'Marvel')
|
104
|
+
|
105
|
+
set = HeroSet.with_universe('Marvel')
|
106
|
+
assert_equal [captain.id, spidey.id, ironman.id], set.ids
|
107
|
+
end
|
108
|
+
|
109
|
+
should "maintain initial order when adding conditions" do
|
110
|
+
captain = Hero.create(:name => 'Captain America', :universe => 'Marvel')
|
111
|
+
spidey = Hero.create(:name => 'Spider Man', :universe => 'Marvel')
|
112
|
+
batman = Hero.create(:name => 'Batman', :universe => 'D.C.' )
|
113
|
+
superman = Hero.create(:name => 'Superman', :universe => 'D.C.' )
|
114
|
+
ironman = Hero.create(:name => 'Iron Man', :universe => 'Marvel')
|
115
|
+
|
116
|
+
set = HeroSet.new([ironman, captain, superman, spidey, batman])
|
117
|
+
|
118
|
+
set.add_conditions!("universe = 'Marvel'")
|
119
|
+
|
120
|
+
assert_equal [ironman.id, captain.id, spidey.id], set.ids
|
121
|
+
end
|
122
|
+
|
123
|
+
should "order and reverse set" do
|
124
|
+
captain = Hero.create(:name => 'Captain America', :universe => 'Marvel')
|
125
|
+
spidey = Hero.create(:name => 'Spider Man', :universe => 'Marvel')
|
126
|
+
wolverine = Hero.create(:name => 'Wolverine', :universe => 'Marvel' )
|
127
|
+
phoenix = Hero.create(:name => 'Phoenix', :universe => 'Marvel' )
|
128
|
+
ironman = Hero.create(:name => 'Iron Man', :universe => 'Marvel')
|
129
|
+
|
130
|
+
ids = [captain.id, ironman.id, phoenix.id, spidey.id, wolverine.id]
|
131
|
+
set = HeroSet.with_universe('Marvel')
|
132
|
+
|
133
|
+
set.order_by!('name')
|
134
|
+
assert_equal ids, set.ids
|
135
|
+
|
136
|
+
set.reverse!
|
137
|
+
assert_equal ids.reverse, set.ids
|
138
|
+
|
139
|
+
set.order_by!('name DESC')
|
140
|
+
assert_equal ids.reverse, set.ids
|
141
|
+
|
142
|
+
set.reverse!
|
143
|
+
assert_equal ids, set.ids
|
144
|
+
|
145
|
+
# Make sure that a comma in a function call works.
|
146
|
+
set.order_by!("lower(ltrim(name, 'C'))")
|
147
|
+
assert_equal ids, set.ids
|
148
|
+
|
149
|
+
set.reverse!
|
150
|
+
assert_equal ids.reverse, set.ids
|
151
|
+
end
|
152
|
+
|
153
|
+
should "have missing ids" do
|
154
|
+
missing_id = 5555
|
155
|
+
spidey = Hero.create(:name => 'Spider Man', :universe => 'Marvel')
|
156
|
+
set = HeroSet.new([spidey.id, missing_id])
|
157
|
+
|
158
|
+
# Iterate through the profiles so the missing ones will be detected.
|
159
|
+
set.each {}
|
160
|
+
assert_equal [missing_id], set.missing_ids
|
161
|
+
end
|
162
|
+
|
163
|
+
should "have missing ids with add_fields" do
|
164
|
+
missing_id = 5555
|
165
|
+
spidey = Hero.create(:name => 'Spider Man', :universe => 'Marvel')
|
166
|
+
set = HeroSet.new([spidey.id, missing_id]).add_birthday
|
167
|
+
|
168
|
+
# Iterate through the profiles so the missing ones will be detected.
|
169
|
+
set.each {}
|
170
|
+
assert_equal [missing_id], set.missing_ids
|
171
|
+
end
|
172
|
+
|
173
|
+
should "support has_set" do
|
174
|
+
hero = Hero.create(:name => 'Mr. Invisible')
|
175
|
+
mighty_mouse = Superpet.create(:name => 'Mighty Mouse', :owner_id => hero.id)
|
176
|
+
underdog = Superpet.create(:name => 'Underdog', :owner_id => hero.id)
|
177
|
+
|
178
|
+
set = hero.pets
|
179
|
+
assert_equal SuperpetSet, set.class
|
180
|
+
assert_equal [mighty_mouse.id, underdog.id], set.ids
|
181
|
+
end
|
182
|
+
|
183
|
+
should "support has_set with through" do
|
184
|
+
hero = Hero.create(:name => 'Mr. Invisible')
|
185
|
+
invisibility = Superpower.create(:name => 'Invisibility')
|
186
|
+
flying = Superpower.create(:name => 'Flying')
|
187
|
+
HeroSuperpower.create(:hero_id => hero.id, :power_id => invisibility.id)
|
188
|
+
HeroSuperpower.create(:hero_id => hero.id, :power_id => flying.id)
|
189
|
+
|
190
|
+
set = hero.superpowers
|
191
|
+
assert_equal SuperpowerSet, set.class
|
192
|
+
assert_equal [invisibility.id, flying.id], set.ids
|
193
|
+
end
|
194
|
+
|
195
|
+
should "allow set extensions" do
|
196
|
+
hero = Hero.create(:name => 'Mr. Invisible')
|
197
|
+
mighty_mouse = Superpet.create(:name => 'Mighty Mouse', :owner_id => hero.id, :species => 'mouse')
|
198
|
+
sammy = Superpet.create(:name => 'Sammy Davis Jr. Jr.', :owner_id => hero.id, :species => 'dog')
|
199
|
+
underdog = Superpet.create(:name => 'Underdog', :owner_id => hero.id, :species => 'dog')
|
200
|
+
|
201
|
+
set = hero.pets
|
202
|
+
assert_equal ['mouse', 'dog', 'dog'], set.collect {|pet| pet.species}
|
203
|
+
|
204
|
+
assert_equal [sammy.id, underdog.id], set.dogs!.ids
|
205
|
+
end
|
206
|
+
|
207
|
+
class Robot < ActiveRecord::Base
|
208
|
+
end
|
209
|
+
|
210
|
+
class RobotSet < ModelSet
|
211
|
+
end
|
212
|
+
|
213
|
+
setup do
|
214
|
+
@bender = Robot.create(:name => 'Bender', :classification => :smart_ass )
|
215
|
+
@r2d2 = Robot.create(:name => 'R2D2', :classification => :droid )
|
216
|
+
@c3po = Robot.create(:name => 'C3PO', :classification => :droid )
|
217
|
+
@rosie = Robot.create(:name => 'Rosie', :classification => :domestic )
|
218
|
+
@small_wonder = Robot.create(:name => 'Vicki', :classification => :child )
|
219
|
+
@t1000 = Robot.create(:name => 'Terminator', :classification => :assasin )
|
220
|
+
@johnny5 = Robot.create(:name => 'Johnny 5', :classification => :miltary )
|
221
|
+
|
222
|
+
@bot_set = RobotSet.new([@bender,@r2d2,@c3po,@rosie,@small_wonder,@t1000,@johnny5])
|
223
|
+
|
224
|
+
@data = Robot.create(:name => 'Data', :classification => :positronic)
|
225
|
+
@number8 = Robot.create(:name => 'Boomer', :classification => :cylon )
|
226
|
+
end
|
227
|
+
|
228
|
+
should "be empty" do
|
229
|
+
set = RobotSet.empty
|
230
|
+
assert_equal 0, set.size
|
231
|
+
assert set.empty?
|
232
|
+
|
233
|
+
set = RobotSet.new(@bender)
|
234
|
+
assert !set.empty?
|
235
|
+
end
|
236
|
+
|
237
|
+
should "create a set with single model" do
|
238
|
+
set = RobotSet.new(@bender)
|
239
|
+
assert_equal [@bender.id], set.ids
|
240
|
+
end
|
241
|
+
|
242
|
+
should "include models" do
|
243
|
+
set = RobotSet.new([@bender, @r2d2.id, @c3po.id])
|
244
|
+
assert set.include?(@bender)
|
245
|
+
assert set.include?(@r2d2.id)
|
246
|
+
assert set.include?(@c3po)
|
247
|
+
end
|
248
|
+
|
249
|
+
should "delete models from a set" do
|
250
|
+
set = RobotSet.new([@rosie, @small_wonder, @c3po])
|
251
|
+
|
252
|
+
set.delete(@c3po)
|
253
|
+
assert_equal [@rosie.id, @small_wonder.id], set.ids
|
254
|
+
|
255
|
+
set.delete(@rosie.id)
|
256
|
+
assert_equal [@small_wonder.id], set.ids
|
257
|
+
|
258
|
+
set.delete(@small_wonder)
|
259
|
+
assert_equal [], set.ids
|
260
|
+
assert set.empty?
|
261
|
+
end
|
262
|
+
|
263
|
+
should "select models from a set" do
|
264
|
+
assert_equal [@r2d2, @c3po], @bot_set.select {|bot| bot.classification == :droid}.to_a
|
265
|
+
assert_equal 7, @bot_set.size
|
266
|
+
|
267
|
+
@bot_set.select! {|bot| bot.classification == :miltary}
|
268
|
+
assert_equal [@johnny5], @bot_set.to_a
|
269
|
+
end
|
270
|
+
|
271
|
+
should "sort a set" do
|
272
|
+
assert_equal [@bender,@c3po,@johnny5,@r2d2,@rosie,@t1000,@small_wonder], @bot_set.sort {|a,b| a.name <=> b.name}.to_a
|
273
|
+
assert_equal @johnny5, @bot_set.last
|
274
|
+
|
275
|
+
@bot_set.sort! {|a,b| b.name <=> a.name}
|
276
|
+
assert_equal [@bender,@c3po,@johnny5,@r2d2,@rosie,@t1000,@small_wonder].reverse, @bot_set.to_a
|
277
|
+
|
278
|
+
@bot_set.reverse!
|
279
|
+
assert_equal [@bender,@c3po,@johnny5,@r2d2,@rosie,@t1000,@small_wonder], @bot_set.to_a
|
280
|
+
end
|
281
|
+
|
282
|
+
should "sort a set by name" do
|
283
|
+
assert_equal [@bender,@c3po,@johnny5,@r2d2,@rosie,@t1000,@small_wonder], @bot_set.sort_by {|bot| bot.name}.to_a
|
284
|
+
end
|
285
|
+
|
286
|
+
should "reject models from a set" do
|
287
|
+
@bot_set.reject! {|bot| bot.classification == :domestic}
|
288
|
+
assert !@bot_set.include?(@rosie)
|
289
|
+
end
|
290
|
+
|
291
|
+
should "do set arithmetic" do
|
292
|
+
droids = RobotSet.new([@c3po, @r2d2])
|
293
|
+
womanoids = RobotSet.new([@rosie, @small_wonder, @number8])
|
294
|
+
humanoids = RobotSet.new([@small_wonder, @t1000, @data, @number8])
|
295
|
+
metalics = RobotSet.new([@r2d2, @c3po, @johnny5])
|
296
|
+
cartoons = RobotSet.new([@bender, @rosie])
|
297
|
+
|
298
|
+
assert_equal ['C3PO', 'R2D2', 'Johnny 5'], (droids + metalics).collect {|bot| bot.name}
|
299
|
+
assert_equal ['Bender', 'Rosie', 'C3PO', 'R2D2', 'Johnny 5'], (cartoons + droids + metalics).collect {|bot| bot.name}
|
300
|
+
assert_equal 5, (cartoons + droids + metalics).size
|
301
|
+
assert_equal 5, (cartoons + droids + metalics).count
|
302
|
+
|
303
|
+
assert_equal [], (droids - metalics).collect {|bot| bot.name}
|
304
|
+
assert_equal ['Johnny 5'], (metalics - droids).collect {|bot| bot.name}
|
305
|
+
assert_equal ['Terminator', 'Data'], (humanoids - womanoids).collect {|bot| bot.name}
|
306
|
+
assert_equal ['Bender'], (cartoons - womanoids).collect {|bot| bot.name}
|
307
|
+
assert_equal 2, (humanoids - womanoids).size
|
308
|
+
assert_equal 2, (humanoids - womanoids).count
|
309
|
+
|
310
|
+
assert_equal ['C3PO', 'R2D2'], (droids & metalics).collect {|bot| bot.name}
|
311
|
+
assert_equal ['R2D2', 'C3PO'], (metalics & droids).collect {|bot| bot.name}
|
312
|
+
assert_equal ['Vicki', 'Boomer'], (humanoids & womanoids).collect {|bot| bot.name}
|
313
|
+
assert_equal ['Rosie'], (cartoons & womanoids).collect {|bot| bot.name}
|
314
|
+
assert_equal 2, (humanoids & womanoids).size
|
315
|
+
assert_equal 2, (humanoids & womanoids).count
|
316
|
+
|
317
|
+
set = (droids + @johnny5)
|
318
|
+
assert_equal ['C3PO', 'R2D2', 'Johnny 5'], set.collect {|bot| bot.name}
|
319
|
+
set -= @r2d2
|
320
|
+
assert_equal ['C3PO', 'Johnny 5'], set.collect {|bot| bot.name}
|
321
|
+
end
|
322
|
+
|
323
|
+
should "clone a set" do
|
324
|
+
set = RobotSet.new([1])
|
325
|
+
new_set = set.clone
|
326
|
+
assert new_set.object_id != set.object_id
|
327
|
+
end
|
328
|
+
end
|
329
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
class MultiSetTest < Test::Unit::TestCase
|
4
|
+
class CreateTables < ActiveRecord::Migration
|
5
|
+
def self.up
|
6
|
+
create_table :robots do |t|
|
7
|
+
t.string :name
|
8
|
+
t.string :classification
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.down
|
13
|
+
drop_table :robots
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class Robot < ActiveRecord::Base
|
18
|
+
end
|
19
|
+
|
20
|
+
class RobotSet < ModelSet
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'with a db connection' do
|
24
|
+
setup do
|
25
|
+
CreateTables.verbose = false
|
26
|
+
CreateTables.up
|
27
|
+
|
28
|
+
@bender = Robot.create(:name => 'Bender', :classification => :smart_ass )
|
29
|
+
@r2d2 = Robot.create(:name => 'R2D2', :classification => :droid )
|
30
|
+
@c3po = Robot.create(:name => 'C3PO', :classification => :droid )
|
31
|
+
@rosie = Robot.create(:name => 'Rosie', :classification => :domestic )
|
32
|
+
@small_wonder = Robot.create(:name => 'Vicki', :classification => :child )
|
33
|
+
@t1000 = Robot.create(:name => 'Terminator', :classification => :assasin )
|
34
|
+
@johnny5 = Robot.create(:name => 'Johnny 5', :classification => :miltary )
|
35
|
+
@data = Robot.create(:name => 'Data', :classification => :positronic)
|
36
|
+
@number8 = Robot.create(:name => 'Boomer', :classification => :cylon )
|
37
|
+
end
|
38
|
+
|
39
|
+
teardown do
|
40
|
+
CreateTables.down
|
41
|
+
end
|
42
|
+
|
43
|
+
should "add, subtract, intersect" do
|
44
|
+
set = MultiSet.new
|
45
|
+
set += RobotSet.new([@bender, @r2d2, @rosie])
|
46
|
+
set += RobotSet.new([@c3po, @r2d2, @t1000])
|
47
|
+
set += RobotSet.new([@data, @number8, @johnny5])
|
48
|
+
|
49
|
+
assert_equal [3,3,3], set.size
|
50
|
+
assert_equal [@bender,@r2d2,@rosie,@c3po,@t1000,@data,@number8,@johnny5].collect {|r| r.id}, set.ids
|
51
|
+
assert_equal [@bender,@r2d2,@rosie,@c3po,@r2d2,@t1000,@data,@number8,@johnny5], set.to_a
|
52
|
+
|
53
|
+
set -= RobotSet.new([@r2d2, @rosie, @t1000, @johnny5])
|
54
|
+
|
55
|
+
assert_equal [1,1,2], set.size
|
56
|
+
assert_equal [@bender,@c3po,@data,@number8].collect {|r| r.id}, set.ids
|
57
|
+
|
58
|
+
other_set = MultiSet.new(RobotSet.new([@data]), RobotSet.new([@bender]))
|
59
|
+
|
60
|
+
set &= other_set
|
61
|
+
assert_equal [1,0,1], set.size
|
62
|
+
assert_equal [@bender,@data].collect {|r| r.id}, set.ids
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'shoulda'
|
4
|
+
require 'mocha'
|
5
|
+
|
6
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + "/../lib"
|
7
|
+
['deep_clonable', 'ordered_set'].each do |dir|
|
8
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + "/../../#{dir}/lib"
|
9
|
+
end
|
10
|
+
require 'model_set'
|
11
|
+
|
12
|
+
class Test::Unit::TestCase
|
13
|
+
end
|
14
|
+
|
15
|
+
ActiveRecord::Base.establish_connection(
|
16
|
+
:adapter => "postgresql",
|
17
|
+
:host => "localhost",
|
18
|
+
:username => "postgres",
|
19
|
+
:password => "",
|
20
|
+
:database => "model_set_test"
|
21
|
+
)
|
22
|
+
ActiveRecord::Migration.verbose = false
|
23
|
+
ActiveRecord::Base.connection.client_min_messages = 'panic'
|
@@ -0,0 +1,41 @@
|
|
1
|
+
=Sphinx Client API 0.9.9-dev (r1299)
|
2
|
+
|
3
|
+
This document gives an overview of what is Sphinx itself and how to use in
|
4
|
+
within Ruby on Rails. For more information or documentation,
|
5
|
+
please go to http://www.sphinxsearch.com
|
6
|
+
|
7
|
+
==Sphinx
|
8
|
+
|
9
|
+
Sphinx is a standalone full-text search engine, meant to provide fast,
|
10
|
+
size-efficient and relevant fulltext search functions to other applications.
|
11
|
+
Sphinx was specially designed to integrate well with SQL databases and
|
12
|
+
scripting languages. Currently built-in data sources support fetching data
|
13
|
+
either via direct connection to MySQL, or from an XML pipe.
|
14
|
+
|
15
|
+
Simplest way to communicate with Sphinx is to use <tt>searchd</tt> -
|
16
|
+
a daemon to search through fulltext indices from external software.
|
17
|
+
|
18
|
+
==Documentation
|
19
|
+
|
20
|
+
You can create the documentation by running:
|
21
|
+
|
22
|
+
rake rdoc
|
23
|
+
|
24
|
+
==Latest version
|
25
|
+
|
26
|
+
You can always get latest version from
|
27
|
+
http://kpumuk.info/projects/ror-plugins/sphinx
|
28
|
+
|
29
|
+
==Credits
|
30
|
+
|
31
|
+
Dmytro Shteflyuk <kpumuk@kpumuk.info> http://kpumuk.info
|
32
|
+
|
33
|
+
Andrew Aksyonoff http://sphinxsearch.com/
|
34
|
+
|
35
|
+
Special thanks to Alexey Kovyrin <alexey@kovyrin.net> http://blog.kovyrin.net
|
36
|
+
|
37
|
+
==License
|
38
|
+
|
39
|
+
This library is distributed under the terms of the Ruby license.
|
40
|
+
You can freely distribute/modify this library.
|
41
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'spec/rake/spectask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :spec
|
7
|
+
|
8
|
+
desc 'Test the sphinx plugin.'
|
9
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
10
|
+
t.libs << 'lib'
|
11
|
+
t.pattern = 'spec/*_spec.rb'
|
12
|
+
end
|
13
|
+
|
14
|
+
desc 'Generate documentation for the sphinx plugin.'
|
15
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'Sphinx Client API'
|
18
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
19
|
+
rdoc.rdoc_files.include('README')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/lib/sphinx'
|