ashikawa-core 0.4.1 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
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