couchbase-model 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +1 -1
- data/README.markdown +91 -2
- data/couchbase-model.gemspec +4 -4
- data/lib/couchbase-model.rb +5 -0
- data/lib/couchbase/model.rb +313 -30
- data/lib/couchbase/model/configuration.rb +30 -0
- data/lib/couchbase/model/uuid.rb +10 -0
- data/lib/couchbase/model/version.rb +1 -1
- data/lib/couchbase/railtie.rb +136 -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/test/test_model.rb +42 -1
- metadata +59 -24
@@ -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
|
data/lib/couchbase/model/uuid.rb
CHANGED
@@ -23,15 +23,23 @@ module Couchbase
|
|
23
23
|
|
24
24
|
# Generator of CouchDB specfic UUIDs. This is the ruby implementation of
|
25
25
|
# couch_uuids.erl from couchdb distribution. It is threadsafe.
|
26
|
+
#
|
27
|
+
# @since 0.0.1
|
26
28
|
|
27
29
|
class UUID
|
28
30
|
# Get default UUID generator. You can create your own if you like.
|
31
|
+
#
|
32
|
+
# @since 0.0.1
|
33
|
+
#
|
34
|
+
# @return [UUID]
|
29
35
|
def self.generator
|
30
36
|
@generator ||= UUID.new
|
31
37
|
end
|
32
38
|
|
33
39
|
# Initialize generator.
|
34
40
|
#
|
41
|
+
# @since 0.0.1
|
42
|
+
#
|
35
43
|
# @param [Fixnum] seed seed for pseudorandom number generator.
|
36
44
|
def initialize(seed = nil)
|
37
45
|
seed ? srand(seed) : srand
|
@@ -42,6 +50,8 @@ module Couchbase
|
|
42
50
|
|
43
51
|
# Generate list of UUIDs.
|
44
52
|
#
|
53
|
+
# @since 0.0.1
|
54
|
+
#
|
45
55
|
# @param [Fixnum] count number of UUIDs you need
|
46
56
|
#
|
47
57
|
# @param [Symbol] algorithm Algorithm to use. Known algorithms:
|
@@ -0,0 +1,136 @@
|
|
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
|
+
# Determine which generator to use. app_generators was introduced after
|
27
|
+
# 3.0.0.
|
28
|
+
#
|
29
|
+
# @since 0.1.0
|
30
|
+
#
|
31
|
+
# @example Get the generators method.
|
32
|
+
# railtie.generators
|
33
|
+
#
|
34
|
+
# @return [Symbol] The method name to use.
|
35
|
+
def self.generator
|
36
|
+
config.respond_to?(:app_generators) ? :app_generators : :generators
|
37
|
+
end
|
38
|
+
|
39
|
+
# Maping of rescued exceptions to HTTP responses
|
40
|
+
#
|
41
|
+
# @since 0.1.0
|
42
|
+
#
|
43
|
+
# @example
|
44
|
+
# railtie.rescue_responses
|
45
|
+
#
|
46
|
+
# @return [Hash] rescued responses
|
47
|
+
def self.rescue_responses
|
48
|
+
{
|
49
|
+
"Couchbase::Error::NotFound" => :not_found,
|
50
|
+
"Couchbase::Error::NotStored" => :unprocessable_entity
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
config.send(generator).orm :couchbase, :migration => false
|
55
|
+
|
56
|
+
if config.action_dispatch.rescue_responses
|
57
|
+
config.action_dispatch.rescue_responses.merge!(rescue_responses)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Initialize Couchbase Mode. This will look for a couchbase.yml in the
|
61
|
+
# config directory and configure Couchbase connection appropriately.
|
62
|
+
#
|
63
|
+
# @example couchbase.yml
|
64
|
+
#
|
65
|
+
# common: &common
|
66
|
+
# hostname: localhost
|
67
|
+
# port: 8091
|
68
|
+
# username:
|
69
|
+
# password:
|
70
|
+
# pool: default
|
71
|
+
#
|
72
|
+
# production:
|
73
|
+
# <<: *common
|
74
|
+
# bucket: example_production
|
75
|
+
#
|
76
|
+
# test:
|
77
|
+
# <<: *common
|
78
|
+
# bucket: example_test
|
79
|
+
#
|
80
|
+
# development:
|
81
|
+
# <<: *common
|
82
|
+
# bucket: example_development
|
83
|
+
#
|
84
|
+
initializer "couchbase.setup_connection" do
|
85
|
+
config_file = Rails.root.join("config", "couchbase.yml")
|
86
|
+
if config_file.file? &&
|
87
|
+
config = YAML.load(ERB.new(File.read(config_file)).result)[Rails.env]
|
88
|
+
::Couchbase.connection_options = config.with_indifferent_access
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# After initialization we will warn the user if we can't find a couchbase.yml and
|
93
|
+
# alert to create one.
|
94
|
+
initializer "couchbase.warn_configuration_missing" do
|
95
|
+
unless ARGV.include?("couchbase:config")
|
96
|
+
config.after_initialize do
|
97
|
+
unless Rails.root.join("config", "couchbase.yml").file?
|
98
|
+
puts "\nCouchbase config not found. Create a config file at: config/couchbase.yml"
|
99
|
+
puts "to generate one run: rails generate couchbase:config\n\n"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Check (and upgrade if needed) all design documents
|
106
|
+
initializer "couchbase.upgrade_design_documents", :after =>"couchbase.setup_connection" do |app|
|
107
|
+
config.to_prepare do
|
108
|
+
::Couchbase::Model::Configuration.design_documents_paths ||= app.config.paths["app/models"]
|
109
|
+
app.config.paths["app/models"].each do |path|
|
110
|
+
Dir.glob("#{path}/**/*.rb").sort.each do |file|
|
111
|
+
require_dependency(file.gsub("#{path}/" , "").gsub(".rb", ""))
|
112
|
+
end
|
113
|
+
end
|
114
|
+
begin
|
115
|
+
::Couchbase::Model.descendants.each do |model|
|
116
|
+
model.ensure_design_document!
|
117
|
+
end
|
118
|
+
rescue ::Couchbase::Error::Timeout, ::Couchbase::Error::Connect
|
119
|
+
# skip connection errors for now
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Set the proper error types for Rails. NotFound errors should be
|
125
|
+
# 404s and not 500s, validation errors are 422s.
|
126
|
+
initializer "couchbase.load_http_errors" do |app|
|
127
|
+
config.after_initialize do
|
128
|
+
unless config.action_dispatch.rescue_responses
|
129
|
+
ActionDispatch::ShowExceptions.rescue_responses.update(Railtie.rescue_responses)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
end
|
136
|
+
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'] %>
|
@@ -0,0 +1,40 @@
|
|
1
|
+
// The map function is the most critical part of any view as it provides the
|
2
|
+
// logical mapping between the input fields of the individual objects stored
|
3
|
+
// within Couchbase to the information output when the view is accessed.
|
4
|
+
//
|
5
|
+
// Read more about how to write map functions at:
|
6
|
+
// http://www.couchbase.com/docs/couchbase-manual-2.0/couchbase-views-writing-map.html
|
7
|
+
|
8
|
+
function(doc) {
|
9
|
+
emit(doc._id, null);
|
10
|
+
}
|
11
|
+
|
12
|
+
// You can also check out following examples
|
13
|
+
//
|
14
|
+
// The simplest example of a map function:
|
15
|
+
//
|
16
|
+
// function(doc) {
|
17
|
+
// emit(doc._id, doc);
|
18
|
+
// }
|
19
|
+
//
|
20
|
+
// Slightly more complex example of a function that defines a view on values
|
21
|
+
// computed from customer documents:
|
22
|
+
//
|
23
|
+
// function(doc) {
|
24
|
+
// if (doc.type == "customer") {
|
25
|
+
// emit(doc._id, {last_name: doc.last_name, first_name: doc.first_name});
|
26
|
+
// }
|
27
|
+
// }
|
28
|
+
//
|
29
|
+
// To be able to filter or sort the view by some document property, you
|
30
|
+
// would use that property for the key. For example, the following view
|
31
|
+
// would allow you to lookup customer documents by the last_name or
|
32
|
+
// first_name fields (your keys could be compound, e.g. arrays):
|
33
|
+
//
|
34
|
+
// function(doc) {
|
35
|
+
// if (doc.type == "customer") {
|
36
|
+
// emit(doc.last_name, {first_name: doc.first_name});
|
37
|
+
// emit(doc.first_name, {last_name: doc.last_name});
|
38
|
+
// }
|
39
|
+
// }
|
40
|
+
//
|
@@ -0,0 +1,61 @@
|
|
1
|
+
// If a view has a reduce function, it is used to produce aggregate results
|
2
|
+
// for that view. A reduce function is passed a set of intermediate values
|
3
|
+
// and combines them to a single value. Reduce functions must accept, as
|
4
|
+
// input, results emitted by its corresponding map function as well as
|
5
|
+
// results returned by the reduce function itself. The latter case is
|
6
|
+
// referred to as a rereduce.
|
7
|
+
//
|
8
|
+
// function (key, values, rereduce) {
|
9
|
+
// return sum(values);
|
10
|
+
// }
|
11
|
+
//
|
12
|
+
// Reduce functions must handle two cases:
|
13
|
+
//
|
14
|
+
// 1. When rereduce is false:
|
15
|
+
//
|
16
|
+
// reduce([ [key1,id1], [key2,id2], [key3,id3] ], [value1,value2,value3], false)
|
17
|
+
//
|
18
|
+
// * key will be an array whose elements are arrays of the form [key,id],
|
19
|
+
// where key is a key emitted by the map function and id is that of the
|
20
|
+
// document from which the key was generated.
|
21
|
+
// * values will be an array of the values emitted for the respective
|
22
|
+
// elements in keys
|
23
|
+
//
|
24
|
+
// 2. When rereduce is true:
|
25
|
+
//
|
26
|
+
// reduce(null, [intermediate1,intermediate2,intermediate3], true)
|
27
|
+
//
|
28
|
+
// * key will be null
|
29
|
+
// * values will be an array of values returned by previous calls to the
|
30
|
+
// reduce function
|
31
|
+
//
|
32
|
+
// Reduce functions should return a single value, suitable for both the
|
33
|
+
// value field of the final view and as a member of the values array passed
|
34
|
+
// to the reduce function.
|
35
|
+
//
|
36
|
+
// NOTE: If this file is empty, reduce part will be skipped in design document
|
37
|
+
//
|
38
|
+
// There is number of built-in functions, which could be used instead of
|
39
|
+
// javascript implementation of reduce function.
|
40
|
+
//
|
41
|
+
// The _count function provides a simple count of the input rows from the
|
42
|
+
// map function, using the keys and group level to provide to provide a
|
43
|
+
// count of the correlated items. The values generated during the map()
|
44
|
+
// stage are ignored.
|
45
|
+
//
|
46
|
+
// _count
|
47
|
+
//
|
48
|
+
// The built-in _sum function collates the output from the map function
|
49
|
+
// call. The information can either be a single number or an array of numbers.
|
50
|
+
//
|
51
|
+
// _sum
|
52
|
+
//
|
53
|
+
// The _stats built-in produces statistical calculations for the input data.
|
54
|
+
// Like the _sum call the source information should be a number. The
|
55
|
+
// generated statistics include the sum, count, minimum (min), maximum (max)
|
56
|
+
// and sum squared (sumsqr) of the input rows.
|
57
|
+
//
|
58
|
+
// _stats
|
59
|
+
//
|
60
|
+
// Read more about how to write reduce functions at:
|
61
|
+
// http://www.couchbase.com/docs/couchbase-manual-2.0/couchbase-views-writing-reduce.html
|
@@ -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 ViewGenerator < Rails::Generators::Base
|
25
|
+
desc "Creates a Couchbase views skeletons for map/reduce functions"
|
26
|
+
|
27
|
+
argument :model_name, :type => :string
|
28
|
+
argument :view_name, :type => :string
|
29
|
+
|
30
|
+
source_root File.expand_path("../templates", __FILE__)
|
31
|
+
|
32
|
+
def app_name
|
33
|
+
Rails::Application.subclasses.first.parent.to_s.underscore
|
34
|
+
end
|
35
|
+
|
36
|
+
def create_map_reduce_files
|
37
|
+
template 'map.js', File.join('app', 'models', model_name, view_name, 'map.js')
|
38
|
+
template 'reduce.js', File.join('app', 'models', model_name, view_name, 'reduce.js')
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -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 Couchbase #: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
|