active_datastore 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 3b916ae69eb1d47e3734ab3d833766118a1ceea4
4
- data.tar.gz: 52c7af6d7bb4ef3be9f768adc8eab5187a5799ea
5
- SHA512:
6
- metadata.gz: 287950a37eec281f80d0b22d0582115c8ac759a6015f8e31bda56f78eb9fa6d03de522c2af15a7f7333b8a724c3372330f789f3cef225f1defcfec1a7d738817
7
- data.tar.gz: 9e899419c16fb4483ca76f9a2797ddd4b47c1e4071a950e5f7b82e136b468ce174d6436372dcd48478de49f1013bf201379894983723920fde83397fd5ccaef2
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MGQ0ZDdhOTg2MjdkNDM1ZjEwYzc5NzE4NzU0YzMyMGNmNTU4NjcxOA==
5
+ data.tar.gz: !binary |-
6
+ NzQxYzljYjdiM2I3YWVmYWIwMDliMTEzM2ViYTQzY2UxZmVlMDM3Mw==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ ZGIwOTdmM2VjNGRmNjk5YmM3YjE5ZGMyY2UzNTk4ZWJmODhiNGM5NTczM2Vh
10
+ OTJjMTEzZmJmYjJjOWE2NGIzM2I3ZWE2ZmE0NTEyMzMzMDViOWE3NTg2N2U2
11
+ MDgzYWEzZDljNmY1OTIyZmUwOGZlNTdjYmRkODRkZTk5MmNmMDg=
12
+ data.tar.gz: !binary |-
13
+ ODE5MTlmYTdjNjU1MjdhMjIwMjUxMDU1MmM2MzY2MDc0M2U5YmQwZDI1MGJk
14
+ ZDFjNzViOGQzYWZmYjRjNzdiNmY5MjZhNGViYzExNDdmMmZkNGI3NTIwN2Ey
15
+ YTY2YTY3NWQ2NDgyY2EzMjk5MTFiMWE2ZWEyOTNlZjQxNjE4OGQ=
data/.gitignore CHANGED
@@ -15,3 +15,9 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+
19
+ *.p12
20
+
21
+ spec/credentials.yml
22
+
23
+ .DS_Store
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 1.9.3-p392
data/Gemfile CHANGED
@@ -1,4 +1,12 @@
1
1
  source 'https://rubygems.org'
2
+ ruby '1.9.3'
2
3
 
3
- # Specify your gem's dependencies in active_datastore.gemspec
4
+ gem 'google-api-client'
5
+ gem 'json'
6
+ gem 'oj'
7
+ gem 'active_support'
8
+ gem 'i18n'
4
9
  gemspec
10
+
11
+ gem 'rspec'
12
+ gem 'pry'
data/README.md CHANGED
@@ -1,6 +1,13 @@
1
1
  # ActiveDatastore
2
2
 
3
- TODO: Write a gem description
3
+ With the release of the [Google Cloud Datastore API](https://developers.google.com/datastore/), it's finally possible to leverage the datastore in pretty much any stack. Since Google seems to be supporting NodeJS, Python and Java right of the bat, it makes sense to bridge the Ruby gap.
4
+
5
+ ActiveDatastore is (eventually) meant to be comparable to [ActiveRecord](https://github.com/rails/rails/tree/master/activerecord) in terms of API, features and ease of use. It will rely heavily on [ActiveModel](https://github.com/rails/rails/tree/master/activemodel), but will continue to be framework agnostic and usable with or without [Rails](http://rubyonrails.org/).
6
+
7
+ ## Current Status
8
+ I've built a wrapper over the GCD API (`ActiveDatastore::Dataset`) that's fully functional and can be used for pretty much all the examples given in the documentation. The wrapper's API is very similar to what you see in the NodeJS examples.
9
+
10
+ Right now, ActiveDatastore is very much a work in progress. Please evaluate it before production use, and do remember that the API will undergo breaking changes until we hit v1.0.
4
11
 
5
12
  ## Installation
6
13
 
@@ -18,12 +25,44 @@ Or install it yourself as:
18
25
 
19
26
  ## Usage
20
27
 
21
- TODO: Write usage instructions here
28
+ Follow the instructions [here](https://developers.google.com/datastore/docs/activate#google_cloud_datastore_from_other_platforms) to get your **service account** (`AUTH_EMAIL`), **private key** (`AUTH_KEY`) and **dataset id** (`DATASET_ID`).
29
+
30
+ In your initializer (if you're on Rails you could create `config/initializers/datastore.rb`):
31
+
32
+ require 'active_datastore'
33
+
34
+ AUTH_EMAIL = "something@developer.gserviceaccount.com"
35
+ AUTH_KEY = File.open("path/to/my/secret.key.p12").read
36
+ DATASET_ID = "my-dataset"
37
+
38
+ client = ActiveDatastore::Client.new AUTH_EMAIL, AUTH_KEY
39
+ $dataset = ActiveDatastore::Dataset.new DATASET_ID, client
40
+
41
+ The initialization of the client seems be performance / network intensive, so it might make sense to do it once and hold the `$dataset` for the lifetime of the application. `ActiveDatastore::Dataset` is stateless and should support this.
42
+
43
+ To make calls to the datastore, use the methods documented on the [JSON API Reference](https://developers.google.com/datastore/docs/apis/v1beta1/datasets) (but remember use the underscore equivalent names.)
44
+
45
+ start_response = $dataset.begin_transaction({
46
+ isolationLevel: "snapshot"
47
+ })
48
+
49
+ start_response.data.kind # Should be "datastore#beginTransactionResponse"
50
+ transaction_id = start_response.data.transaction
51
+
52
+ rollback_response = $dataset.rollback({
53
+ transaction: transaction_id
54
+ })
55
+
56
+ rollback_response.data.kind # Should be "datastore#rollbackResponse"
57
+
58
+ Remeber that both the request body and the `response.data` are hashes with camel case keys, as shown in the [docs](https://developers.google.com/datastore/docs/apis/v1beta1/datasets/lookup#response). I know it's a little inconsistent that way, but an effort to deeply walk through each hash and convert keys will probably be more trouble than it's worth.
59
+
22
60
 
23
61
  ## Contributing
24
62
 
25
- 1. Fork it
63
+ 1. Fork the repo
26
64
  2. Create your feature branch (`git checkout -b my-new-feature`)
27
- 3. Commit your changes (`git commit -am 'Add some feature'`)
28
- 4. Push to the branch (`git push origin my-new-feature`)
29
- 5. Create new Pull Request
65
+ 3. **WRITE GOOD AND CLEAR TESTS**. Do remember that this gem may be used in production to serve millions of requests. Bugs can be catastrophic. Also, I can't merge and maintain code I don't fully understand.
66
+ 4. Commit your changes (`git commit -am 'Add some feature'`)
67
+ 5. Push to the branch (`git push origin my-new-feature`)
68
+ 6. Create new Pull Request
data/Rakefile CHANGED
@@ -1 +1,7 @@
1
1
  require "bundler/gem_tasks"
2
+
3
+ require "rspec/core/rake_task"
4
+
5
+ RSpec::Core::RakeTask.new('spec')
6
+
7
+ task :default => :spec
@@ -8,9 +8,9 @@ Gem::Specification.new do |spec|
8
8
  spec.version = ActiveDatastore::VERSION
9
9
  spec.authors = ["Sudhir Jonathan"]
10
10
  spec.email = ["sudhir.j@gmail.com"]
11
- spec.description = "Active Wrapper for GCD"
12
- spec.summary = "Wrapper for Google Cloud datastore"
13
- spec.homepage = ""
11
+ spec.description = "With the release of the Google Cloud Datastore API, its now possible to use the full power of Google's datastore in Ruby apps. ActiveDatastore is right now a clean wrapper over the API, and I'd like to take to a point where it's camparable and similar to ActiveRecord."
12
+ spec.summary = "ODM (Object-Document-Mapper) for the Google Cloud Datastore."
13
+ spec.homepage = "https://github.com/sudhirj/active_datastore"
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files`.split($/)
@@ -1,4 +1,8 @@
1
+ require 'active_support/all'
2
+
1
3
  require "active_datastore/version"
4
+ require "active_datastore/client"
5
+ require "active_datastore/dataset"
2
6
 
3
7
  module ActiveDatastore
4
8
  # Your code goes here...
@@ -0,0 +1,32 @@
1
+ require 'google/api_client'
2
+
3
+ module ActiveDatastore
4
+ class Client
5
+ def initialize email, secret
6
+ @client = Google::APIClient.new
7
+ key = Google::APIClient::KeyUtils.load_from_pkcs12(secret, 'notasecret')
8
+ service_account = Google::APIClient::JWTAsserter.new(
9
+ email,
10
+ ['https://www.googleapis.com/auth/datastore', 'https://www.googleapis.com/auth/userinfo.email'],
11
+ key)
12
+ @client.authorization = service_account.authorize
13
+
14
+ end
15
+
16
+ def valid?
17
+ not @client.authorization.expired?
18
+ end
19
+
20
+ def api
21
+ @api ||= @client.discovered_api('datastore', 'v1beta1').datasets
22
+ end
23
+
24
+ def execute opts
25
+ @client.execute({
26
+ api_method: api.send(opts[:method]),
27
+ body_object: opts[:body],
28
+ parameters: opts[:params]
29
+ })
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,15 @@
1
+ module ActiveDatastore
2
+ class Dataset
3
+ METHODS = [:allocate_ids, :begin_transaction, :blind_write, :commit, :lookup, :rollback, :run_query]
4
+ def initialize dataset_id, client
5
+ @client = client
6
+ @dataset_id = dataset_id
7
+ end
8
+
9
+ METHODS.each do |method|
10
+ define_method method do |body={}|
11
+ @client.execute method: method, body: body, params: {datasetId: @dataset_id}
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,3 +1,3 @@
1
1
  module ActiveDatastore
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+ require 'pry'
3
+ describe ActiveDatastore::Client do
4
+
5
+ let (:client) { ActiveDatastore::Client.new AUTH_EMAIL, AUTH_KEY }
6
+
7
+ it 'should connect to the GCD, given credentials' do
8
+ client.valid?.should be_true
9
+ end
10
+
11
+ it 'should discover the datastore api' do
12
+ client.api.lookup.generate_uri(datasetId: 'abc').to_s.should == "https://www.googleapis.com/datastore/v1beta1/datasets/abc/lookup"
13
+ end
14
+
15
+ it 'should execute calls made using the google client' do
16
+ response = client.execute method: :begin_transaction, body: {"isolationLevel" => "snapshot"}, params: {datasetId: 'active-datastore-test'}
17
+ response.data.transaction.should_not be_nil
18
+ response.data.kind.should == 'datastore#beginTransactionResponse'
19
+ end
20
+ end
@@ -0,0 +1,2 @@
1
+ EMAIL: "something@developer.gserviceaccount.com"
2
+ KEY_PATH: "key.p12 (the path from the top level gem directory)"
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveDatastore::Dataset do
4
+ let (:client) { ActiveDatastore::Client.new AUTH_EMAIL, AUTH_KEY }
5
+ let (:dataset) { ActiveDatastore::Dataset.new 'active-datastore-test', client }
6
+
7
+ it "should have all the datastore api methods" do
8
+ discovered_methods = client.api.discovered_methods.map(&:id).map{|n| n.split('.')[2]}.map(&:underscore).map(&:to_sym)
9
+ ActiveDatastore::Dataset::METHODS.sort.should == discovered_methods.sort
10
+
11
+ ActiveDatastore::Dataset::METHODS.each do |method|
12
+ dataset.respond_to?(method).should be_true
13
+ end
14
+ end
15
+
16
+ it "should execute corresponding methods on the client with the given parameters, always including the dataset id" do
17
+ ActiveDatastore::Dataset::METHODS.each do |method|
18
+ client.should_receive(:execute).with(method: method, body: {abc: 42}, params: {datasetId: 'active-datastore-test'} )
19
+ dataset.send(method, {abc: 42})
20
+ end
21
+ end
22
+
23
+ context "transactions" do
24
+ it 'should start and rollback a transaction' do
25
+ start_response = dataset.begin_transaction
26
+ start_response.data.kind.should == "datastore#beginTransactionResponse"
27
+ start_response.data.transaction.should_not be_nil
28
+
29
+ rollback_response = dataset.rollback({transaction: start_response.data.transaction})
30
+ rollback_response.data.kind.should == "datastore#rollbackResponse"
31
+ end
32
+ end
33
+
34
+ end
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'active_datastore'
5
+
6
+ credentials = YAML.load File.open 'spec/credentials.yml'
7
+
8
+ AUTH_EMAIL = credentials["EMAIL"]
9
+ AUTH_KEY = File.open(credentials["KEY_PATH"]).read
10
+
11
+ RSpec.configure do |config|
12
+
13
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_datastore
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sudhir Jonathan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-05-21 00:00:00.000000000 Z
11
+ date: 2013-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -28,17 +28,20 @@ dependencies:
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ! '>='
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ! '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
- description: Active Wrapper for GCD
41
+ description: With the release of the Google Cloud Datastore API, its now possible
42
+ to use the full power of Google's datastore in Ruby apps. ActiveDatastore is right
43
+ now a clean wrapper over the API, and I'd like to take to a point where it's camparable
44
+ and similar to ActiveRecord.
42
45
  email:
43
46
  - sudhir.j@gmail.com
44
47
  executables: []
@@ -46,14 +49,22 @@ extensions: []
46
49
  extra_rdoc_files: []
47
50
  files:
48
51
  - .gitignore
52
+ - .rspec
53
+ - .ruby-version
49
54
  - Gemfile
50
55
  - LICENSE.txt
51
56
  - README.md
52
57
  - Rakefile
53
58
  - active_datastore.gemspec
54
59
  - lib/active_datastore.rb
60
+ - lib/active_datastore/client.rb
61
+ - lib/active_datastore/dataset.rb
55
62
  - lib/active_datastore/version.rb
56
- homepage: ''
63
+ - spec/client_spec.rb
64
+ - spec/credentials.yml.example
65
+ - spec/dataset_spec.rb
66
+ - spec/spec_helper.rb
67
+ homepage: https://github.com/sudhirj/active_datastore
57
68
  licenses:
58
69
  - MIT
59
70
  metadata: {}
@@ -63,12 +74,12 @@ require_paths:
63
74
  - lib
64
75
  required_ruby_version: !ruby/object:Gem::Requirement
65
76
  requirements:
66
- - - '>='
77
+ - - ! '>='
67
78
  - !ruby/object:Gem::Version
68
79
  version: '0'
69
80
  required_rubygems_version: !ruby/object:Gem::Requirement
70
81
  requirements:
71
- - - '>='
82
+ - - ! '>='
72
83
  - !ruby/object:Gem::Version
73
84
  version: '0'
74
85
  requirements: []
@@ -76,5 +87,9 @@ rubyforge_project:
76
87
  rubygems_version: 2.0.3
77
88
  signing_key:
78
89
  specification_version: 4
79
- summary: Wrapper for Google Cloud datastore
80
- test_files: []
90
+ summary: ODM (Object-Document-Mapper) for the Google Cloud Datastore.
91
+ test_files:
92
+ - spec/client_spec.rb
93
+ - spec/credentials.yml.example
94
+ - spec/dataset_spec.rb
95
+ - spec/spec_helper.rb