orm_adapter-guacamole 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 744fc399a566ee38824d9dcf341d5b26ac1664c6
4
+ data.tar.gz: 1b14933544229b5b891c9914320cbd31f2afd61d
5
+ SHA512:
6
+ metadata.gz: b2c3ad311ca6f1748c96d0a46a1a0e0851a5e4c8bcad32c084054c0adc0435c3eebaec89c890f087f5218c87b4d8fd2dd2c4cb49bb6e046f9855433b01217f48
7
+ data.tar.gz: 6c6d4d56e8b6dc728d84a2389d2ae28c991fdf3b913f4f73bea9c22c82ec5a94f371df57a289d1c8f4b9ad822e449ff6494523fe059f0545e7470e5200ea3448
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /Gemfile.lock
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /.idea/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in orm_adapter-guacamole.gemspec
4
+ gemspec
@@ -0,0 +1,11 @@
1
+ # _*_ encoding : utf-8 _*_
2
+
3
+ guard :bundler do
4
+ watch(/^.+\.gemspec/)
5
+ end
6
+
7
+ guard :rspec, cmd: 'rspec' do
8
+ watch(%r{spec/.+\.rb})
9
+ watch(%r{lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
10
+ watch('spec/spec_helper.rb') { 'spec' }
11
+ end
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Klaus Humme
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,53 @@
1
+ # OrmAdapter::Guacamole
2
+
3
+ This gem provides a simple entry to [ArangoDB] via [guacamole gem]. Its further use may be e.g. to use Devise
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'orm_adapter-guacamole'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install orm_adapter-guacamole
20
+
21
+ ## Usage
22
+
23
+ Detailed informations about usage are available at [Ian Whites orm_adapter page]
24
+
25
+ NOTICE: Relations between models will not work until now.
26
+
27
+ ## Development
28
+
29
+ To run the specs, you can start from the last known good set of gem dependencies in Gemfile.lock.development:
30
+
31
+ git clone http://github.com/klausinho/orm_adapter-guacamole
32
+ cd orm_adapter-guacamole
33
+ bundle install
34
+ bundle exec rake spec
35
+
36
+ There are 4 pending specs. They are all related to model relations.
37
+ All other tests were green and should be kept green :)
38
+
39
+ ## Contributing
40
+
41
+ 1. Fork it
42
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
43
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
44
+ 4. Push to the branch (`git push origin my-new-feature`)
45
+ 5. Create a new Pull Request
46
+
47
+ [Ian Whites orm_adapter page]: https://github.com/ianwhite/orm_adapter
48
+ [ArangoDB]: https://www.arangodb.com/
49
+ [guacamole gem]: https://github.com/triAGENS/guacamole
50
+
51
+ ## Copyright and License
52
+
53
+ Copyright 2015 by Klaus Humme and Ian White. See LICENSE.txt for further license informations.
@@ -0,0 +1,2 @@
1
+ require 'bundler/gem_tasks'
2
+
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application '_guard-core' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile',
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('guard', '_guard-core')
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'guard' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile',
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('guard', 'guard')
@@ -0,0 +1,148 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require 'guacamole'
4
+ require 'orm_adapter'
5
+
6
+ module Guacamole
7
+ module Model
8
+ module ClassMethods
9
+ include ::OrmAdapter::ToAdapter
10
+ end
11
+
12
+ class OrmAdapter < ::OrmAdapter::Base
13
+ extend Forwardable
14
+
15
+ def self.model_classes
16
+ Guacamole::Model.all
17
+ end
18
+
19
+ # creates the name of the collection from the klass name
20
+ def collection_name
21
+ "#{klass.model_name.to_s.classify.pluralize}Collection".constantize
22
+ end
23
+
24
+ # @see OrmAdapter::Base#get!
25
+ def get!(id)
26
+ collection_name.by_key(wrap_key(id))
27
+ end
28
+
29
+ # @see OrmAdapter::Base#get
30
+ def get(id)
31
+ begin
32
+ collection_name.by_key(wrap_key(id))
33
+ rescue URI::InvalidURIError, Ashikawa::Core::DocumentNotFoundException
34
+ return nil
35
+ end
36
+ end
37
+
38
+ # @see OrmAdapter::Base#find_first
39
+ def find_first(options = {})
40
+ collection_name.by_aql(build_aql(options)).to_a.first
41
+ end
42
+
43
+ # @see OrmAdapter::Base#find_all
44
+ def find_all(options = {})
45
+ collection_name.by_aql(build_aql(options)).to_a
46
+ end
47
+
48
+ # @see OrmAdapter::Base#create
49
+ def create!(attributes = {})
50
+ model = klass.new(attributes)
51
+ collection_name.create model
52
+ end
53
+
54
+ # @see OrmAdapter::Base#destroy
55
+ def destroy(object)
56
+ collection_name.delete(object) && true if valid_object?(object)
57
+ end
58
+
59
+ protected
60
+
61
+ def wrap_key(key)
62
+ key.is_a?(Array) ? key.first : key
63
+ end
64
+
65
+ def build_aql(conditions)
66
+ conditions, order, limit, offset = extract_conditions!(conditions)
67
+ conditions = conditions_to_fields(conditions)
68
+ unless conditions.empty?
69
+ aql_string = "FILTER " << conditions.map{|k, v| "user.#{k} == #{v.inspect}"}.join(" && ")
70
+ unless order.empty?
71
+ order_str =[]
72
+ order.each do |attr, direction|
73
+ order_str << "#{klass.model_name.element}.#{attr} #{direction.upcase}"
74
+ end
75
+ aql_string << " SORT #{order_str.join(', ')}"
76
+ end
77
+ aql_string << " LIMIT #{limit}" unless limit.nil?
78
+ # cause AQL has no single offset method, using the LIMIT 42, 2147483647 is just a workaround
79
+ # (42 would be the offset, 2147483647 is a just a high number for the tests )
80
+ aql_string << " LIMIT #{offset}, 2147483647" unless offset.nil?
81
+ else
82
+ unless order.empty?
83
+ aql_string = 'SORT '
84
+ order_str =[]
85
+ order.each do |attr, direction|
86
+ order_str << "#{klass.model_name.element}.#{attr} #{direction.upcase}"
87
+ end
88
+ aql_string << order_str.join(', ')
89
+ if !limit.nil? && !offset.nil?
90
+ aql_string << " LIMIT #{offset}, #{limit}" unless limit.nil?
91
+ elsif !limit.nil? && offset.nil?
92
+ aql_string << " LIMIT #{limit}"
93
+ elsif limit.nil? && !offset.nil?
94
+ aql_string << " LIMIT #{offset}, 2147483647"
95
+ end
96
+ else
97
+ if !limit.nil? && !offset.nil?
98
+ aql_string = " LIMIT #{offset}, #{limit}" unless limit.nil?
99
+ elsif !limit.nil? && offset.nil?
100
+ aql_string = " LIMIT #{limit}"
101
+ elsif limit.nil? && !offset.nil?
102
+ aql_string = " LIMIT #{offset}, 2147483647"
103
+ end
104
+ end
105
+ end
106
+ aql_string
107
+ end
108
+
109
+ # given an options hash,
110
+ # with optional :conditions, :order, :limit and :offset keys,
111
+ # returns conditions, normalized order, limit and offset
112
+ def extract_conditions!(options = {})
113
+ order = normalize_order(options.delete(:order))
114
+ limit = options.delete(:limit)
115
+ offset = options.delete(:offset)
116
+ conditions = options.delete(:conditions) || options
117
+ [conditions, order, limit, offset]
118
+ end
119
+
120
+ # given an order argument, returns an array of pairs, with each pair containing the attribute, and :asc or :desc
121
+ def normalize_order(order)
122
+ order = Array(order)
123
+ if order.length == 2 && !order[0].is_a?(Array) && [:asc, :desc].include?(order[1])
124
+ order = [order]
125
+ else
126
+ order = order.map {|pair| pair.is_a?(Array) ? pair : [pair, :asc] }
127
+ end
128
+ order.each do |pair|
129
+ pair.length == 2 or raise ArgumentError, "each order clause must be a pair (unknown clause #{pair.inspect})"
130
+ [:asc, :desc].include?(pair[1]) or raise ArgumentError, "order must be specified with :asc or :desc (unknown key #{pair[1].inspect})"
131
+ end
132
+ order
133
+ end
134
+
135
+ # converts and documents to ids
136
+ def conditions_to_fields(conditions)
137
+ conditions.inject({}) do |fields, (key, value)|
138
+ if key.to_s == 'id'
139
+ fields.merge('_key' => value)
140
+ else
141
+ fields.merge(key => value)
142
+ end
143
+ end
144
+ end
145
+
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,2 @@
1
+ require 'orm_adapter-guacamole/version'
2
+ require 'guacamole/model/orm_adapter'
@@ -0,0 +1,5 @@
1
+ module OrmAdapter
2
+ module Guacamole
3
+ VERSION = '0.1.0'
4
+ end
5
+ end
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'orm_adapter-guacamole/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'orm_adapter-guacamole'
8
+ spec.version = OrmAdapter::Guacamole::VERSION
9
+ spec.authors = ['Klaus Humme']
10
+ spec.email = ['klaus_21x2@twentyonetwice.com']
11
+
12
+ spec.summary = 'ORM Adapter for guacamole, the ODM for the NoSQL database ArangoDB'
13
+ spec.description = 'ORM Adapter for guacamole'
14
+ spec.homepage = 'https://github.com/klausinho/orm_adapter-guacamole'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{'^(test|spec|features)/'}) }
18
+ spec.bindir = 'exe'
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_dependency 'orm_adapter', '~> 0.5.0'
23
+ spec.add_dependency 'guacamole', '~> 0.4.0'
24
+
25
+ spec.add_development_dependency 'bundler', '~> 1.8'
26
+ spec.add_development_dependency 'rake', '~> 10.0'
27
+ spec.add_development_dependency 'rspec', '~> 3.2.0', '>= 3.2.0'
28
+ spec.add_development_dependency 'guard', '~> 2.12.4', '>= 2.12.4'
29
+ spec.add_development_dependency 'guard-rspec', '~> 4.4'
30
+ spec.add_development_dependency 'guard-bundler', '~> 2.0'
31
+ spec.add_development_dependency 'pry', '~> 0.10.1'
32
+
33
+ end
@@ -0,0 +1,14 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+ require 'example_app_shared'
5
+
6
+ describe Guacamole::Model::OrmAdapter do
7
+
8
+ it_should_behave_like 'example app with orm_adapter' do
9
+
10
+ let(:user_class) { User }
11
+ let(:note_class) { Note }
12
+
13
+ end
14
+ end
@@ -0,0 +1,7 @@
1
+ class NotesCollection
2
+ include Guacamole::Collection
3
+
4
+ map do
5
+ attribute :user, via: Authorship, inverse: true
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ class UsersCollection
2
+ include Guacamole::Collection
3
+
4
+ map do
5
+ attribute :notes, via: Authorship
6
+ end
7
+ end
@@ -0,0 +1,117 @@
1
+ require 'spec_helper'
2
+
3
+ describe Guacamole::Model::OrmAdapter do
4
+
5
+ subject { Guacamole::Model::OrmAdapter.new(User) }
6
+
7
+ describe 'AQL query should return the correct aql string ' do
8
+ let(:conditions) { {:foo => 'bar'} }
9
+ let(:more_conditions) { { :foo => 'bar', :rating => 42 } }
10
+ let(:order) { [[:foo, :asc]] }
11
+ let(:limit) { 1 }
12
+ let(:offset) { 2 }
13
+
14
+
15
+ it '(<conditions>)' do
16
+ expect(subject.send(:extract_conditions!, conditions)).to eq [conditions, [], nil, nil]
17
+ end
18
+
19
+ it 'with conditions only' do
20
+ expect(subject.send(:build_aql, :conditions => conditions)).to eq("FILTER user.foo == \"bar\"")
21
+ end
22
+
23
+
24
+ it 'with multiple conditions only' do
25
+ expect(subject.send(:build_aql, :conditions => more_conditions)).to eq("FILTER user.foo == \"bar\" && user.rating == 42")
26
+ end
27
+
28
+ it '(:order => <order>)' do
29
+ expect(subject.send(:extract_conditions!, :order => order)).to eq [{}, order, nil, nil]
30
+ end
31
+
32
+ it 'with order clause only' do
33
+ expect(subject.send(:build_aql, :order => order)).to eq('SORT user.foo ASC')
34
+ end
35
+
36
+ it '(:limit => <limit>)' do
37
+ expect(subject.send(:extract_conditions!, :limit => limit)).to eq [{}, [], limit, nil]
38
+ end
39
+
40
+ it 'with limit only' do
41
+ expect(subject.send(:build_aql, :limit => limit)).to eq(' LIMIT 1')
42
+ end
43
+
44
+ it 'with order clause and limit' do
45
+ expect(subject.send(:build_aql, :limit => limit, :order => order)).to eq('SORT user.foo ASC LIMIT 1')
46
+ end
47
+
48
+ it '(:offset => <offset>)' do
49
+ expect(subject.send(:extract_conditions!, :offset => offset)).to eq [{}, [], nil, offset]
50
+ end
51
+
52
+ it 'with offset only' do
53
+ expect(subject.send(:build_aql, :offset => offset)).to eq(' LIMIT 2, 2147483647')
54
+ end
55
+
56
+ it 'with order clause, limit and offset' do
57
+ expect(subject.send(:build_aql, :limit => limit, :order => order, :offset => offset)).to eq('SORT user.foo ASC LIMIT 2, 1')
58
+ end
59
+
60
+ it '(:conditions => <conditions>, :order => <order>)' do
61
+ expect(subject.send(:extract_conditions!, :conditions => conditions, :order => order)).to eq [conditions, order, nil, nil]
62
+ end
63
+
64
+ it 'with conditions and order clause' do
65
+ expect(subject.send(:build_aql, :conditions => conditions, :order => order)).to eq("FILTER user.foo == \"bar\" SORT user.foo ASC")
66
+ end
67
+
68
+ it '(:conditions => <conditions>, :limit => <limit>)' do
69
+ expect(subject.send(:extract_conditions!, :conditions => conditions, :limit => limit)).to eq [conditions, [], limit, nil]
70
+ end
71
+
72
+ it 'with conditions and limit' do
73
+ expect(subject.send(:build_aql, :conditions => conditions, :limit => limit)).to eq("FILTER user.foo == \"bar\" LIMIT 1")
74
+ end
75
+
76
+ it '(:conditions => <conditions>, :offset => <offset>)' do
77
+ expect(subject.send(:extract_conditions!, :conditions => conditions, :offset => offset)).to eq [conditions, [], nil, offset]
78
+ end
79
+
80
+ it 'with conditions and offset' do
81
+ expect(subject.send(:build_aql, :conditions => conditions, :offset => offset)).to eq("FILTER user.foo == \"bar\" LIMIT 2, 2147483647")
82
+ end
83
+
84
+ describe '#valid_object?' do
85
+
86
+ it 'determines whether an object is valid for the current model class' do
87
+ expect(subject.send(:valid_object?, User.new)).to be_truthy
88
+ expect(subject.send(:valid_object?, String.new)).to be_falsey
89
+ end
90
+ end
91
+
92
+ describe '#normalize_order' do
93
+ specify '(nil) returns []' do
94
+ expect(subject.send(:normalize_order, nil)).to eq []
95
+ end
96
+ specify ':foo returns [[:foo, :asc]]' do
97
+ expect(subject.send(:normalize_order, :foo)).to eq [[:foo, :asc]]
98
+ end
99
+ specify '[:foo] returns [[:foo, :asc]]' do
100
+ expect(subject.send(:normalize_order, [:foo])).to eq [[:foo, :asc]]
101
+ end
102
+ specify '[:foo, :desc] returns [[:foo, :desc]]' do
103
+ expect(subject.send(:normalize_order, [:foo, :desc])).to eq [[:foo, :desc]]
104
+ end
105
+ specify '[:foo, [:bar, :asc], [:baz, :desc], :bing] returns [[:foo, :asc], [:bar, :asc], [:baz, :desc], [:bing, :asc]]' do
106
+ expect(subject.send(:normalize_order, [:foo, [:bar, :asc], [:baz, :desc], :bing])).to eq [[:foo, :asc], [:bar, :asc], [:baz, :desc], [:bing, :asc]]
107
+ end
108
+ specify '[[:foo, :wtf]] raises ArgumentError' do
109
+ expect(lambda { subject.send(:normalize_order, [[:foo, :wtf]]) }).to raise_error(ArgumentError)
110
+ end
111
+ specify '[[:foo, :asc, :desc]] raises ArgumentError' do
112
+ expect(lambda { subject.send(:normalize_order, [[:foo, :asc, :desc]]) }).to raise_error(ArgumentError)
113
+ end
114
+ end
115
+ end
116
+
117
+ end
@@ -0,0 +1,7 @@
1
+ test:
2
+ protocol: 'http'
3
+ host: 'localhost'
4
+ port: 8529
5
+ password: 'klaus'
6
+ username: 'test_pw'
7
+ database: 'orm_adapter_spec'
@@ -0,0 +1,6 @@
1
+ class Authorship
2
+ include Guacamole::Edge
3
+
4
+ from :users
5
+ to :notes
6
+ end
@@ -0,0 +1,266 @@
1
+ # Copied from orm_adapter and fixed some Specs
2
+ # to test your new orm_adapter, make an example app that matches the functionality
3
+ # found in the existing specs for example, look at spec/orm_adapter/adapters/active_record_spec.rb
4
+ #
5
+ # Then you can execute this shared spec as follows:
6
+ #
7
+ # it_should_behave_like "example app with orm_adapter" do
8
+ # let(:user_class) { User }
9
+ # let(:note_class) { Note }
10
+ #
11
+ # # optionaly define the following functions if the ORM does not support
12
+ # # this syntax - this should NOT use the orm_adapter, because we're testing that
13
+ # def create_model(klass, attrs = {})
14
+ # klass.create!(attrs)
15
+ # end
16
+ #
17
+ # def reload_model(model)
18
+ # model.class.find(model.id)
19
+ # end
20
+ # end
21
+ #
22
+ shared_examples_for 'example app with orm_adapter' do
23
+
24
+ def create_model(klass, attrs = {})
25
+ collection_name = "#{klass.model_name.to_s.classify.pluralize}Collection".constantize
26
+ model = klass.new(attrs)
27
+ collection_name.create model
28
+ end
29
+
30
+ def reload_model(model)
31
+ collection_name = "#{model.model_name.to_s.classify.pluralize}Collection".constantize
32
+ collection_name.by_key(model.id)
33
+ end
34
+
35
+ describe 'an ORM class' do
36
+
37
+ subject { note_class }
38
+
39
+ it '#to_adapter should return an adapter instance' do
40
+ expect(subject.to_adapter).to be_a(OrmAdapter::Base)
41
+ end
42
+
43
+ it '#to_adapter should return an adapter for the receiver' do
44
+ expect(subject.to_adapter.klass).to eq subject
45
+ end
46
+
47
+ it '#to_adapter should be cached' do
48
+ expect(subject.to_adapter.object_id).to eq subject.to_adapter.object_id
49
+ end
50
+ end
51
+
52
+ describe 'adapter instance' do
53
+
54
+ let(:note_adapter) { note_class.to_adapter }
55
+ let(:user_adapter) { user_class.to_adapter }
56
+
57
+ describe '#get!(id)' do
58
+
59
+ it 'should return the instance with id if it exists' do
60
+ user = create_model(user_class)
61
+ expect(user_adapter.get!(user.id)).to eq user
62
+ end
63
+
64
+ it 'should allow to_key like arguments' do
65
+ user = create_model(user_class)
66
+ expect(user_adapter.get!(user.to_key)).to eq user
67
+ end
68
+
69
+ it 'should raise an error if there is no instance with that id' do
70
+ expect(lambda { user_adapter.get!('nonexistent id') }).to raise_error
71
+ end
72
+
73
+ end
74
+
75
+ describe '#get(id)' do
76
+
77
+ it 'should return the instance with id if it exists' do
78
+ user = create_model(user_class)
79
+ expect(user_adapter.get(user.id)).to eq user
80
+ end
81
+
82
+ it 'should allow to_key like arguments' do
83
+ user = create_model(user_class)
84
+ expect(user_adapter.get(user.to_key)).to eq user
85
+ end
86
+
87
+ it 'should return nil if there is an id which leads into an InvalidURIError' do
88
+ expect(user_adapter.get('nonexistent id')).to be_nil
89
+ end
90
+
91
+ it 'should return nil if there is no instance with that id' do
92
+ expect(user_adapter.get('nonexistent_id')).to be_nil
93
+ end
94
+
95
+ end
96
+
97
+ describe '#find_first' do
98
+
99
+ describe '(conditions)' do
100
+
101
+ it 'should return first model matching conditions, if it exists' do
102
+ user = create_model(user_class, :name => 'Fred')
103
+ expect(user_adapter.find_first(:name => 'Fred')).to eq user
104
+ end
105
+
106
+ it 'should return nil if no conditions match' do
107
+ expect(user_adapter.find_first(:name => 'Betty')).to be_nil
108
+ end
109
+
110
+ it 'should return the first model if no conditions passed' do
111
+ user = create_model(user_class)
112
+ create_model(user_class)
113
+ expect(user_adapter.find_first).to eq user
114
+ end
115
+
116
+ xit 'when conditions contain associated object, should return first model if it exists' do
117
+ user = create_model(user_class)
118
+ user.notes = create_model(note_class, :body => 'test')
119
+ expect(note_adapter.find_first(:user => user)).to eq note
120
+ end
121
+
122
+ it 'understands :id as a primary key condition (allowing scoped finding)' do
123
+ create_model(user_class, :name => 'Fred')
124
+ user = create_model(user_class, :name => 'Fred')
125
+ expect(user_adapter.find_first(:id => user.id, :name => 'Fred')).to eq user
126
+ expect(user_adapter.find_first(:id => user.id, :name => 'Not Fred')).to be_nil
127
+ end
128
+ end
129
+
130
+ describe '(:order => <order array>)' do
131
+
132
+ it 'should return first model in specified order' do
133
+ user1 = create_model(user_class, :name => 'Fred', :rating => 1)
134
+ user2 = create_model(user_class, :name => 'Fred', :rating => 2)
135
+ expect(user_adapter.find_first(:order => [:name, [:rating, :desc]])).to eq user2
136
+ end
137
+ end
138
+
139
+ describe '(:conditions => <conditions hash>, :order => <order array>)' do
140
+
141
+ it 'should return first model matching conditions, in specified order' do
142
+ user1 = create_model(user_class, :name => 'Fred', :rating => 1)
143
+ user2 = create_model(user_class, :name => 'Fred', :rating => 2)
144
+ expect(user_adapter.find_first(:conditions => {:name => 'Fred'}, :order => [:rating, :desc])).to eq user2
145
+ end
146
+ end
147
+ end
148
+
149
+ describe '#find_all' do
150
+
151
+ describe '(conditions)' do
152
+
153
+ it 'should return only models matching conditions' do
154
+ user1 = create_model(user_class, :name => 'Fred')
155
+ user2 = create_model(user_class, :name => 'Fred')
156
+ user3 = create_model(user_class, :name => 'Betty')
157
+ expect(user_adapter.find_all(:name => 'Fred').to_a).to match_array [user1, user2]
158
+ end
159
+
160
+ it 'should return all models if no conditions passed' do
161
+ user1 = create_model(user_class, :name => 'Fred')
162
+ user2 = create_model(user_class, :name => 'Fred')
163
+ user3 = create_model(user_class, :name => 'Betty')
164
+ expect(user_adapter.find_all.to_a).to match_array [user1, user2, user3]
165
+ end
166
+
167
+ it 'should return empty array if no conditions match' do
168
+ expect(user_adapter.find_all(:name => 'Fred')).to eq []
169
+ end
170
+
171
+ xit 'when conditions contain associated object, should return first model if it exists' do
172
+ user1, user2 = create_model(user_class), create_model(user_class)
173
+ note1 = create_model(note_class, :owner => user1)
174
+ note2 = create_model(note_class, :owner => user2)
175
+ expect(note_adapter.find_all(:owner => user2)).to eq [note2]
176
+ end
177
+ end
178
+
179
+ describe '(:order => <order array>)' do
180
+
181
+ it 'should return all models in specified order' do
182
+ user1 = create_model(user_class, :name => 'Fred', :rating => 1)
183
+ user2 = create_model(user_class, :name => 'Fred', :rating => 2)
184
+ user3 = create_model(user_class, :name => 'Betty', :rating => 1)
185
+ expect(user_adapter.find_all(:order => [:name, [:rating, :desc]])).to eq [user3, user2, user1]
186
+ end
187
+ end
188
+
189
+ describe '(:conditions => <conditions hash>, :order => <order array>)' do
190
+
191
+ it 'should return only models matching conditions, in specified order' do
192
+ user1 = create_model(user_class, :name => 'Fred', :rating => 1)
193
+ user2 = create_model(user_class, :name => 'Fred', :rating => 2)
194
+ user3 = create_model(user_class, :name => 'Betty', :rating => 1)
195
+ expect(user_adapter.find_all(:conditions => {:name => 'Fred'}, :order => [:rating, :desc])).to eq [user2, user1]
196
+ end
197
+ end
198
+
199
+ describe '(:limit => <number of items>)' do
200
+
201
+ it 'should return a limited set of matching models' do
202
+ user1 = create_model(user_class, :name => 'Fred', :rating => 1)
203
+ user2 = create_model(user_class, :name => 'Fred', :rating => 2)
204
+ user3 = create_model(user_class, :name => 'Betty', :rating => 3)
205
+ #expect(user_adapter.find_all(:limit => 1, :order => [:rating, :asc])).to eq [user1]
206
+ expect(user_adapter.find_all(:limit => 2, :order => [:rating, :asc])).to eq [user1, user2]
207
+ end
208
+ end
209
+
210
+ describe '(:offset => <offset number>) with limit (as DataMapper does not allow offset on its own)' do
211
+
212
+ it 'should return an offset set of matching models' do
213
+ user1 = create_model(user_class, :name => 'Fred', :rating => 1)
214
+ user2 = create_model(user_class, :name => 'Fred', :rating => 2)
215
+ user3 = create_model(user_class, :name => 'Betty', :rating => 3)
216
+ expect(user_adapter.find_all(:limit => 3, :offset => 0, :order => [:rating, :asc])).to eq [user1, user2, user3]
217
+ expect(user_adapter.find_all(:limit => 3, :offset => 1, :order => [:rating, :asc])).to eq [user2, user3]
218
+ expect(user_adapter.find_all(:limit => 1, :offset => 1, :order => [:rating, :asc])).to eq [user2]
219
+ end
220
+ end
221
+ end
222
+
223
+ describe '#create!(attributes)' do
224
+
225
+ it 'should create a model with the passed attributes' do
226
+ user = user_adapter.create!(:name => 'Fred')
227
+ expect(reload_model(user).name).to eq 'Fred'
228
+ end
229
+
230
+ it 'should raise error when create fails' do
231
+ expect(lambda { user_adapter.create!(:user => create_model(some_class)) }).to raise_error
232
+ end
233
+
234
+ xit 'when attributes contain an associated object, should create a model with the attributes' do
235
+ user = create_model(user_class)
236
+ note = note_adapter.create!(:user => user)
237
+ expect(reload_model(note).user).to eq user
238
+ end
239
+
240
+ xit 'when attributes contain an has_many assoc, should create a model with the attributes' do
241
+ notes = [create_model(note_class), create_model(note_class)]
242
+ user = user_adapter.create!(:notes => notes)
243
+ expect(reload_model(user).notes).to eq notes
244
+ end
245
+ end
246
+
247
+ describe '#destroy(instance)' do
248
+
249
+ it 'should destroy the instance if it exists' do
250
+ user = create_model(user_class)
251
+ expect(!!user_adapter.destroy(user)).to be_truthy
252
+ expect(user_adapter.get(user.id)).to be_nil
253
+ end
254
+
255
+ it 'should return nil if passed with an invalid instance' do
256
+ expect(user_adapter.destroy('nonexistent instance')).to be_nil
257
+ end
258
+
259
+ it 'should not destroy the instance if it does not match the model class' do
260
+ user = create_model(user_class)
261
+ expect(note_adapter.destroy(user)).to be_nil
262
+ expect(user_adapter.get(user.id)).to eq user
263
+ end
264
+ end
265
+ end
266
+ end
@@ -0,0 +1,37 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
5
+ if !defined?(Guacamole) || !(Guacamole.configuration.database.create rescue Ashikawa::Core::ClientError)
6
+ puts "** require 'guacamole' and start ArangoDB to run the specs in #{__FILE__}"
7
+ else
8
+
9
+ # Pure guacamole related specs!
10
+ describe 'The collections' do
11
+
12
+ let(:new_user) { User.new(name: 'Lou', rating: 99) }
13
+ let(:new_note) { Note.new(body: 'Mambo No. 5') }
14
+
15
+ it 'should create a user in the database' do
16
+ UsersCollection.save new_user
17
+
18
+ expect(UsersCollection.by_key(new_user.key)).to eq new_user
19
+ end
20
+
21
+ it 'should create a note in the database' do
22
+ NotesCollection.save new_note
23
+
24
+ expect(NotesCollection.by_key(new_note.key)).to eq new_note
25
+ end
26
+
27
+ it 'should create a relation between user and note' do
28
+ UsersCollection.save new_user
29
+ user = UsersCollection.by_key new_user.key
30
+ user.notes = new_note
31
+ UsersCollection.save user
32
+
33
+ expect(user.notes.first.body).to eq('Mambo No. 5')
34
+ end
35
+ end
36
+
37
+ end
@@ -0,0 +1,11 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ class Note
4
+ include Guacamole::Model
5
+ extend ActiveSupport::Autoload
6
+
7
+ autoload :User, 'models/user'
8
+
9
+ attribute :body, String
10
+ attribute :user, User
11
+ end
@@ -0,0 +1,12 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ class User
4
+ include Guacamole::Model
5
+ extend ActiveSupport::Autoload
6
+
7
+ autoload :Note, 'models/note'
8
+
9
+ attribute :name, String
10
+ attribute :rating, Integer
11
+ attribute :notes, Array[Note]#, coerce: false
12
+ end
@@ -0,0 +1,43 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
4
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
+
6
+ require 'rspec'
7
+ require 'guacamole'
8
+ require 'orm_adapter'
9
+ require 'orm_adapter-guacamole'
10
+ require 'pry'
11
+ require 'models/note'
12
+ require 'models/user'
13
+ require 'edges/authorship'
14
+ require 'collections/notes_collection'
15
+ require 'collections/users_collection'
16
+
17
+
18
+ ENV['GUACAMOLE_ENV'] = 'test'
19
+
20
+ Guacamole.configure do |config|
21
+ config.load File.join(File.dirname(__FILE__), 'config', 'guacamole.yml')
22
+ end
23
+
24
+ begin
25
+ Guacamole.configuration.database.create
26
+ rescue Ashikawa::Core::ClientError
27
+ # Database already exists, don't worry
28
+ end
29
+
30
+ RSpec.configure do |config|
31
+ config.expect_with :rspec do |c|
32
+ c.syntax = :expect
33
+ end
34
+ config.mock_with :rspec do |c|
35
+ c.syntax = :expect
36
+ end
37
+ config.before(:each) do
38
+ Guacamole.configuration.database.truncate
39
+ end
40
+ config.after(:each) do
41
+ Guacamole.configuration.database.truncate
42
+ end
43
+ end
metadata ADDED
@@ -0,0 +1,206 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: orm_adapter-guacamole
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Klaus Humme
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-03-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: orm_adapter
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.5.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.5.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: guacamole
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.4.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.4.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.8'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.8'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 3.2.0
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: 3.2.0
79
+ type: :development
80
+ prerelease: false
81
+ version_requirements: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - "~>"
84
+ - !ruby/object:Gem::Version
85
+ version: 3.2.0
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: 3.2.0
89
+ - !ruby/object:Gem::Dependency
90
+ name: guard
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: 2.12.4
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: 2.12.4
99
+ type: :development
100
+ prerelease: false
101
+ version_requirements: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - "~>"
104
+ - !ruby/object:Gem::Version
105
+ version: 2.12.4
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: 2.12.4
109
+ - !ruby/object:Gem::Dependency
110
+ name: guard-rspec
111
+ requirement: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - "~>"
114
+ - !ruby/object:Gem::Version
115
+ version: '4.4'
116
+ type: :development
117
+ prerelease: false
118
+ version_requirements: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - "~>"
121
+ - !ruby/object:Gem::Version
122
+ version: '4.4'
123
+ - !ruby/object:Gem::Dependency
124
+ name: guard-bundler
125
+ requirement: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - "~>"
128
+ - !ruby/object:Gem::Version
129
+ version: '2.0'
130
+ type: :development
131
+ prerelease: false
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - "~>"
135
+ - !ruby/object:Gem::Version
136
+ version: '2.0'
137
+ - !ruby/object:Gem::Dependency
138
+ name: pry
139
+ requirement: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - "~>"
142
+ - !ruby/object:Gem::Version
143
+ version: 0.10.1
144
+ type: :development
145
+ prerelease: false
146
+ version_requirements: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - "~>"
149
+ - !ruby/object:Gem::Version
150
+ version: 0.10.1
151
+ description: ORM Adapter for guacamole
152
+ email:
153
+ - klaus_21x2@twentyonetwice.com
154
+ executables: []
155
+ extensions: []
156
+ extra_rdoc_files: []
157
+ files:
158
+ - ".gitignore"
159
+ - ".rspec"
160
+ - Gemfile
161
+ - Guardfile
162
+ - LICENSE.txt
163
+ - README.md
164
+ - Rakefile
165
+ - bin/_guard-core
166
+ - bin/guard
167
+ - lib/guacamole/model/orm_adapter.rb
168
+ - lib/orm_adapter-guacamole.rb
169
+ - lib/orm_adapter-guacamole/version.rb
170
+ - orm_adapter-guacamole.gemspec
171
+ - spec/adapter_spec.rb
172
+ - spec/collections/notes_collection.rb
173
+ - spec/collections/users_collection.rb
174
+ - spec/conditions_spec.rb
175
+ - spec/config/guacamole.yml
176
+ - spec/edges/authorship.rb
177
+ - spec/example_app_shared.rb
178
+ - spec/guacamole_spec.rb
179
+ - spec/models/note.rb
180
+ - spec/models/user.rb
181
+ - spec/spec_helper.rb
182
+ homepage: https://github.com/klausinho/orm_adapter-guacamole
183
+ licenses:
184
+ - MIT
185
+ metadata: {}
186
+ post_install_message:
187
+ rdoc_options: []
188
+ require_paths:
189
+ - lib
190
+ required_ruby_version: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ required_rubygems_version: !ruby/object:Gem::Requirement
196
+ requirements:
197
+ - - ">="
198
+ - !ruby/object:Gem::Version
199
+ version: '0'
200
+ requirements: []
201
+ rubyforge_project:
202
+ rubygems_version: 2.4.5
203
+ signing_key:
204
+ specification_version: 4
205
+ summary: ORM Adapter for guacamole, the ODM for the NoSQL database ArangoDB
206
+ test_files: []