oedipus-dm 0.0.1

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.
@@ -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