ashikawa-core 0.4.1 → 0.5.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.
data/.gitignore CHANGED
@@ -6,3 +6,5 @@ doc
6
6
  Gemfile.lock
7
7
  pkg/*
8
8
  report/*
9
+ coverage
10
+ .rbx
data/.travis.yml CHANGED
@@ -1,4 +1,6 @@
1
1
  language: ruby
2
+ before_script:
3
+ - ./spec/setup/arangodb.sh
2
4
  rvm:
3
5
  - 1.9.2
4
6
  - 1.9.3
data/CONTRIBUTING.md CHANGED
@@ -3,10 +3,11 @@
3
3
  When you want to write code for the project, please follow these guidelines:
4
4
 
5
5
  1. Claim the ticket: Tell us that you want to work on a certain ticket, we will assign it to you (We don't want two people to work on the same thing ;) )
6
- 2. Write an Integration Test: Describe what you want to do (our integration tests touch the database)
7
- 3. Implement it: Write a unit test, check that it fails, make the test pass – repeat (our unit tests don't touch the database)
8
- 4. Write Documentation for it.
9
- 5. Check with `rake` that everything is fine and send the Pull Request :)
6
+ 2. Fork your feature branch from the `development` branch (not the `master` branch)
7
+ 3. Write an acceptance test: Describe what you want to do (our integration tests touch the database)
8
+ 4. Implement it: Write a unit test, check that it fails, make the test pass – repeat (our unit tests don't touch the database)
9
+ 5. Write documentation for it.
10
+ 6. Check with `rake` that everything is fine and send the pull request to the `development` branch :)
10
11
 
11
12
  ## How to get started developing
12
13
 
@@ -38,7 +39,3 @@ Guard is a tool for comfortable development. If you want to use it for developme
38
39
  * Run a documentation server on `http://localhost:8808`
39
40
  * Run `bundle` whenever you change the dependencies
40
41
  * Run the integration and unit tests whenever you change a file in the lib or spec directory
41
-
42
- ### Continuous Integration
43
-
44
- Our tests are run on Travis CI, the build status is displayed above. **Please note** that it only runs the unit tests and not the integration tests, because that would require ArangoDB to be installed on the Travis CI boxes. *Therefore green doesn't neccessarily mean green* (which is unfortunate). Therefore it is important that you run the integration tests on your local machine before sending the pull requests.
data/Guardfile CHANGED
@@ -11,7 +11,7 @@ guard 'rspec', :spec_paths => "spec/unit" do
11
11
  watch(%r{spec/.+\.rb})
12
12
  end
13
13
 
14
- guard 'rspec', :spec_paths => "spec/integration" do
14
+ guard 'rspec', :spec_paths => "spec/acceptance" do
15
15
  watch(%r{lib/.+\.rb})
16
16
  watch(%r{spec/.+\.rb})
17
17
  end
data/README.md CHANGED
@@ -6,6 +6,16 @@
6
6
 
7
7
  Ashikawa Core is a Wrapper around the ArangoDB Rest API. It provides low level access and will be used in different ArangoDB ODMs.
8
8
 
9
+ All tests run on Travis CI for the following versions of Ruby:
10
+
11
+ * MRI 1.9.2 and 1.9.3
12
+ * Rubinius 1.9 mode
13
+ * JRuby 1.9 mode
14
+
15
+ We also run on JRuby and MRI Head. MRI-head is currently not passing, because some dependencies are not compatible.
16
+
17
+ Please note that the `master` branch is always the stable version released on Ruby Gems (*This is actually a lie, but we are currently converting to this model ;) The next release will implement this*). If you want the most recent version, please refer to the `development` branch.
18
+
9
19
  ## How to use it
10
20
 
11
21
  For a detailed description of Ashikawa::Core please refer to the [documentation](http://rdoc.info/github/triAGENS/ashikawa-core/master/frames). An example:
@@ -18,6 +28,10 @@ database["my_collection"].name = "new_name"
18
28
  database["new_name"].delete
19
29
  ```
20
30
 
31
+ # Issues or Questions
32
+
33
+ If you find a bug in this gem, please report it on [our tracker](https://github.com/triAGENS/ashikawa-core/issues). If you have a question, just contact us via the [mailing list](https://groups.google.com/forum/?fromgroups#!forum/ashikawa) – we are happy to help you :)
34
+
21
35
  # Contributing
22
36
 
23
- If you want to contribute to the project, see CONTRIBUTING.md for details.
37
+ If you want to contribute to the project, see CONTRIBUTING.md for details. It contains information on our process and how to set up everything.
data/Rakefile CHANGED
@@ -2,21 +2,28 @@
2
2
  require "bundler/gem_tasks"
3
3
  require "rspec"
4
4
  require "rspec/core/rake_task"
5
+ require "roodi"
6
+ require "roodi_task"
5
7
  # require 'yardstick/rake/measurement'
6
8
  # require 'yardstick/rake/verify'
7
9
 
8
10
 
9
11
  namespace :spec do
10
- desc "Run the integration tests. Requires ArangoDB."
11
- RSpec::Core::RakeTask.new(:integration) do |spec|
12
- spec.rspec_opts = "--require integration/arango_helper.rb"
13
- spec.pattern = "spec/integration/*_spec.rb"
12
+ desc "Run the acceptance tests. Requires ArangoDB to be running."
13
+ RSpec::Core::RakeTask.new(:acceptance_with_running_arangodb) do |spec|
14
+ spec.pattern = "spec/acceptance/*_spec.rb"
14
15
  end
15
16
 
16
- desc "Run the authentication integration tests. Requires ArangoDB."
17
- RSpec::Core::RakeTask.new(:integration_auth) do |spec|
18
- spec.rspec_opts = "--require integration_auth/arango_helper.rb"
19
- spec.pattern = "spec/integration_auth/*_spec.rb"
17
+ desc "Run the acceptance tests. Requires ArangoDB."
18
+ RSpec::Core::RakeTask.new(:acceptance) do |spec|
19
+ spec.rspec_opts = "--require acceptance/arango_helper.rb"
20
+ spec.pattern = "spec/acceptance/*_spec.rb"
21
+ end
22
+
23
+ desc "Run the authentication acceptance tests. Requires ArangoDB."
24
+ RSpec::Core::RakeTask.new(:acceptance_auth) do |spec|
25
+ spec.rspec_opts = "--require acceptance_auth/arango_helper.rb"
26
+ spec.pattern = "spec/acceptance_auth/*_spec.rb"
20
27
  end
21
28
 
22
29
  desc "Run the unit tests"
@@ -25,7 +32,7 @@ namespace :spec do
25
32
  end
26
33
 
27
34
  desc "Run all tests. Requires ArangoDB"
28
- task :all => [:integration, :unit]
35
+ task :all => [:acceptance, :unit]
29
36
  end
30
37
 
31
38
  desc "check if gems are up to date"
@@ -64,10 +71,36 @@ namespace :yard do
64
71
  end
65
72
  end
66
73
 
67
- desc "Run Unit Tests and verify documentation - no ArangoDB required"
74
+ namespace :metrics do
75
+ metric_tasks = []
76
+
77
+ begin
78
+ require 'cane/rake_task'
79
+
80
+ desc "Run cane to check quality metrics"
81
+ Cane::RakeTask.new(:cane) do |cane|
82
+ cane.abc_max = 10
83
+ cane.style_measure = 140
84
+ cane.style_glob = "{app,lib}/**/*.rb"
85
+ end
86
+
87
+ metric_tasks << :cane
88
+ rescue LoadError
89
+ warn "cane not available, quality task not provided."
90
+ end
91
+
92
+ RoodiTask.new do |roodi|
93
+ roodi.patterns = %w(lib/**/*.rb spec/**/*.rb)
94
+ end
95
+ metric_tasks << :roodi
96
+
97
+ task :all => metric_tasks
98
+ end
99
+
100
+ desc "Run Unit Tests - no ArangoDB required"
68
101
  # task :ci => ["spec:unit", "yard:verify"]
69
- task :ci => ["spec:unit"]
102
+ task :ci => ["spec:unit", "spec:acceptance_with_running_arangodb", "metrics:all"]
70
103
 
71
104
  desc "Run all tests and verify documentation - ArangoDB required"
72
105
  # task :default => ["spec:all", "yard:verify"]
73
- task :default => ["spec:all"]
106
+ task :default => ["spec:all", "metrics:all"]
@@ -31,19 +31,26 @@ Gem::Specification.new do |gem|
31
31
  else
32
32
  # RedCarpet is not compatible with JRuby
33
33
  # It is only needed to generate the YARD Documentation
34
- gem.add_development_dependency "redcarpet", "~> 2.2.1"
34
+ gem.add_development_dependency "redcarpet", "~> 2.2.2"
35
35
  end
36
36
 
37
37
  # Development Dependencies
38
38
  gem.add_development_dependency "rake", "~> 0.9.2.2"
39
39
  gem.add_development_dependency "rspec", "~> 2.11.0"
40
40
  gem.add_development_dependency "yard", "~> 0.8.3"
41
- gem.add_development_dependency "webmock", "~> 1.8.9"
41
+ gem.add_development_dependency "webmock", "~> 1.9.0"
42
42
  # gem.add_development_dependency "yardstick", "~> 0.6.0"
43
+ gem.add_development_dependency "simplecov", "~> 0.7.1"
44
+ gem.add_development_dependency "cane", "~> 2.4.0"
45
+ gem.add_development_dependency "roodi1.9", "~> 2.0.1"
43
46
 
44
- gem.add_development_dependency "guard", "~> 1.4.0"
45
- gem.add_development_dependency "guard-rspec", "~> 2.1.0"
47
+ # Do not update to version 3, it is currently not compatible with roodi1.9
48
+ # see grsmv/roodi1.9#1
49
+ gem.add_development_dependency "ruby_parser", "~> 2.3.1"
50
+
51
+ gem.add_development_dependency "guard", "~> 1.5.3"
52
+ gem.add_development_dependency "guard-rspec", "~> 2.1.1"
46
53
  gem.add_development_dependency "guard-bundler", "~> 1.0.0"
47
- gem.add_development_dependency "guard-yard", "~> 2.0.0"
48
- gem.add_development_dependency "rb-fsevent", "~> 0.9.1"
54
+ gem.add_development_dependency "guard-yard", "~> 2.0.1"
55
+ gem.add_development_dependency "rb-fsevent", "~> 0.9.2"
49
56
  end
@@ -1,6 +1,8 @@
1
1
  require "ashikawa-core/document"
2
2
  require "ashikawa-core/index"
3
3
  require "ashikawa-core/cursor"
4
+ require "ashikawa-core/query"
5
+ require "restclient/exceptions"
4
6
  require "forwardable"
5
7
 
6
8
  module Ashikawa
@@ -47,6 +49,12 @@ module Ashikawa
47
49
  # collection.id #=> 4588
48
50
  attr_reader :id
49
51
 
52
+ # The database the collection belongs to
53
+ #
54
+ # @return [Database]
55
+ # @api public
56
+ attr_reader :database
57
+
50
58
  # Sending requests is delegated to the database
51
59
  delegate send_request: :@database
52
60
 
@@ -367,143 +375,6 @@ module Ashikawa
367
375
  send_request_for_this_collection "/truncate", put: {}
368
376
  end
369
377
 
370
- # Retrieves all documents for this collection
371
- #
372
- # @note It is advised to NOT use this method due to possible HUGE data amounts requested
373
- # @option options [Integer] :limit limit the maximum number of queried and returned elements.
374
- # @option options [Integer] :skip skip the first <n> documents of the query.
375
- # @return [Cursor]
376
- # @api public
377
- # @example Get an array with all documents
378
- # database = Ashikawa::Core::Database.new "http://localhost:8529"
379
- # raw_collection = {
380
- # "name" => "example_1",
381
- # "waitForSync" => true,
382
- # "id" => 4588,
383
- # "status" => 3,
384
- # "error" => false,
385
- # "code" => 200
386
- # }
387
- # collection = Ashikawa::Core::Collection.new database, raw_collection
388
- # collection.all # => #<Cursor id=33>
389
- def all(options={})
390
- send_simple_query "/simple/all", options, [:limit, :skip]
391
- end
392
-
393
- # Looks for documents in the collection which match the given criteria
394
- #
395
- # @option options [Hash] :example a Hash with data matching the documents you are looking for.
396
- # @option options [Integer] :limit limit the maximum number of queried and returned elements.
397
- # @option options [Integer] :skip skip the first <n> documents of the query.
398
- # @return [Cursor]
399
- # @api public
400
- # @example Find all documents in the collection that are red
401
- # database = Ashikawa::Core::Database.new "http://localhost:8529"
402
- # raw_collection = {
403
- # "name" => "example_1",
404
- # "waitForSync" => true,
405
- # "id" => 4588,
406
- # "status" => 3,
407
- # "error" => false,
408
- # "code" => 200
409
- # }
410
- # collection = Ashikawa::Core::Collection.new database, raw_collection
411
- # collection.by_example example: { "color" => "red"} # => #<Cursor id=2444>
412
- def by_example(options={})
413
- send_simple_query "/simple/by-example", options, [:limit, :skip, :example]
414
- end
415
-
416
- # Looks for one document in the collection which matches the given criteria
417
- #
418
- # @param [Hash] example a Hash with data matching the document you are looking for.
419
- # @return [Document]
420
- # @api public
421
- # @example Find one document in the collection that is red
422
- # database = Ashikawa::Core::Database.new "http://localhost:8529"
423
- # raw_collection = {
424
- # "name" => "example_1",
425
- # "waitForSync" => true,
426
- # "id" => 4588,
427
- # "status" => 3,
428
- # "error" => false,
429
- # "code" => 200
430
- # }
431
- # collection = Ashikawa::Core::Collection.new database, raw_collection
432
- # collection.first_example { "color" => "red"} # => #<Document id=2444 color="red">
433
- def first_example(example)
434
- server_response = send_request "/simple/first-example",
435
- put: { "collection" => @name, "example" => example }
436
- Document.new @database, server_response
437
- end
438
-
439
- # Looks for documents in the collection based on location
440
- #
441
- # @option options [Integer] :latitude Latitude location for your search.
442
- # @option options [Integer] :longitude Longitude location for your search.
443
- # @option options [Integer] :skip The documents to skip in the query.
444
- # @option options [Integer] :distance If given, the attribute key used to store the distance.
445
- # @option options [Integer] :limit The maximal amount of documents to return (default: 100).
446
- # @option options [Integer] :geo If given, the identifier of the geo-index to use.
447
- # @return [Cursor]
448
- # @api public
449
- # @example Find all documents at Infinite Loop
450
- # database = Ashikawa::Core::Database.new "http://localhost:8529"
451
- # raw_collection = {
452
- # "name" => "example_1",
453
- # "waitForSync" => true,
454
- # "id" => 4588,
455
- # "status" => 3,
456
- # "error" => false,
457
- # "code" => 200
458
- # }
459
- # collection = Ashikawa::Core::Collection.new database, raw_collection
460
- # collection.near latitude: 37.331693, longitude: -122.030468
461
- def near(options={})
462
- send_simple_query "/simple/near", options, [:latitude, :longitude, :distance, :skip, :limit, :geo]
463
- end
464
-
465
- # Looks for documents in the collection within a certain radius
466
- #
467
- # @option options [Integer] :latitude Latitude location for your search.
468
- # @option options [Integer] :longitude Longitude location for your search.
469
- # @option options [Integer] :radius Radius around the given location you want to search in.
470
- # @option options [Integer] :skip The documents to skip in the query.
471
- # @option options [Integer] :distance If given, the attribute key used to store the distance.
472
- # @option options [Integer] :limit The maximal amount of documents to return (default: 100).
473
- # @option options [Integer] :geo If given, the identifier of the geo-index to use.
474
- # @return [Cursor]
475
- # @api public
476
- # @example Find all documents within a radius of 100 to Infinite Loop
477
- # database = Ashikawa::Core::Database.new "http://localhost:8529"
478
- # raw_collection = {
479
- # "name" => "example_1",
480
- # "waitForSync" => true,
481
- # "id" => 4588,
482
- # "status" => 3,
483
- # "error" => false,
484
- # "code" => 200
485
- # }
486
- # collection = Ashikawa::Core::Collection.new database, raw_collection
487
- # collection.within latitude: 37.331693, longitude: -122.030468, radius: 100
488
- def within(options={})
489
- send_simple_query "/simple/within", options, [:latitude, :longitude, :radius, :distance, :skip, :limit, :geo]
490
- end
491
-
492
-
493
- # Looks for documents in the collection with an attribute between two values
494
- #
495
- # @option options [Integer] :attribute The attribute path to check.
496
- # @option options [Integer] :left The lower bound
497
- # @option options [Integer] :right The upper bound
498
- # @option options [Integer] :closed If true, use intervall including left and right, otherwise exclude right, but include left.
499
- # @option options [Integer] :skip The documents to skip in the query (optional).
500
- # @option options [Integer] :limit The maximal amount of documents to return (optional).
501
- # @return [Cursor]
502
- # @api public
503
- def in_range(options={})
504
- send_simple_query "/simple/range", options, [:attribute, :left, :right, :closed, :limit, :skip]
505
- end
506
-
507
378
  # Fetch a certain document by its ID
508
379
  #
509
380
  # @param [Integer] document_id the id of the document
@@ -522,7 +393,7 @@ module Ashikawa
522
393
  Document.new @database, server_response
523
394
  end
524
395
 
525
- # Replace a certain document by its ID
396
+ # Replace a document by its ID
526
397
  #
527
398
  # @param [Integer] document_id the id of the document
528
399
  # @param [Hash] raw_document the data you want to replace it with
@@ -531,7 +402,7 @@ module Ashikawa
531
402
  send_request "/document/#{@id}/#{document_id}", put: raw_document
532
403
  end
533
404
 
534
- # Create a document with given raw data
405
+ # Create a new document from raw data
535
406
  #
536
407
  # @param [Hash] raw_document
537
408
  # @return DocumentHash
@@ -547,10 +418,13 @@ module Ashikawa
547
418
 
548
419
  # Add an index to the collection
549
420
  #
550
- # @param [Symbol] type What kind of index?
551
- # @option opts [Array<Symbol>] on On which fields?
421
+ # @param [Symbol] type specify the type of the index, for example `:hash`
422
+ # @option opts [Array<Symbol>] on fields on which to apply the index
552
423
  # @return Index
553
424
  # @api public
425
+ # @example Add a hash-index to the fields :name and :profession of a collection
426
+ # people = database['people']
427
+ # people.add_index :hash, :on => [:name, :profession]
554
428
  def add_index(type, opts)
555
429
  server_response = send_request "/index?collection=#{@id}", post: {
556
430
  "type" => type.to_s,
@@ -562,7 +436,7 @@ module Ashikawa
562
436
 
563
437
  # Get an index by ID
564
438
  #
565
- # @param [Int] id
439
+ # @param [Integer] id
566
440
  # @return Index
567
441
  # @api public
568
442
  def index(id)
@@ -583,6 +457,14 @@ module Ashikawa
583
457
  end
584
458
  end
585
459
 
460
+ # Return a Query initialized with this collection
461
+ #
462
+ # @return [Query]
463
+ # @api public
464
+ def query
465
+ Query.new self
466
+ end
467
+
586
468
  private
587
469
 
588
470
  # Send a request to the server with the name of the collection prepended
@@ -592,24 +474,6 @@ module Ashikawa
592
474
  def send_request_for_this_collection(path, method={})
593
475
  send_request "/collection/#{id}#{path}", method
594
476
  end
595
-
596
- # Send a simple query to the server
597
- #
598
- # @param [String] path The path for the request
599
- # @param [Hash] options The options given to the method
600
- # @param [Array<Symbol>] keys The required keys
601
- # @return [Hash] The parsed hash for the request
602
- # @api private
603
- def send_simple_query(path, options, keys)
604
- request_data = { "collection" => @name }
605
-
606
- keys.each do |key|
607
- request_data[key.to_s] = options[key] if options.has_key? key
608
- end
609
-
610
- server_response = send_request path, :put => request_data
611
- Cursor.new @database, server_response
612
- end
613
477
  end
614
478
  end
615
479
  end
@@ -1,5 +1,6 @@
1
1
  require "rest-client"
2
2
  require "json"
3
+ require "uri"
3
4
 
4
5
  module Ashikawa
5
6
  module Core
@@ -49,68 +50,93 @@ module Ashikawa
49
50
  # @api public
50
51
  # @example Create a new Connection
51
52
  # connection = Connection.new "http://localhost:8529"
52
- def initialize(api_string="http://localhost:8529")
53
- @api_string = api_string
54
-
55
- require 'uri'
56
- uri = URI(@api_string)
57
- @host = uri.host
58
- @port = uri.port
53
+ def initialize(api_string = "http://localhost:8529")
54
+ uri = URI api_string
55
+ @host = uri.host
56
+ @port = uri.port
59
57
  @scheme = uri.scheme
60
58
  end
61
59
 
62
- def authenticate_with(options={})
63
- if options.key? :username and options.key? :password
64
- @username = options[:username]
65
- @password = options[:password]
66
- else
67
- raise ArgumentError, 'missing username or password'
68
- end
69
-
70
- self
71
- end
72
-
73
- # Sends a request to a given path (Prepends the api_string automatically)
60
+ # Sends a request to a given path returning the parsed result
61
+ # (Prepends the api_string automatically)
74
62
  #
75
63
  # @example get request
76
64
  # connection.send_request('/collection/new_collection')
77
65
  # @example post request
78
66
  # connection.send_request('/collection/new_collection', :post => { :name => 'new_collection' })
79
67
  # @param [String] path the path you wish to send a request to.
80
- # @param [Hash] method_params additional parameters for your request. Only needed if you want to send something other than a GET request.
81
- # @option method_params [Hash] :post POST data in case you want to send a POST request.
68
+ # @option params [Hash] :post POST data in case you want to send a POST request.
82
69
  # @return [Hash] parsed JSON response from the server
83
- # @api semipublic
84
- def send_request(path, method_params = {})
85
- path = "#{url}/_api/#{path.gsub(/^\//, '')}"
70
+ # @api public
71
+ def send_request(path, params = {})
72
+ raw = raw_result_for path, params
73
+ JSON.parse raw
74
+ end
75
+
76
+ # Sends a request to a given path returning the raw result
77
+ # (Prepends the api_string automatically)
78
+ #
79
+ # @example get request
80
+ # connection.raw_result_for('/collection/new_collection')
81
+ # @example post request
82
+ # connection.raw_result_for('/collection/new_collection', :post => { :name => 'new_collection' })
83
+ # @param [String] path the path you wish to send a request to.
84
+ # @option params [Hash] :post POST data in case you want to send a POST request.
85
+ # @return [String] raw response from the server
86
+ # @api public
87
+ def raw_result_for(path, params = {})
88
+ path = full_path path
89
+ method = [:post, :put, :delete].find { |method_name|
90
+ params.has_key? method_name
91
+ } || :get
86
92
 
87
- answer = if method_params.has_key? :post
88
- RestClient.post path, method_params[:post].to_json
89
- elsif method_params.has_key? :put
90
- RestClient.put path, method_params[:put].to_json
91
- elsif method_params.has_key? :delete
92
- RestClient.delete path
93
+ if [:post, :put].include? method
94
+ RestClient.send method, path, params[method].to_json
93
95
  else
94
- RestClient.get path
96
+ RestClient.send method, path
95
97
  end
96
-
97
- JSON.parse answer
98
98
  end
99
99
 
100
+ # Checks if authentication for this Connection is active or not
101
+ #
102
+ # @return [Boolean]
103
+ # @api public
100
104
  def authentication?
101
105
  !!@username
102
106
  end
103
107
 
104
- private
108
+ # Authenticate with given username and password
109
+ #
110
+ # @option [String] username
111
+ # @option [String] password
112
+ # @return [self]
113
+ # @raise [ArgumentError] if username or password are missing
114
+ # @api public
115
+ def authenticate_with(options = {})
116
+ if options.key? :username and options.key? :password
117
+ @username = options[:username]
118
+ @password = options[:password]
119
+ else
120
+ raise ArgumentError, 'missing username or password'
121
+ end
122
+
123
+ self
124
+ end
105
125
 
106
- def url
107
- if authentication?
126
+ # Return the full path for a given API path
127
+ #
128
+ # @param [String] path The API path
129
+ # @return [String] Full path
130
+ # @api public
131
+ def full_path(path)
132
+ prefix = if authentication?
108
133
  "#{@scheme}://#{@username}:#{@password}@#{@host}:#{@port}"
109
134
  else
110
- @api_string
135
+ "#{@scheme}://#{@host}:#{@port}"
111
136
  end
112
- end
113
137
 
138
+ "#{prefix}/_api/#{path.gsub(/^\//, '')}"
139
+ end
114
140
  end
115
141
  end
116
142
  end
@@ -24,10 +24,7 @@ module Ashikawa
24
24
  # @api public
25
25
  def initialize(database, raw_cursor)
26
26
  @database = database
27
- @id = raw_cursor['id'].to_i if raw_cursor.has_key? 'id'
28
- @has_more = raw_cursor['hasMore']
29
- @length = raw_cursor['count'].to_i if raw_cursor.has_key? 'count'
30
- @current = raw_cursor['result']
27
+ parse_raw_cursor raw_cursor
31
28
  end
32
29
 
33
30
  # Iterate over the documents found by the cursor
@@ -43,22 +40,31 @@ module Ashikawa
43
40
  end
44
41
 
45
42
  # Delete the cursor
43
+ # @api public
46
44
  def delete
47
45
  @database.send_request "/cursor/#{@id}", delete: {}
48
46
  end
49
47
 
50
48
  private
51
49
 
50
+ # Pull the raw data from the cursor into this object
51
+ #
52
+ # @api private
53
+ def parse_raw_cursor(raw_cursor)
54
+ @id = raw_cursor['id'].to_i if raw_cursor.has_key? 'id'
55
+ @has_more = raw_cursor['hasMore']
56
+ @length = raw_cursor['count'].to_i if raw_cursor.has_key? 'count'
57
+ @current = raw_cursor['result']
58
+ end
59
+
52
60
  # Get a new batch from the server
53
61
  #
54
62
  # @return [Boolean] Is there a next batch?
63
+ # @api private
55
64
  def next_batch
56
- return @false unless @has_more
65
+ return false unless @has_more
57
66
  raw_cursor = @database.send_request "/cursor/#{@id}", put: {}
58
- @id = raw_cursor['id']
59
- @has_more = raw_cursor['hasMore']
60
- @length = raw_cursor['count']
61
- @current = raw_cursor['result']
67
+ parse_raw_cursor raw_cursor
62
68
  end
63
69
  end
64
70
  end
@@ -68,19 +68,12 @@ module Ashikawa
68
68
  Ashikawa::Core::Collection.new self, server_response
69
69
  end
70
70
 
71
- # Send a query to the database
71
+ # Return a Query initialized with this database
72
72
  #
73
- # @param [String] query
74
- # @option opts [Integer] :count Should the number of results be counted?
75
- # @option opts [Integer] :batch_size Set the number of results returned at once
76
- def query(query, opts = {})
77
- parameter = { query: query }
78
-
79
- parameter[:count] = opts[:count] if opts.has_key? :count
80
- parameter[:batchSize] = opts[:batch_size] if opts.has_key? :batch_size
81
-
82
- server_response = send_request "/cursor", post: parameter
83
- Cursor.new self, server_response
73
+ # @return [Query]
74
+ # @api public
75
+ def query
76
+ Query.new self
84
77
  end
85
78
  end
86
79
  end