couchbase-orm 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,42 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Author:: Couchbase <info@couchbase.com>
4
+ # Copyright:: 2012 Couchbase, Inc.
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ require 'rails/generators/couchbase_orm_generator'
21
+
22
+ module CouchbaseOrm
23
+ module Generators
24
+ class ConfigGenerator < Rails::Generators::Base
25
+ desc 'Creates a Couchbase configuration file at config/couchbase.yml'
26
+ argument :database_name, :type => :string, :optional => true
27
+
28
+ def self.source_root
29
+ @_couchbase_source_root ||= File.expand_path('../templates', __FILE__)
30
+ end
31
+
32
+ def app_name
33
+ Rails::Application.subclasses.first.parent.to_s.underscore
34
+ end
35
+
36
+ def create_config_file
37
+ template 'couchbase.yml', File.join('config', 'couchbase.yml')
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,18 @@
1
+ common: &common
2
+ hosts: localhost
3
+ password:
4
+
5
+ development:
6
+ <<: *common
7
+ bucket: <%= database_name || 'default' %>
8
+
9
+ test:
10
+ <<: *common
11
+ bucket: <%= database_name || app_name %>_test
12
+ password: for_test_bucket
13
+
14
+ # set these environment variables on your production server
15
+ production:
16
+ hosts: <%%= ENV['COUCHBASE_HOST'] || ENV['COUCHBASE_HOSTS'] %>
17
+ bucket: <%%= ENV['COUCHBASE_BUCKET'] %>
18
+ password: <%%= ENV['COUCHBASE_PASSWORD'] %>
@@ -0,0 +1,42 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Author:: Couchbase <info@couchbase.com>
4
+ # Copyright:: 2012 Couchbase, Inc.
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ require 'rails/generators/named_base'
21
+ require 'rails/generators/active_model'
22
+
23
+ module CouchbaseOrm #:nodoc:
24
+ module Generators #:nodoc:
25
+
26
+ class Base < ::Rails::Generators::NamedBase #:nodoc:
27
+
28
+ def self.source_root
29
+ @_couchbase_source_root ||=
30
+ File.expand_path("../#{base_name}/#{generator_name}/templates", __FILE__)
31
+ end
32
+
33
+ unless methods.include?(:module_namespacing)
34
+ def module_namespacing(&block)
35
+ yield if block
36
+ end
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true, encoding: ASCII-8BIT
2
+
3
+ require File.expand_path("../support", __FILE__)
4
+
5
+
6
+ class Parent < CouchbaseOrm::Base
7
+ attribute :name
8
+ end
9
+
10
+ class Child < CouchbaseOrm::Base
11
+ attribute :name
12
+
13
+ belongs_to :parent, dependent: :destroy
14
+ end
15
+
16
+
17
+ describe CouchbaseOrm::Associations do
18
+ it "should work with dependent associations" do
19
+ parent = Parent.create!(name: 'joe')
20
+ child = Child.create!(name: 'bob', parent_id: parent.id)
21
+
22
+ expect(parent.persisted?).to be(true)
23
+ expect(child.persisted?).to be(true)
24
+ id = parent.id
25
+
26
+ child.destroy
27
+ expect(child.destroyed?).to be(true)
28
+ expect(parent.destroyed?).to be(false)
29
+
30
+ # Ensure that parent has been destroyed
31
+ expect { Parent.find(id) }.to raise_error(Libcouchbase::Error::KeyNotFound)
32
+ expect(Parent.find_by_id(id)).to be(nil)
33
+
34
+ expect { parent.reload }.to raise_error(Libcouchbase::Error::KeyNotFound)
35
+
36
+ # Save will always return true unless the model is changed (won't touch the database)
37
+ parent.name = 'should fail'
38
+ expect { parent.save }.to raise_error(Libcouchbase::Error::KeyNotFound)
39
+ expect { parent.save! }.to raise_error(Libcouchbase::Error::KeyNotFound)
40
+ end
41
+
42
+ it "should cache associations" do
43
+ parent = Parent.create!(name: 'joe')
44
+ child = Child.create!(name: 'bob', parent_id: parent.id)
45
+
46
+ id = child.parent.__id__
47
+ expect(parent.__id__).not_to eq(child.parent.__id__)
48
+ expect(parent).to eq(child.parent)
49
+ expect(child.parent.__id__).to eq(id)
50
+
51
+ child.reload
52
+ expect(parent).to eq(child.parent)
53
+ expect(child.parent.__id__).not_to eq(id)
54
+
55
+ child.destroy
56
+ end
57
+
58
+ it "should ignore associations when delete is used" do
59
+ parent = Parent.create!(name: 'joe')
60
+ child = Child.create!(name: 'bob', parent_id: parent.id)
61
+
62
+ id = child.id
63
+ child.delete
64
+
65
+ expect(Child.exists?(id)).to be(false)
66
+ expect(Parent.exists?(parent.id)).to be(true)
67
+
68
+ id = parent.id
69
+ parent.delete
70
+ expect(Parent.exists?(id)).to be(false)
71
+ end
72
+
73
+ describe Parent do
74
+ it_behaves_like "ActiveModel"
75
+ end
76
+
77
+ describe Child do
78
+ it_behaves_like "ActiveModel"
79
+ end
80
+ end
data/spec/base_spec.rb ADDED
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true, encoding: ASCII-8BIT
2
+
3
+ require File.expand_path("../support", __FILE__)
4
+
5
+
6
+ class BaseTest < CouchbaseOrm::Base
7
+ attribute :name, :job
8
+ end
9
+
10
+ class CompareTest < CouchbaseOrm::Base
11
+ attribute :age
12
+ end
13
+
14
+
15
+
16
+ describe CouchbaseOrm::Base do
17
+ it "should be comparable to other objects" do
18
+ base = BaseTest.create!(name: 'joe')
19
+ base2 = BaseTest.create!(name: 'joe')
20
+
21
+ expect(base).to eq(base)
22
+ expect(base).to be(base)
23
+ expect(base).not_to eq(base2)
24
+
25
+ same_base = BaseTest.find(base.id)
26
+ expect(base).to eq(same_base)
27
+ expect(base).not_to be(same_base)
28
+ expect(base2).not_to eq(same_base)
29
+
30
+ base.delete
31
+ base2.delete
32
+ end
33
+
34
+ it "should load database responses" do
35
+ base = BaseTest.create!(name: 'joe')
36
+ resp = BaseTest.bucket.get(base.id, extended: true)
37
+
38
+ expect(resp.key).to eq(base.id)
39
+
40
+ base_loaded = BaseTest.new(resp)
41
+ expect(base_loaded).to eq(base)
42
+ expect(base_loaded).not_to be(base)
43
+
44
+ base.destroy
45
+ end
46
+
47
+ it "should not load objects if there is a type mismatch" do
48
+ base = BaseTest.create!(name: 'joe')
49
+
50
+ expect { CompareTest.find_by_id(base.id) }.to raise_error(RuntimeError)
51
+
52
+ base.destroy
53
+ end
54
+
55
+ it "should support serialisation" do
56
+ base = BaseTest.create!(name: 'joe')
57
+
58
+ base_id = base.id
59
+ expect(base.to_json).to eq({name: 'joe', job: nil, id: base_id}.to_json)
60
+ expect(base.to_json(only: :name)).to eq({name: 'joe'}.to_json)
61
+
62
+ base.destroy
63
+ end
64
+
65
+ describe BaseTest do
66
+ it_behaves_like "ActiveModel"
67
+ end
68
+
69
+ describe CompareTest do
70
+ it_behaves_like "ActiveModel"
71
+ end
72
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true, encoding: ASCII-8BIT
2
+
3
+ require File.expand_path("../support", __FILE__)
4
+
5
+
6
+ class ObjectRatingTest < CouchbaseOrm::Base
7
+ join :object_test, :rating_test
8
+ view :all
9
+ end
10
+
11
+ class RatingTest < CouchbaseOrm::Base
12
+ enum rating: [:awesome, :good, :okay, :bad], default: :okay
13
+ belongs_to :object_test
14
+
15
+ has_many :object_tests, through: :object_rating_test
16
+ view :all
17
+ end
18
+
19
+ class ObjectTest < CouchbaseOrm::Base
20
+ attribute :name, type: String
21
+ has_many :rating_tests, dependent: :destroy
22
+
23
+ view :all
24
+ end
25
+
26
+
27
+ describe CouchbaseOrm::HasMany do
28
+ before :all do
29
+ RatingTest.ensure_design_document!
30
+ ObjectTest.ensure_design_document!
31
+ ObjectRatingTest.ensure_design_document!
32
+ end
33
+
34
+ after :each do
35
+ ObjectTest.all.stream { |ob| ob.delete }
36
+ RatingTest.all.stream { |ob| ob.delete }
37
+ ObjectRatingTest.all.stream { |ob| ob.delete }
38
+ end
39
+
40
+ it "should return matching results" do
41
+ first = ObjectTest.create! name: :bob
42
+ second = ObjectTest.create! name: :jane
43
+
44
+ rate = RatingTest.create! rating: :awesome, object_test: first
45
+ RatingTest.create! rating: :bad, object_test: second
46
+ RatingTest.create! rating: :good, object_test: first
47
+
48
+ expect(rate.object_test_id).to eq(first.id)
49
+ expect(RatingTest.respond_to?(:find_by_object_test_id)).to be(true)
50
+ expect(first.respond_to?(:rating_tests)).to be(true)
51
+
52
+ docs = first.rating_tests.collect { |ob|
53
+ ob.rating
54
+ }
55
+
56
+ expect(docs).to eq([1, 2])
57
+
58
+ first.destroy
59
+ expect { RatingTest.find rate.id }.to raise_error(::Libcouchbase::Error::KeyNotFound)
60
+ expect(RatingTest.all.count).to be(1)
61
+ end
62
+
63
+ it "should work through a join model" do
64
+ first = ObjectTest.create! name: :bob
65
+ second = ObjectTest.create! name: :jane
66
+
67
+ rate1 = RatingTest.create! rating: :awesome, object_test: first
68
+ rate2 = RatingTest.create! rating: :bad, object_test: second
69
+ rate3 = RatingTest.create! rating: :good, object_test: first
70
+
71
+ ort = ObjectRatingTest.create! object_test: first, rating_test: rate1
72
+ ObjectRatingTest.create! object_test: second, rating_test: rate1
73
+
74
+ expect(ort.rating_test_id).to eq(rate1.id)
75
+ expect(rate1.respond_to?(:object_tests)).to be(true)
76
+ docs = rate1.object_tests.collect { |ob|
77
+ ob.name
78
+ }
79
+
80
+ expect(docs).to eq(['bob', 'jane'])
81
+ end
82
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true, encoding: ASCII-8BIT
2
+
3
+ require 'couchbase-orm'
4
+ require 'thread'
5
+
6
+ class IdTestModel < CouchbaseOrm::Base; end
7
+
8
+ describe CouchbaseOrm::IdGenerator do
9
+ it "should not generate ID clashes" do
10
+ model = IdTestModel.new
11
+
12
+ ids1 = []
13
+ thread1 = Thread.new do
14
+ (1..10000).each {
15
+ ids1 << CouchbaseOrm::IdGenerator.next(model)
16
+ }
17
+ end
18
+
19
+ ids2 = []
20
+ thread2 = Thread.new do
21
+ (1..10000).each {
22
+ ids2 << CouchbaseOrm::IdGenerator.next(model)
23
+ }
24
+ end
25
+
26
+ ids3 = []
27
+ thread3 = Thread.new do
28
+ (1..10000).each {
29
+ ids3 << CouchbaseOrm::IdGenerator.next(model)
30
+ }
31
+ end
32
+
33
+ ids4 = []
34
+ thread4 = Thread.new do
35
+ (1..10000).each {
36
+ ids4 << CouchbaseOrm::IdGenerator.next(model)
37
+ }
38
+ end
39
+
40
+ thread1.join
41
+ thread2.join
42
+ thread3.join
43
+ thread4.join
44
+
45
+ results = [ids1, ids2, ids3, ids4].flatten
46
+ expect(results.uniq).to eq(results)
47
+ end
48
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true, encoding: ASCII-8BIT
2
+
3
+ require File.expand_path("../support", __FILE__)
4
+
5
+
6
+ class IndexTest < CouchbaseOrm::Base
7
+ attribute :email
8
+ ensure_unique :email
9
+ end
10
+
11
+ class EnumTest < CouchbaseOrm::Base
12
+ enum visibility: [:group, :authority, :public], default: :authority
13
+ end
14
+
15
+
16
+ describe CouchbaseOrm::Index do
17
+ it "should prevent models being created if they should have unique keys" do
18
+ joe = IndexTest.create!(email: 'joe@aca.com')
19
+ expect { IndexTest.create!(email: 'joe@aca.com') }.to raise_error(CouchbaseOrm::Error::RecordInvalid)
20
+
21
+ joe.email = 'other@aca.com'
22
+ joe.save
23
+ other = IndexTest.new(email: 'joe@aca.com')
24
+ expect(other.save).to be(true)
25
+
26
+ expect { IndexTest.create!(email: 'joe@aca.com') }.to raise_error(CouchbaseOrm::Error::RecordInvalid)
27
+ expect { IndexTest.create!(email: 'other@aca.com') }.to raise_error(CouchbaseOrm::Error::RecordInvalid)
28
+
29
+ joe.destroy
30
+ other.destroy
31
+
32
+ again = IndexTest.new(email: 'joe@aca.com')
33
+ expect(again.save).to be(true)
34
+
35
+ again.destroy
36
+ end
37
+
38
+ it "should provide helper methods for looking up the model" do
39
+ joe = IndexTest.create!(email: 'joe@aca.com')
40
+
41
+ joe_again = IndexTest.find_by_email('joe@aca.com')
42
+ expect(joe).to eq(joe_again)
43
+
44
+ joe.destroy
45
+ end
46
+
47
+ it "should clean up itself if dangling keys are left" do
48
+ joe = IndexTest.create!(email: 'joe@aca.com')
49
+ joe.delete # no callbacks are executed
50
+
51
+ again = IndexTest.new(email: 'joe@aca.com')
52
+ expect(again.save).to be(true)
53
+
54
+ again.destroy
55
+ end
56
+
57
+ it "should work with enumerators" do
58
+ # Test symbol
59
+ enum = EnumTest.create!(visibility: :public)
60
+ expect(enum.visibility).to eq(3)
61
+ enum.destroy
62
+
63
+ # Test number
64
+ enum = EnumTest.create!(visibility: 2)
65
+ expect(enum.visibility).to eq(2)
66
+ enum.destroy
67
+
68
+ # Test default
69
+ enum = EnumTest.create!
70
+ expect(enum.visibility).to eq(2)
71
+ enum.destroy
72
+ end
73
+ end