oedipus-dm 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,398 @@
1
+ require "spec_helper"
2
+
3
+ describe Oedipus::DataMapper::Index do
4
+ include Oedipus::RSpec::TestHarness
5
+
6
+ before(:all) do
7
+ set_data_dir File.expand_path("../../data", __FILE__)
8
+ set_searchd ENV["SEARCHD"]
9
+ start_searchd
10
+ end
11
+
12
+ after(:all) { stop_searchd }
13
+
14
+ before(:each) do
15
+ Post.destroy!
16
+ User.destroy!
17
+ empty_indexes
18
+ end
19
+
20
+ let(:conn) do
21
+ Oedipus::Connection.new(searchd_host)
22
+ end
23
+
24
+ let(:index) do
25
+ Oedipus::DataMapper::Index.new(Post, name: :posts_rt, connection: conn) do |idx|
26
+ idx.map :id
27
+ idx.map :title
28
+ idx.map :body
29
+ idx.map :user_id
30
+ idx.map :views, with: :view_count
31
+ end
32
+ end
33
+
34
+ describe "#insert" do
35
+ let(:user) do
36
+ User.create(username: "bob")
37
+ end
38
+
39
+ let(:post) do
40
+ Post.create(
41
+ title: "There was one was a badger",
42
+ body: "And a nice one he was.",
43
+ user: user,
44
+ view_count: 98
45
+ )
46
+ end
47
+
48
+ before(:each) { index.insert(post) }
49
+
50
+ it "inserts the object into the index" do
51
+ conn[:posts_rt].fetch(post.id)[:user_id].should == user.id
52
+ end
53
+
54
+ it "uses the defined mappings" do
55
+ conn[:posts_rt].fetch(post.id)[:views].should == 98
56
+ end
57
+ end
58
+
59
+ pending "the sphinxql grammar does not currently support this, though I'm patching it" do
60
+ describe "#update" do
61
+ let(:user) do
62
+ User.create(username: "bob")
63
+ end
64
+
65
+ let(:post) do
66
+ Post.create(
67
+ title: "There was one was a badger",
68
+ body: "And a nice one he was.",
69
+ user: user,
70
+ view_count: 98
71
+ )
72
+ end
73
+
74
+ before(:each) do
75
+ conn[:posts_rt].insert(post.id, title: "Not this", body: "Or this", views: 0, user_id: 100)
76
+ index.update(post)
77
+ end
78
+
79
+ it "updates the object in the index" do
80
+ conn[:posts_rt].fetch(post.id)[:user_id].should == user.id
81
+ end
82
+
83
+ it "uses the defined mappings" do
84
+ conn[:posts_rt].fetch(post.id)[:views].should == 98
85
+ end
86
+ end
87
+ end
88
+
89
+ describe "#replace" do
90
+ let(:user) do
91
+ User.create(username: "bob")
92
+ end
93
+
94
+ let(:post) do
95
+ Post.create(
96
+ title: "There was one was a badger",
97
+ body: "And a nice one he was.",
98
+ user: user,
99
+ view_count: 98
100
+ )
101
+ end
102
+
103
+ before(:each) do
104
+ conn[:posts_rt].insert(post.id, title: "Not this", body: "Nor this", user_id: 100, views: 0)
105
+ index.replace(post)
106
+ end
107
+
108
+ it "updates the object in the index" do
109
+ conn[:posts_rt].fetch(post.id)[:user_id].should == user.id
110
+ end
111
+
112
+ it "uses the defined mappings" do
113
+ conn[:posts_rt].fetch(post.id)[:views].should == 98
114
+ end
115
+ end
116
+
117
+ describe "#delete" do
118
+ let(:user) do
119
+ User.create(username: "bob")
120
+ end
121
+
122
+ let(:post) do
123
+ Post.create(
124
+ title: "There was one was a badger",
125
+ body: "And a nice one he was.",
126
+ user: user,
127
+ view_count: 98
128
+ )
129
+ end
130
+
131
+ before(:each) do
132
+ conn[:posts_rt].insert(post.id, title: "Not this", body: "Nor this", user_id: 100, views: 0)
133
+ index.delete(post)
134
+ end
135
+
136
+ it "removes the object in the index" do
137
+ conn[:posts_rt].fetch(post.id).should be_nil
138
+ end
139
+ end
140
+
141
+ describe "#search" do
142
+ before(:each) do
143
+ @user_a = User.create(username: "bob")
144
+ @user_b = User.create(username: "abi")
145
+ [
146
+ @a = Post.create(
147
+ title: "Badgers on the run",
148
+ body: "Big badger little badger",
149
+ view_count: 7,
150
+ user: @user_a
151
+ ),
152
+ @b = Post.create(
153
+ title: "Do it for the badgers!",
154
+ body: "The badgers need you",
155
+ view_count: 11,
156
+ user: @user_a
157
+ ),
158
+ @c = Post.create(
159
+ title: "Talk to the hand, not to the badgers",
160
+ body: "Cos this badger ain't listening",
161
+ view_count: 6,
162
+ user: @user_b
163
+ ),
164
+ @d = Post.create(
165
+ title: "Rabbits doing rabbity things",
166
+ body: "Being all cute, with their floppy little ears",
167
+ view_count: 9,
168
+ user: @user_a
169
+ )
170
+ ].each do |p|
171
+ conn[:posts_rt].insert(p.id, title: p.title, body: p.body, views: p.view_count, user_id: p.user.id)
172
+ end
173
+ end
174
+
175
+ it "returns a datamapper collection" do
176
+ index.search("badgers").should be_a_kind_of(DataMapper::Collection)
177
+ end
178
+
179
+ it "returns models of the correct type" do
180
+ index.search("badgers").map(&:model).should == [Post, Post, Post]
181
+ end
182
+
183
+ it "loads the records matching the search" do
184
+ index.search("badgers", order: :id).collect { |p| { id: p.id, title: p.title } }.should == [
185
+ { id: @a.id, title: @a.title },
186
+ { id: @b.id, title: @b.title },
187
+ { id: @c.id, title: @c.title }
188
+ ]
189
+ end
190
+
191
+ it "handles the attribute mappings" do
192
+ index.search("badgers", order: :id).collect { |p| { view_count: p.view_count } }.should == [
193
+ { view_count: @a.view_count },
194
+ { view_count: @b.view_count },
195
+ { view_count: @c.view_count }
196
+ ]
197
+ end
198
+
199
+ it "provides the count for the total number of records matched" do
200
+ index.search("badgers", limit: 2).total_found.should == 3
201
+ end
202
+
203
+ it "provides the count for the number of records returned" do
204
+ index.search("badgers", limit: 2).count.should == 2
205
+ end
206
+
207
+ it "loads the models directly from the index" do
208
+ index.search("badgers").each do |p|
209
+ Post.user_id.loaded?(p).should be_true
210
+ end
211
+ end
212
+
213
+ it "allows lazy-loading of the non-indexed attributes" do
214
+ index.search("badgers").each do |p|
215
+ Post.created_at.loaded?(p).should be_false
216
+ end
217
+ end
218
+
219
+ describe "symbol operators" do
220
+ describe "Symbol.not" do
221
+ it "works like Oedipus.not" do
222
+ index.search("badgers", :user_id.not => @user_a.id, order: :id).map(&:id).should == [@c.id]
223
+ end
224
+ end
225
+
226
+ describe "Symbol.gt" do
227
+ it "works like Oedipus.gt" do
228
+ index.search("badgers", :views.gt => 7, order: :id).map(&:id).should == [@b.id]
229
+ end
230
+ end
231
+
232
+ describe "Symbol.gte" do
233
+ it "works like Oedipus.gte" do
234
+ index.search("badgers", :views.gte => 7, order: :id).map(&:id).should == [@a.id, @b.id]
235
+ end
236
+ end
237
+
238
+ describe "Symbol.lt" do
239
+ it "works like Oedipus.lt" do
240
+ index.search("badgers", :views.lt => 7, order: :id).map(&:id).should == [@c.id]
241
+ end
242
+ end
243
+
244
+ describe "Symbol.lte" do
245
+ it "works like Oedipus.lte" do
246
+ index.search("badgers", :views.lte => 7, order: :id).map(&:id).should == [@a.id, @c.id]
247
+ end
248
+ end
249
+
250
+ describe "Symbol.asc" do
251
+ it "is converted to Hash notation" do
252
+ index.search("badgers", order: :id.asc).map(&:id).should == [@a.id, @b.id, @c.id]
253
+ end
254
+
255
+ context "inside an array" do
256
+ it "is converted to Hash notation" do
257
+ index.search("badgers", order: [:id.asc]).map(&:id).should == [@a.id, @b.id, @c.id]
258
+ end
259
+ end
260
+ end
261
+
262
+ describe "Symbol.desc" do
263
+ it "is converted to Hash notation" do
264
+ index.search("badgers", order: :id.desc).map(&:id).should == [@c.id, @b.id, @a.id]
265
+ end
266
+
267
+ context "inside an array" do
268
+ it "is converted to Hash notation" do
269
+ index.search("badgers", order: [:id.desc]).map(&:id).should == [@c.id, @b.id, @a.id]
270
+ end
271
+ end
272
+ end
273
+ end
274
+
275
+ describe "pagination" do
276
+ before(:each) do
277
+ [
278
+ @e = Post.create(
279
+ title: "Badgers again",
280
+ body: "Blah blah badger",
281
+ view_count: 20,
282
+ user: @user_a
283
+ ),
284
+ @f = Post.create(
285
+ title: "Don't take my badger!",
286
+ body: "Badgers are afraid of the dark",
287
+ view_count: 21,
288
+ user: @user_a
289
+ ),
290
+ @g = Post.create(
291
+ title: "You seen one badger, you seen em all",
292
+ body: "Badgers, they're all the same",
293
+ view_count: 4,
294
+ user: @user_b
295
+ )
296
+ ].each do |p|
297
+ conn[:posts_rt].insert(p.id, title: p.title, body: p.body, views: p.view_count, user_id: p.user.id)
298
+ end
299
+ end
300
+
301
+ context "with :per_page specified" do
302
+ context "with :page => 1" do
303
+ it "returns the first page of the results" do
304
+ index.search("badgers", order: :id, pager: {page: 1, per_page: 2}).map(&:id).should == [@a.id, @b.id]
305
+ end
306
+
307
+ it "provides a #pager with #current_page = 1" do
308
+ index.search("badgers", order: :id, pager: {page: 1, per_page: 2}).pager.current_page.should == 1
309
+ end
310
+ end
311
+
312
+ context "with :page => 2" do
313
+ it "returns the second page of the results" do
314
+ index.search("badgers", order: :id, pager: {page: 2, per_page: 2}).map(&:id).should == [@c.id, @e.id]
315
+ end
316
+
317
+ it "provides a #pager with #current_page = 2" do
318
+ index.search("badgers", order: :id, pager: {page: 2, per_page: 2}).pager.current_page.should == 2
319
+ end
320
+ end
321
+ end
322
+ end
323
+
324
+ describe "with :facets" do
325
+ it "returns the main results in the collection" do
326
+ index.search(
327
+ "badgers",
328
+ order: :id,
329
+ facets: {
330
+ popular: {:views.gte => 7}
331
+ }
332
+ ).map(&:id).should == [@a.id, @b.id, @c.id]
333
+ end
334
+
335
+ it "returns the facets inside the collection" do
336
+ index.search(
337
+ "badgers",
338
+ order: :id,
339
+ facets: {
340
+ popular: {:views.gte => 7}
341
+ }
342
+ ).facets[:popular].map(&:id).should == [@a.id, @b.id]
343
+ end
344
+
345
+ it "provides data on the matches inside the facets" do
346
+ index.search(
347
+ "badgers",
348
+ order: :id,
349
+ facets: {
350
+ popular: {:views.gte => 7}
351
+ }
352
+ ).facets[:popular].total_found.should == 2
353
+ end
354
+ end
355
+ end
356
+
357
+ describe "#multi_search" do
358
+ before(:each) do
359
+ @user_a = User.create(username: "bob")
360
+ @user_b = User.create(username: "abi")
361
+ [
362
+ @a = Post.create(
363
+ title: "Badgers on the run",
364
+ body: "Big badger little badger",
365
+ view_count: 7,
366
+ user: @user_a
367
+ ),
368
+ @b = Post.create(
369
+ title: "Do it for the badgers!",
370
+ body: "The badgers need you",
371
+ view_count: 11,
372
+ user: @user_a
373
+ ),
374
+ @c = Post.create(
375
+ title: "Talk to the hand, not to the badgers",
376
+ body: "Cos this badger ain't listening",
377
+ view_count: 6,
378
+ user: @user_b
379
+ ),
380
+ @d = Post.create(
381
+ title: "Rabbits doing rabbity things",
382
+ body: "Being all cute, with their floppy little ears",
383
+ view_count: 9,
384
+ user: @user_a
385
+ )
386
+ ].each do |p|
387
+ conn[:posts_rt].insert(p.id, title: p.title, body: p.body, views: p.view_count, user_id: p.user.id)
388
+ end
389
+ end
390
+
391
+ it "returns a Hash mapping the search names with their collections" do
392
+ index.multi_search(
393
+ popular_badgers: ["badgers", :views.gte => 7],
394
+ rabbits: "rabbits"
395
+ ).should be_a_kind_of(Hash)
396
+ end
397
+ end
398
+ end
@@ -0,0 +1,14 @@
1
+ require "rspec"
2
+ require "oedipus-dm"
3
+ require "oedipus/rspec/test_harness"
4
+ require "dm-pager"
5
+
6
+ Dir[File.expand_path("../support/**/*.rb", __FILE__)].each { |f| require f }
7
+
8
+ RSpec.configure do |config|
9
+ config.before(:suite) do
10
+ DataMapper::Model.raise_on_save_failure = true
11
+ DataMapper.setup(:default, adapter: :in_memory)
12
+ DataMapper.finalize
13
+ end
14
+ end
@@ -0,0 +1,11 @@
1
+ class Post
2
+ include DataMapper::Resource
3
+
4
+ property :id, Serial
5
+ property :title, String
6
+ property :body, Text
7
+ property :view_count, Integer
8
+ property :created_at, DateTime
9
+
10
+ belongs_to :user
11
+ end
@@ -0,0 +1,8 @@
1
+ class User
2
+ include DataMapper::Resource
3
+
4
+ property :id, Serial
5
+ property :username, String
6
+
7
+ has n, :posts
8
+ end
metadata ADDED
@@ -0,0 +1,134 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: oedipus-dm
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - d11wtq
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-29 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: oedipus
16
+ requirement: &14446500 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.0.5
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *14446500
25
+ - !ruby/object:Gem::Dependency
26
+ name: dm-core
27
+ requirement: &14445360 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '1.2'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *14445360
36
+ - !ruby/object:Gem::Dependency
37
+ name: rake
38
+ requirement: &14444580 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *14444580
47
+ - !ruby/object:Gem::Dependency
48
+ name: rspec
49
+ requirement: &14443860 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *14443860
58
+ - !ruby/object:Gem::Dependency
59
+ name: dm-pager
60
+ requirement: &14431500 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *14431500
69
+ description: ! '== DataMapper Integration for Oedipus
70
+
71
+
72
+ This gem adds the possibility to find DataMapper models by searching in
73
+
74
+ a Sphinx index, and to update/delete/replace them.
75
+
76
+
77
+ Faceted searches are cleanly supported.
78
+
79
+ '
80
+ email:
81
+ - chris@w3style.co.uk
82
+ executables: []
83
+ extensions: []
84
+ extra_rdoc_files: []
85
+ files:
86
+ - .gitignore
87
+ - .rspec
88
+ - Gemfile
89
+ - LICENSE
90
+ - README.md
91
+ - Rakefile
92
+ - lib/oedipus-dm.rb
93
+ - lib/oedipus/data_mapper.rb
94
+ - lib/oedipus/data_mapper/collection.rb
95
+ - lib/oedipus/data_mapper/conversions.rb
96
+ - lib/oedipus/data_mapper/index.rb
97
+ - lib/oedipus/data_mapper/pagination.rb
98
+ - lib/oedipus/data_mapper/version.rb
99
+ - oedipus-dm.gemspec
100
+ - spec/data/.gitkeep
101
+ - spec/integration/index_spec.rb
102
+ - spec/spec_helper.rb
103
+ - spec/support/models/post.rb
104
+ - spec/support/models/user.rb
105
+ homepage: https://github.com/d11wtq/oedipus-dm
106
+ licenses: []
107
+ post_install_message:
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ none: false
113
+ requirements:
114
+ - - ! '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ none: false
119
+ requirements:
120
+ - - ! '>='
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ requirements: []
124
+ rubyforge_project:
125
+ rubygems_version: 1.8.11
126
+ signing_key:
127
+ specification_version: 3
128
+ summary: DataMapper Integration for the Oedipus Sphinx 2 Client
129
+ test_files:
130
+ - spec/data/.gitkeep
131
+ - spec/integration/index_spec.rb
132
+ - spec/spec_helper.rb
133
+ - spec/support/models/post.rb
134
+ - spec/support/models/user.rb