couchbase-jruby-model 0.1.0-java
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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +203 -0
- data/README.md +155 -0
- data/Rakefile +22 -0
- data/couchbase-jruby-model.gemspec +27 -0
- data/lib/couchbase-jruby-model.rb +23 -0
- data/lib/couchbase/active_model.rb +69 -0
- data/lib/couchbase/model.rb +859 -0
- data/lib/couchbase/model/configuration.rb +30 -0
- data/lib/couchbase/model/ext/camelize.rb +23 -0
- data/lib/couchbase/model/ext/constantize.rb +29 -0
- data/lib/couchbase/model/ext/singleton_class.rb +24 -0
- data/lib/couchbase/model/uuid.rb +113 -0
- data/lib/couchbase/model/version.rb +26 -0
- data/lib/couchbase/railtie.rb +142 -0
- data/lib/rails/generators/couchbase/config/config_generator.rb +43 -0
- data/lib/rails/generators/couchbase/config/templates/couchbase.yml +23 -0
- data/lib/rails/generators/couchbase/view/templates/map.js +40 -0
- data/lib/rails/generators/couchbase/view/templates/reduce.js +61 -0
- data/lib/rails/generators/couchbase/view/view_generator.rb +43 -0
- data/lib/rails/generators/couchbase_generator.rb +42 -0
- data/tasks/package.rake +27 -0
- data/tasks/test.rake +34 -0
- data/tasks/util.rake +21 -0
- data/test/setup.rb +168 -0
- data/test/test_active_model_integration.rb +124 -0
- data/test/test_model.rb +311 -0
- data/test/test_model_rails_integration.rb +76 -0
- data/test/test_uuid.rb +32 -0
- metadata +151 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
# Author:: Couchbase <info@couchbase.com>
|
2
|
+
# Copyright:: 2012 Couchbase, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
module Couchbase
|
19
|
+
|
20
|
+
class Model
|
21
|
+
|
22
|
+
module Configuration
|
23
|
+
extend self
|
24
|
+
|
25
|
+
attr_accessor :design_documents_paths
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Author:: Couchbase <info@couchbase.com>
|
2
|
+
# Copyright:: 2012 Couchbase, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
class String
|
19
|
+
def camelize
|
20
|
+
res = self.sub(/^[a-z\d]*/) { $&.capitalize }
|
21
|
+
res.gsub(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{$2.capitalize}" }.gsub('/', '::')
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Author:: Couchbase <info@couchbase.com>
|
2
|
+
# Copyright:: 2012 Couchbase, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
class String
|
19
|
+
def constantize
|
20
|
+
names = self.split('::')
|
21
|
+
names.shift if names.empty? || names.first.empty?
|
22
|
+
|
23
|
+
constant = Object
|
24
|
+
names.each do |name|
|
25
|
+
constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
|
26
|
+
end
|
27
|
+
constant
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Author:: Couchbase <info@couchbase.com>
|
2
|
+
# Copyright:: 2012 Couchbase, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
class Object
|
19
|
+
def singleton_class
|
20
|
+
class << self
|
21
|
+
self
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# Author:: Couchbase <info@couchbase.com>
|
2
|
+
# Copyright:: 2012 Couchbase, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require 'thread'
|
19
|
+
|
20
|
+
module Couchbase
|
21
|
+
|
22
|
+
class Model
|
23
|
+
|
24
|
+
# Generator of CouchDB specfic UUIDs. This is the ruby implementation of
|
25
|
+
# couch_uuids.erl from couchdb distribution. It is threadsafe.
|
26
|
+
#
|
27
|
+
# @since 0.0.1
|
28
|
+
|
29
|
+
class UUID
|
30
|
+
# Get default UUID generator. You can create your own if you like.
|
31
|
+
#
|
32
|
+
# @since 0.0.1
|
33
|
+
#
|
34
|
+
# @return [UUID]
|
35
|
+
def self.generator
|
36
|
+
@generator ||= UUID.new
|
37
|
+
end
|
38
|
+
|
39
|
+
# Initialize generator.
|
40
|
+
#
|
41
|
+
# @since 0.0.1
|
42
|
+
#
|
43
|
+
# @param [Fixnum] seed seed for pseudorandom number generator.
|
44
|
+
def initialize(seed = nil)
|
45
|
+
seed ? srand(seed) : srand
|
46
|
+
@prefix, _ = rand_bytes(13).unpack('H26')
|
47
|
+
@inc = rand(0xfff) + 1
|
48
|
+
@lock = Mutex.new
|
49
|
+
end
|
50
|
+
|
51
|
+
# Generate list of UUIDs.
|
52
|
+
#
|
53
|
+
# @since 0.0.1
|
54
|
+
#
|
55
|
+
# @param [Fixnum] count number of UUIDs you need
|
56
|
+
#
|
57
|
+
# @param [Symbol] algorithm Algorithm to use. Known algorithms:
|
58
|
+
# [:random]
|
59
|
+
# 128 bits of random awesome. All awesome, all the time.
|
60
|
+
# [:sequential]
|
61
|
+
# Monotonically increasing ids with random increments. First 26 hex
|
62
|
+
# characters are random. Last 6 increment in random amounts until an
|
63
|
+
# overflow occurs. On overflow, the random prefix is regenerated and
|
64
|
+
# the process starts over.
|
65
|
+
# [:utc_random]
|
66
|
+
# Time since Jan 1, 1970 UTC with microseconds. First 14 characters
|
67
|
+
# are the time in hex. Last 18 are random.
|
68
|
+
#
|
69
|
+
# @return [String, Array] single string value or array of strings. Where
|
70
|
+
# each value represents 128-bit number written in hexadecimal format.
|
71
|
+
def next(count = 1, algorithm = :sequential)
|
72
|
+
raise ArgumentError, 'count should be a positive number' unless count > 0
|
73
|
+
uuids = case algorithm
|
74
|
+
when :random
|
75
|
+
rand_bytes(16 * count).unpack('H32' * count)
|
76
|
+
when :utc_random
|
77
|
+
now = Time.now.utc
|
78
|
+
prefix = '%014x' % [now.to_i * 1_000_000 + now.usec]
|
79
|
+
rand_bytes(9 * count).unpack('H18' * count).map do |tail|
|
80
|
+
"#{prefix}#{tail}"
|
81
|
+
end
|
82
|
+
when :sequential
|
83
|
+
(1..count).map{ next_seq }
|
84
|
+
else
|
85
|
+
raise ArgumentError, "Unknown algorithm #{algo}. Should be one :sequential, :random or :utc_random"
|
86
|
+
end
|
87
|
+
uuids.size == 1 ? uuids[0] : uuids
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def next_seq
|
93
|
+
@lock.synchronize do
|
94
|
+
if @inc >= 0xfff000
|
95
|
+
@prefix, _ = rand_bytes(13).unpack('H26')
|
96
|
+
@inc = rand(0xfff) + 1
|
97
|
+
end
|
98
|
+
@inc += rand(0xfff) + 1
|
99
|
+
'%s%06x' % [@prefix, @inc]
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def rand_bytes(count)
|
104
|
+
bytes = ''
|
105
|
+
count.times { bytes << rand(256) }
|
106
|
+
bytes
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Author:: Couchbase <info@couchbase.com>
|
2
|
+
# Copyright:: 2012 Couchbase, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
module Couchbase
|
19
|
+
|
20
|
+
class Model
|
21
|
+
|
22
|
+
VERSION = '0.1.0'
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,142 @@
|
|
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 'couchbase/model'
|
21
|
+
|
22
|
+
module Rails #:nodoc:
|
23
|
+
module Couchbase #:nodoc:
|
24
|
+
class Railtie < Rails::Railtie #:nodoc:
|
25
|
+
|
26
|
+
config.couchbase = ActiveSupport::OrderedOptions.new
|
27
|
+
config.couchbase.ensure_design_documents ||= true
|
28
|
+
|
29
|
+
# Determine which generator to use. app_generators was introduced after
|
30
|
+
# 3.0.0.
|
31
|
+
#
|
32
|
+
# @since 0.1.0
|
33
|
+
#
|
34
|
+
# @example Get the generators method.
|
35
|
+
# railtie.generators
|
36
|
+
#
|
37
|
+
# @return [Symbol] The method name to use.
|
38
|
+
def self.generator
|
39
|
+
config.respond_to?(:app_generators) ? :app_generators : :generators
|
40
|
+
end
|
41
|
+
|
42
|
+
# Maping of rescued exceptions to HTTP responses
|
43
|
+
#
|
44
|
+
# @since 0.1.0
|
45
|
+
#
|
46
|
+
# @example
|
47
|
+
# railtie.rescue_responses
|
48
|
+
#
|
49
|
+
# @return [Hash] rescued responses
|
50
|
+
def self.rescue_responses
|
51
|
+
{
|
52
|
+
'Couchbase::Error::NotFound' => :not_found,
|
53
|
+
'Couchbase::Error::NotStored' => :unprocessable_entity,
|
54
|
+
'Couchbase::Error::RecordInvalid' => :unprocessable_entity
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
config.send(generator).orm :couchbase, :migration => false
|
59
|
+
|
60
|
+
if config.action_dispatch.rescue_responses
|
61
|
+
config.action_dispatch.rescue_responses.merge!(rescue_responses)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Initialize Couchbase Mode. This will look for a couchbase.yml in the
|
65
|
+
# config directory and configure Couchbase connection appropriately.
|
66
|
+
#
|
67
|
+
# @example couchbase.yml
|
68
|
+
#
|
69
|
+
# common: &common
|
70
|
+
# hostname: localhost
|
71
|
+
# port: 8091
|
72
|
+
# username:
|
73
|
+
# password:
|
74
|
+
# pool: default
|
75
|
+
#
|
76
|
+
# production:
|
77
|
+
# <<: *common
|
78
|
+
# bucket: example_production
|
79
|
+
#
|
80
|
+
# test:
|
81
|
+
# <<: *common
|
82
|
+
# bucket: example_test
|
83
|
+
#
|
84
|
+
# development:
|
85
|
+
# <<: *common
|
86
|
+
# bucket: example_development
|
87
|
+
#
|
88
|
+
initializer 'couchbase.setup_connection' do
|
89
|
+
config_file = Rails.root.join('config', 'couchbase.yml')
|
90
|
+
if config_file.file? &&
|
91
|
+
config = YAML.load(ERB.new(File.read(config_file)).result)[Rails.env]
|
92
|
+
::Couchbase.connection_options = config.with_indifferent_access
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# After initialization we will warn the user if we can't find a couchbase.yml and
|
97
|
+
# alert to create one.
|
98
|
+
initializer 'couchbase.warn_configuration_missing' do
|
99
|
+
unless ARGV.include?('couchbase:config')
|
100
|
+
config.after_initialize do
|
101
|
+
unless Rails.root.join('config', 'couchbase.yml').file?
|
102
|
+
puts "\nCouchbase config not found. Create a config file at: config/couchbase.yml"
|
103
|
+
puts "to generate one run: rails generate couchbase:config\n\n"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Check (and upgrade if needed) all design documents
|
110
|
+
initializer 'couchbase.upgrade_design_documents', :after => 'couchbase.setup_connection' do |app|
|
111
|
+
::Couchbase::Model::Configuration.design_documents_paths ||= app.config.paths['app/models']
|
112
|
+
if config.couchbase.ensure_design_documents
|
113
|
+
config.to_prepare do
|
114
|
+
app.config.paths['app/models'].each do |path|
|
115
|
+
Dir.glob("#{path}/**/*.rb").sort.each do |file|
|
116
|
+
require_dependency(file.gsub("#{path}/" , '').gsub('.rb', ''))
|
117
|
+
end
|
118
|
+
end
|
119
|
+
begin
|
120
|
+
::Couchbase::Model.descendants.each do |model|
|
121
|
+
model.ensure_design_document!
|
122
|
+
end
|
123
|
+
rescue ::Couchbase::Error::Timeout, ::Couchbase::Error::Connect
|
124
|
+
# skip connection errors for now
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# Set the proper error types for Rails. NotFound errors should be
|
131
|
+
# 404s and not 500s, validation errors are 422s.
|
132
|
+
initializer 'couchbase.load_http_errors' do |app|
|
133
|
+
config.after_initialize do
|
134
|
+
unless config.action_dispatch.rescue_responses
|
135
|
+
ActionDispatch::ShowExceptions.rescue_responses.update(Railtie.rescue_responses)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,43 @@
|
|
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_generator'
|
21
|
+
|
22
|
+
module Couchbase
|
23
|
+
module Generators
|
24
|
+
class ConfigGenerator < Rails::Generators::Base
|
25
|
+
desc 'Creates a Couchbase configuration file at config/couchbase.yml'
|
26
|
+
|
27
|
+
argument :database_name, :type => :string, :optional => true
|
28
|
+
|
29
|
+
def self.source_root
|
30
|
+
@_couchbase_source_root ||= File.expand_path('../templates', __FILE__)
|
31
|
+
end
|
32
|
+
|
33
|
+
def app_name
|
34
|
+
Rails::Application.subclasses.first.parent.to_s.underscore
|
35
|
+
end
|
36
|
+
|
37
|
+
def create_config_file
|
38
|
+
template 'couchbase.yml', File.join('config', 'couchbase.yml')
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
common: &common
|
2
|
+
hostname: localhost
|
3
|
+
port: 8091
|
4
|
+
username:
|
5
|
+
password:
|
6
|
+
pool: default
|
7
|
+
|
8
|
+
development:
|
9
|
+
<<: *common
|
10
|
+
bucket: <%= database_name || app_name %>_development
|
11
|
+
|
12
|
+
test:
|
13
|
+
<<: *common
|
14
|
+
bucket: <%= database_name || app_name %>_test
|
15
|
+
|
16
|
+
# set these environment variables on your production server
|
17
|
+
production:
|
18
|
+
hostname: <%%= ENV['COUCHBASE_HOST'] %>
|
19
|
+
port: <%%= ENV['COUCHBASE_PORT'] %>
|
20
|
+
username: <%%= ENV['COUCHBASE_USERNAME'] %>
|
21
|
+
password: <%%= ENV['COUCHBASE_PASSWORD'] %>
|
22
|
+
pool: <%%= ENV['COUCHBASE_POOL'] %>
|
23
|
+
bucket: <%%= ENV['COUCHBASE_BUCKET'] %>
|