model_set 0.10.6
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/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'
|