seomoz-ripple 1.0.0.pre
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.
- data/Gemfile +20 -0
- data/Guardfile +15 -0
- data/Rakefile +88 -0
- data/lib/rails/generators/ripple/configuration/configuration_generator.rb +13 -0
- data/lib/rails/generators/ripple/configuration/templates/ripple.yml +24 -0
- data/lib/rails/generators/ripple/js/js_generator.rb +13 -0
- data/lib/rails/generators/ripple/js/templates/js/contrib.js +63 -0
- data/lib/rails/generators/ripple/js/templates/js/iso8601.js +76 -0
- data/lib/rails/generators/ripple/js/templates/js/ripple.js +132 -0
- data/lib/rails/generators/ripple/model/model_generator.rb +20 -0
- data/lib/rails/generators/ripple/model/templates/model.rb +10 -0
- data/lib/rails/generators/ripple/observer/observer_generator.rb +16 -0
- data/lib/rails/generators/ripple/observer/templates/observer.rb +4 -0
- data/lib/rails/generators/ripple/test/templates/test_server.rb +46 -0
- data/lib/rails/generators/ripple/test/test_generator.rb +39 -0
- data/lib/rails/generators/ripple_generator.rb +78 -0
- data/lib/ripple.rb +79 -0
- data/lib/ripple/associations.rb +356 -0
- data/lib/ripple/associations/embedded.rb +35 -0
- data/lib/ripple/associations/instantiators.rb +26 -0
- data/lib/ripple/associations/linked.rb +65 -0
- data/lib/ripple/associations/many.rb +38 -0
- data/lib/ripple/associations/many_embedded_proxy.rb +38 -0
- data/lib/ripple/associations/many_linked_proxy.rb +66 -0
- data/lib/ripple/associations/many_reference_proxy.rb +93 -0
- data/lib/ripple/associations/many_stored_key_proxy.rb +76 -0
- data/lib/ripple/associations/one.rb +20 -0
- data/lib/ripple/associations/one_embedded_proxy.rb +35 -0
- data/lib/ripple/associations/one_key_proxy.rb +58 -0
- data/lib/ripple/associations/one_linked_proxy.rb +22 -0
- data/lib/ripple/associations/one_stored_key_proxy.rb +43 -0
- data/lib/ripple/associations/proxy.rb +118 -0
- data/lib/ripple/attribute_methods.rb +118 -0
- data/lib/ripple/attribute_methods/dirty.rb +50 -0
- data/lib/ripple/attribute_methods/query.rb +34 -0
- data/lib/ripple/attribute_methods/read.rb +26 -0
- data/lib/ripple/attribute_methods/write.rb +25 -0
- data/lib/ripple/callbacks.rb +74 -0
- data/lib/ripple/conflict/basic_resolver.rb +82 -0
- data/lib/ripple/conflict/document_hooks.rb +20 -0
- data/lib/ripple/conflict/resolver.rb +71 -0
- data/lib/ripple/conflict/test_helper.rb +33 -0
- data/lib/ripple/conversion.rb +28 -0
- data/lib/ripple/core_ext.rb +2 -0
- data/lib/ripple/core_ext/casting.rb +148 -0
- data/lib/ripple/core_ext/object.rb +8 -0
- data/lib/ripple/document.rb +104 -0
- data/lib/ripple/document/bucket_access.rb +25 -0
- data/lib/ripple/document/finders.rb +131 -0
- data/lib/ripple/document/key.rb +43 -0
- data/lib/ripple/document/link.rb +30 -0
- data/lib/ripple/document/persistence.rb +115 -0
- data/lib/ripple/embedded_document.rb +64 -0
- data/lib/ripple/embedded_document/around_callbacks.rb +18 -0
- data/lib/ripple/embedded_document/finders.rb +26 -0
- data/lib/ripple/embedded_document/persistence.rb +77 -0
- data/lib/ripple/i18n.rb +2 -0
- data/lib/ripple/inspection.rb +32 -0
- data/lib/ripple/locale/en.yml +21 -0
- data/lib/ripple/nested_attributes.rb +265 -0
- data/lib/ripple/observable.rb +28 -0
- data/lib/ripple/properties.rb +73 -0
- data/lib/ripple/property_type_mismatch.rb +12 -0
- data/lib/ripple/railtie.rb +13 -0
- data/lib/ripple/serialization.rb +84 -0
- data/lib/ripple/timestamps.rb +27 -0
- data/lib/ripple/translation.rb +14 -0
- data/lib/ripple/validations.rb +67 -0
- data/lib/ripple/validations/associated_validator.rb +43 -0
- data/ripple.gemspec +46 -0
- data/seomoz-ripple.gemspec +46 -0
- data/spec/fixtures/config.yml +8 -0
- data/spec/integration/ripple/associations_spec.rb +220 -0
- data/spec/integration/ripple/conflict_resolution_spec.rb +293 -0
- data/spec/integration/ripple/nested_attributes_spec.rb +264 -0
- data/spec/integration/ripple/persistence_spec.rb +57 -0
- data/spec/integration/ripple/search_associations_spec.rb +42 -0
- data/spec/ripple/associations/many_embedded_proxy_spec.rb +122 -0
- data/spec/ripple/associations/many_linked_proxy_spec.rb +191 -0
- data/spec/ripple/associations/many_reference_proxy_spec.rb +170 -0
- data/spec/ripple/associations/many_stored_key_proxy_spec.rb +158 -0
- data/spec/ripple/associations/one_embedded_proxy_spec.rb +125 -0
- data/spec/ripple/associations/one_key_proxy_spec.rb +82 -0
- data/spec/ripple/associations/one_linked_proxy_spec.rb +91 -0
- data/spec/ripple/associations/one_stored_key_proxy_spec.rb +72 -0
- data/spec/ripple/associations/proxy_spec.rb +84 -0
- data/spec/ripple/associations_spec.rb +129 -0
- data/spec/ripple/attribute_methods/dirty_spec.rb +80 -0
- data/spec/ripple/attribute_methods_spec.rb +230 -0
- data/spec/ripple/bucket_access_spec.rb +25 -0
- data/spec/ripple/callbacks_spec.rb +176 -0
- data/spec/ripple/conflict/resolver_spec.rb +42 -0
- data/spec/ripple/conversion_spec.rb +22 -0
- data/spec/ripple/core_ext_spec.rb +103 -0
- data/spec/ripple/document/link_spec.rb +67 -0
- data/spec/ripple/document_spec.rb +96 -0
- data/spec/ripple/embedded_document/finders_spec.rb +29 -0
- data/spec/ripple/embedded_document/persistence_spec.rb +80 -0
- data/spec/ripple/embedded_document_spec.rb +84 -0
- data/spec/ripple/finders_spec.rb +217 -0
- data/spec/ripple/inspection_spec.rb +51 -0
- data/spec/ripple/key_spec.rb +30 -0
- data/spec/ripple/observable_spec.rb +121 -0
- data/spec/ripple/persistence_spec.rb +326 -0
- data/spec/ripple/properties_spec.rb +262 -0
- data/spec/ripple/ripple_spec.rb +71 -0
- data/spec/ripple/serialization_spec.rb +51 -0
- data/spec/ripple/timestamps_spec.rb +76 -0
- data/spec/ripple/validations/associated_validator_spec.rb +77 -0
- data/spec/ripple/validations_spec.rb +104 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/associations.rb +1 -0
- data/spec/support/associations/proxies.rb +17 -0
- data/spec/support/integration_setup.rb +11 -0
- data/spec/support/mocks.rb +4 -0
- data/spec/support/models.rb +4 -0
- data/spec/support/models/address.rb +12 -0
- data/spec/support/models/box.rb +13 -0
- data/spec/support/models/car.rb +16 -0
- data/spec/support/models/cardboard_box.rb +3 -0
- data/spec/support/models/clock.rb +12 -0
- data/spec/support/models/clock_observer.rb +3 -0
- data/spec/support/models/company.rb +23 -0
- data/spec/support/models/customer.rb +4 -0
- data/spec/support/models/driver.rb +6 -0
- data/spec/support/models/email.rb +4 -0
- data/spec/support/models/engine.rb +5 -0
- data/spec/support/models/family.rb +16 -0
- data/spec/support/models/favorite.rb +4 -0
- data/spec/support/models/invoice.rb +7 -0
- data/spec/support/models/late_invoice.rb +3 -0
- data/spec/support/models/ninja.rb +9 -0
- data/spec/support/models/note.rb +5 -0
- data/spec/support/models/page.rb +4 -0
- data/spec/support/models/paid_invoice.rb +4 -0
- data/spec/support/models/passenger.rb +6 -0
- data/spec/support/models/profile.rb +10 -0
- data/spec/support/models/seat.rb +5 -0
- data/spec/support/models/subscription.rb +27 -0
- data/spec/support/models/tasks.rb +14 -0
- data/spec/support/models/team.rb +11 -0
- data/spec/support/models/transactions.rb +17 -0
- data/spec/support/models/tree.rb +4 -0
- data/spec/support/models/user.rb +10 -0
- data/spec/support/models/wheel.rb +6 -0
- data/spec/support/models/widget.rb +22 -0
- data/spec/support/test_server.rb +18 -0
- data/spec/support/test_server.yml.example +2 -0
- metadata +362 -0
data/Gemfile
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
source :rubygems
|
|
2
|
+
|
|
3
|
+
gemspec
|
|
4
|
+
gem 'riak-client', :path => "../riak-client"
|
|
5
|
+
gem 'builder', '2.1.2'
|
|
6
|
+
gem 'guard-rspec'
|
|
7
|
+
gem 'rb-fsevent'
|
|
8
|
+
gem 'growl'
|
|
9
|
+
|
|
10
|
+
platforms :mri_18, :jruby do
|
|
11
|
+
gem 'ruby-debug'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
platforms :mri_19 do
|
|
15
|
+
gem 'ruby-debug19'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
platforms :jruby do
|
|
19
|
+
gem 'jruby-openssl'
|
|
20
|
+
end
|
data/Guardfile
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# A sample Guardfile
|
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
|
3
|
+
gemset = ENV['RVM_GEMSET'] || 'ripple'
|
|
4
|
+
gemset = "@#{gemset}" unless gemset.to_s == ''
|
|
5
|
+
|
|
6
|
+
rvms = %w[ 1.8.7 1.9.2 jruby ].map do |version|
|
|
7
|
+
"#{version}@#{gemset}"
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
guard 'rspec', :cli => '--tag ~integration', :rvm => rvms do
|
|
11
|
+
watch(%r{^spec/.+_spec\.rb$})
|
|
12
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
|
13
|
+
watch('spec/spec_helper.rb') { "spec/ripple" }
|
|
14
|
+
end
|
|
15
|
+
|
data/Rakefile
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Copyright 2010-2011 Sean Cribbs and Basho Technologies, Inc.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
require 'rubygems'
|
|
15
|
+
require 'rake/gempackagetask'
|
|
16
|
+
|
|
17
|
+
version = File.read('../VERSION').strip
|
|
18
|
+
|
|
19
|
+
gemspec = Gem::Specification.new do |gem|
|
|
20
|
+
gem.name = "seomoz-ripple"
|
|
21
|
+
gem.summary = %Q{ripple is an object-mapper library for Riak, the distributed database by Basho.}
|
|
22
|
+
gem.description = %Q{ripple is an object-mapper library for Riak, the distributed database by Basho. It uses ActiveModel to provide an experience that integrates well with Rails 3 applications.}
|
|
23
|
+
gem.version = version
|
|
24
|
+
gem.email = "sean@basho.com"
|
|
25
|
+
gem.homepage = "http://seancribbs.github.com/ripple"
|
|
26
|
+
gem.authors = ["Sean Cribbs"]
|
|
27
|
+
gem.add_development_dependency "rspec", "~>2.6.0"
|
|
28
|
+
gem.add_development_dependency 'rake', '~> 0.8.7'
|
|
29
|
+
gem.add_dependency "seomoz-riak-client", "~>#{version}"
|
|
30
|
+
gem.add_dependency "activesupport", [">= 3.0.0", "< 3.2.0"]
|
|
31
|
+
gem.add_dependency "activemodel", [">= 3.0.0", "< 3.2.0"]
|
|
32
|
+
gem.add_dependency "tzinfo"
|
|
33
|
+
|
|
34
|
+
files = FileList["**/*"]
|
|
35
|
+
# Editor and O/S files
|
|
36
|
+
files.exclude ".DS_Store", "*~", "\#*", ".\#*", "*.swp", "*.tmproj", "tmtags"
|
|
37
|
+
# Generated artifacts
|
|
38
|
+
files.exclude "coverage", "rdoc", "pkg", ".bundle", "*.rbc", ".rvmrc", ".watchr", ".rspec"
|
|
39
|
+
# Project-specific
|
|
40
|
+
files.exclude "Gemfile.lock", %r{spec/support/test_server.yml$}, "bin"
|
|
41
|
+
# Remove directories
|
|
42
|
+
files.exclude {|d| File.directory?(d) }
|
|
43
|
+
|
|
44
|
+
gem.files = files.to_a
|
|
45
|
+
|
|
46
|
+
gem.test_files = gem.files.grep(/_spec\.rb$/)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Gem packaging tasks
|
|
50
|
+
Rake::GemPackageTask.new(gemspec) do |pkg|
|
|
51
|
+
pkg.need_zip = false
|
|
52
|
+
pkg.need_tar = false
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
task :gem => :gemspec
|
|
56
|
+
|
|
57
|
+
desc %{Build the gemspec file.}
|
|
58
|
+
task :gemspec do
|
|
59
|
+
gemspec.validate
|
|
60
|
+
File.open("#{gemspec.name}.gemspec", 'w'){|f| f.write gemspec.to_ruby }
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
desc %{Release the gem to RubyGems.org}
|
|
64
|
+
task :release => :gem do
|
|
65
|
+
system "gem push pkg/#{gemspec.name}-#{gemspec.version}.gem"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
require 'rspec/core'
|
|
69
|
+
require 'rspec/core/rake_task'
|
|
70
|
+
|
|
71
|
+
desc "Run Unit Specs Only"
|
|
72
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
|
73
|
+
spec.pattern = "spec/ripple/**/*_spec.rb"
|
|
74
|
+
spec.rspec_opts = %w[--profile]
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
namespace :spec do
|
|
78
|
+
desc "Run Integration Specs Only"
|
|
79
|
+
RSpec::Core::RakeTask.new(:integration) do |spec|
|
|
80
|
+
spec.pattern = "spec/integration/**/*_spec.rb"
|
|
81
|
+
spec.rspec_opts = %w[--profile]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
desc "Run All Specs"
|
|
85
|
+
task :all => [:spec, "spec:integration"]
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
task :default => "spec:all"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require 'rails/generators/ripple_generator'
|
|
2
|
+
|
|
3
|
+
module Ripple
|
|
4
|
+
module Generators
|
|
5
|
+
class ConfigurationGenerator < Base
|
|
6
|
+
desc 'Generates a configuration file for Ripple.'
|
|
7
|
+
|
|
8
|
+
def create_configuration_file
|
|
9
|
+
template 'ripple.yml', 'config/ripple.yml'
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Configure Riak connections for the Ripple library.
|
|
2
|
+
development:
|
|
3
|
+
http_port: 8098
|
|
4
|
+
pb_port: 8087
|
|
5
|
+
host: localhost
|
|
6
|
+
|
|
7
|
+
# The test environment has additional keys for configuring the
|
|
8
|
+
# Riak::TestServer for your test/spec suite:
|
|
9
|
+
#
|
|
10
|
+
# * bin_dir specifies the path to the "riak" script that you use to
|
|
11
|
+
# start Riak (just the directory)
|
|
12
|
+
# * js_source_dir specifies where your custom Javascript functions for
|
|
13
|
+
# MapReduce should be loaded from. Usually app/mapreduce.
|
|
14
|
+
test:
|
|
15
|
+
http_port: 9000
|
|
16
|
+
pb_port: 9002
|
|
17
|
+
host: localhost
|
|
18
|
+
bin_dir: /usr/local/bin # Default for Homebrew.
|
|
19
|
+
js_source_dir: <%%= Rails.root + "app/mapreduce" %>
|
|
20
|
+
|
|
21
|
+
production:
|
|
22
|
+
http_port: 8098
|
|
23
|
+
pb_port: 8087
|
|
24
|
+
host: localhost
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require 'rails/generators/ripple_generator'
|
|
2
|
+
|
|
3
|
+
module Ripple
|
|
4
|
+
module Generators
|
|
5
|
+
class JsGenerator < Base
|
|
6
|
+
desc 'Generates Javascript built-ins for use in your queries.'
|
|
7
|
+
|
|
8
|
+
def create_js_files
|
|
9
|
+
directory 'js', 'app/mapreduce'
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// -------------------------------------------------------------------
|
|
2
|
+
//
|
|
3
|
+
// This file contains Javascript MapReduce functions copied from the
|
|
4
|
+
// "Riak Function Contrib" project.
|
|
5
|
+
//
|
|
6
|
+
Riak.Contrib = {
|
|
7
|
+
// Count keys in a group of results.
|
|
8
|
+
// http://contrib.basho.com/count_keys.html
|
|
9
|
+
mapCount: function(){
|
|
10
|
+
return [1];
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
// Generate commonly used statistics from an array of numbers.
|
|
14
|
+
// Supports count, sum, min, max, percentiles, mean, variance, and
|
|
15
|
+
// stddev.
|
|
16
|
+
// http://contrib.basho.com/stats.html
|
|
17
|
+
reduceStats: function(data) {
|
|
18
|
+
var result = {};
|
|
19
|
+
|
|
20
|
+
data.sort(function(a,b){return a-b;});
|
|
21
|
+
result.count = data.length;
|
|
22
|
+
|
|
23
|
+
// Since the data is sorted, the minimum value
|
|
24
|
+
// is at the beginning of the array, the median
|
|
25
|
+
// value is in the middle of the array, and the
|
|
26
|
+
// maximum value is at the end of the array.
|
|
27
|
+
result.min = data[0];
|
|
28
|
+
result.max = data[data.length - 1];
|
|
29
|
+
|
|
30
|
+
var ntileFunc = function(percentile){
|
|
31
|
+
if (data.length == 1) return data[0];
|
|
32
|
+
var ntileRank = ((percentile/100) * (data.length - 1)) + 1;
|
|
33
|
+
var integralRank = Math.floor(ntileRank);
|
|
34
|
+
var fractionalRank = ntileRank - integralRank;
|
|
35
|
+
var lowerValue = data[integralRank-1];
|
|
36
|
+
var upperValue = data[integralRank];
|
|
37
|
+
return (fractionalRank * (upperValue - lowerValue)) + lowerValue;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
result.percentile25 = ntileFunc(25);
|
|
41
|
+
result.median = ntileFunc(50);
|
|
42
|
+
result.percentile75 = ntileFunc(75);
|
|
43
|
+
result.percentile99 = ntileFunc(99);
|
|
44
|
+
|
|
45
|
+
// Compute the mean and variance using a
|
|
46
|
+
// numerically stable algorithm.
|
|
47
|
+
var sqsum = 0;
|
|
48
|
+
result.mean = data[0];
|
|
49
|
+
result.sum = result.mean * result.count;
|
|
50
|
+
for (var i = 1; i < data.length; ++i) {
|
|
51
|
+
var x = data[i];
|
|
52
|
+
var delta = x - result.mean;
|
|
53
|
+
var sweep = i + 1.0;
|
|
54
|
+
result.mean += delta / sweep;
|
|
55
|
+
sqsum += delta * delta * (i / sweep);
|
|
56
|
+
result.sum += x;
|
|
57
|
+
}
|
|
58
|
+
result.variance = sqsum / result.count;
|
|
59
|
+
result.sdev = Math.sqrt(result.variance);
|
|
60
|
+
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// Written by Paul Sowden, 2005
|
|
2
|
+
// http://delete.me.uk/2005/03/iso8601.html
|
|
3
|
+
// Released under the Academic Free License
|
|
4
|
+
|
|
5
|
+
Date.prototype.setISO8601 = function (string) {
|
|
6
|
+
var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})" +
|
|
7
|
+
"(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?" +
|
|
8
|
+
"(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?";
|
|
9
|
+
var d = string.match(new RegExp(regexp));
|
|
10
|
+
|
|
11
|
+
var offset = 0;
|
|
12
|
+
var date = new Date(d[1], 0, 1);
|
|
13
|
+
|
|
14
|
+
if (d[3]) { date.setMonth(d[3] - 1); }
|
|
15
|
+
if (d[5]) { date.setDate(d[5]); }
|
|
16
|
+
if (d[7]) { date.setHours(d[7]); }
|
|
17
|
+
if (d[8]) { date.setMinutes(d[8]); }
|
|
18
|
+
if (d[10]) { date.setSeconds(d[10]); }
|
|
19
|
+
if (d[12]) { date.setMilliseconds(Number("0." + d[12]) * 1000); }
|
|
20
|
+
if (d[14]) {
|
|
21
|
+
offset = (Number(d[16]) * 60) + Number(d[17]);
|
|
22
|
+
offset *= ((d[15] == '-') ? 1 : -1);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
offset -= date.getTimezoneOffset();
|
|
26
|
+
time = (Number(date) + (offset * 60 * 1000));
|
|
27
|
+
this.setTime(Number(time));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
Date.prototype.iso8601 = function (format, offset) {
|
|
31
|
+
/* accepted values for the format [1-6]:
|
|
32
|
+
1 Year:
|
|
33
|
+
YYYY (eg 1997)
|
|
34
|
+
2 Year and month:
|
|
35
|
+
YYYY-MM (eg 1997-07)
|
|
36
|
+
3 Complete date:
|
|
37
|
+
YYYY-MM-DD (eg 1997-07-16)
|
|
38
|
+
4 Complete date plus hours and minutes:
|
|
39
|
+
YYYY-MM-DDThh:mmTZD (eg 1997-07-16T19:20+01:00)
|
|
40
|
+
5 Complete date plus hours, minutes and seconds:
|
|
41
|
+
YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00)
|
|
42
|
+
6 Complete date plus hours, minutes, seconds and a decimal
|
|
43
|
+
fraction of a second
|
|
44
|
+
YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00)
|
|
45
|
+
*/
|
|
46
|
+
if (!format) { var format = 6; }
|
|
47
|
+
if (!offset) {
|
|
48
|
+
var offset = 'Z';
|
|
49
|
+
var date = this;
|
|
50
|
+
} else {
|
|
51
|
+
var d = offset.match(/([-+])([0-9]{2}):([0-9]{2})/);
|
|
52
|
+
var offsetnum = (Number(d[2]) * 60) + Number(d[3]);
|
|
53
|
+
offsetnum *= ((d[1] == '-') ? -1 : 1);
|
|
54
|
+
var date = new Date(Number(Number(this) + (offsetnum * 60000)));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
var zeropad = function (num) { return ((num < 10) ? '0' : '') + num; }
|
|
58
|
+
|
|
59
|
+
var str = "";
|
|
60
|
+
str += date.getUTCFullYear();
|
|
61
|
+
if (format > 1) { str += "-" + zeropad(date.getUTCMonth() + 1); }
|
|
62
|
+
if (format > 2) { str += "-" + zeropad(date.getUTCDate()); }
|
|
63
|
+
if (format > 3) {
|
|
64
|
+
str += "T" + zeropad(date.getUTCHours()) +
|
|
65
|
+
":" + zeropad(date.getUTCMinutes());
|
|
66
|
+
}
|
|
67
|
+
if (format > 5) {
|
|
68
|
+
var secs = Number(date.getUTCSeconds() + "." +
|
|
69
|
+
((date.getUTCMilliseconds() < 100) ? '0' : '') +
|
|
70
|
+
zeropad(date.getUTCMilliseconds()));
|
|
71
|
+
str += ":" + zeropad(secs);
|
|
72
|
+
} else if (format > 4) { str += ":" + zeropad(date.getUTCSeconds()); }
|
|
73
|
+
|
|
74
|
+
if (format > 3) { str += offset; }
|
|
75
|
+
return str;
|
|
76
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
|
|
2
|
+
/*
|
|
3
|
+
* Namespace for Ripple's built-in MapReduce functions.
|
|
4
|
+
*/
|
|
5
|
+
var Ripple = {
|
|
6
|
+
/*
|
|
7
|
+
* Filter input values by simple equality test on passed "fields"
|
|
8
|
+
* argument. Returns bucket/key pairs for use in later map phases.
|
|
9
|
+
*
|
|
10
|
+
* Raw Phase Example:
|
|
11
|
+
* {"map":{
|
|
12
|
+
* "language":"javascript",
|
|
13
|
+
* "name":"Ripple.filterByFields",
|
|
14
|
+
* "arg":{"manufactured":true, "name":"widget"}
|
|
15
|
+
* }}
|
|
16
|
+
*
|
|
17
|
+
* Ruby invocation example:
|
|
18
|
+
* mr.map("Ripple.filterByFields",
|
|
19
|
+
* :arg => {:manufactured => true, :name => "widget"})
|
|
20
|
+
*
|
|
21
|
+
*/
|
|
22
|
+
filterByFields: function(value, keyData, fields){
|
|
23
|
+
var object = Riak.mapValuesJson(value)[0];
|
|
24
|
+
for(field in fields){
|
|
25
|
+
if(object[field] != fields[field])
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
return [[value.bucket, value.key]];
|
|
29
|
+
},
|
|
30
|
+
/*
|
|
31
|
+
* Filter input values by various conditions passed as the
|
|
32
|
+
* "conditions" argument. Returns bucket/key pairs for use in
|
|
33
|
+
* later map phases.
|
|
34
|
+
*
|
|
35
|
+
* Valid operators:
|
|
36
|
+
* ==, eq (equality)
|
|
37
|
+
* !=, neq (inequality)
|
|
38
|
+
* <, lt (less than)
|
|
39
|
+
* =<, <=, lte (less than or equal)
|
|
40
|
+
* >, gt (greater than)
|
|
41
|
+
* >=, =>, gte (greater than or equal)
|
|
42
|
+
* ~=, match (regular expression match)
|
|
43
|
+
* between (inclusive numeric range)
|
|
44
|
+
* includes (String or Array inclusion)
|
|
45
|
+
*
|
|
46
|
+
* Example:
|
|
47
|
+
* {"map":{
|
|
48
|
+
* "language":"javascript",
|
|
49
|
+
* "name":"Ripple.filterByConditions",
|
|
50
|
+
* "arg":{"tags":{"includes":"riak"}, "title":{"~=":"schema"}}
|
|
51
|
+
* }}
|
|
52
|
+
*
|
|
53
|
+
* Ruby invocation example:
|
|
54
|
+
* mr.map("Ripple.filterByConditions",
|
|
55
|
+
* :arg => {:tags => {:includes => "riak"},
|
|
56
|
+
* :title => {"~=" => "schema"}})
|
|
57
|
+
*/
|
|
58
|
+
filterByConditions: function(value, keyData, conditions){
|
|
59
|
+
var object = Riak.mapValuesJson(value)[0];
|
|
60
|
+
for(condition in conditions){
|
|
61
|
+
if(!Ripple.conditionMatch(condition, conditions[condition], object))
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
return [[value.bucket, value.key]];
|
|
65
|
+
},
|
|
66
|
+
/*
|
|
67
|
+
* Given a specific field and test, returns whether the object
|
|
68
|
+
* matches the condition specified by the test. Used internally by
|
|
69
|
+
* Ripple.filterByConditions map phases.
|
|
70
|
+
*/
|
|
71
|
+
conditionMatch: function(field, test, object){
|
|
72
|
+
for(t in test){
|
|
73
|
+
switch(t){
|
|
74
|
+
case "==": case "eq":
|
|
75
|
+
if(object[field] != test[t])
|
|
76
|
+
return false;
|
|
77
|
+
break;
|
|
78
|
+
case "!=": case "neq":
|
|
79
|
+
if(object[field] == test[t])
|
|
80
|
+
return false;
|
|
81
|
+
break;
|
|
82
|
+
case "<": case "lt":
|
|
83
|
+
if(object[field] >= test[t])
|
|
84
|
+
return false;
|
|
85
|
+
break;
|
|
86
|
+
case "=<": case "<=": case "lte":
|
|
87
|
+
if(object[field] > test[t])
|
|
88
|
+
return false;
|
|
89
|
+
break;
|
|
90
|
+
case ">": case "gt":
|
|
91
|
+
if(object[field] <= test[t])
|
|
92
|
+
return false;
|
|
93
|
+
break;
|
|
94
|
+
case ">=": case "=>": case "gte":
|
|
95
|
+
if(object[field] < test[t])
|
|
96
|
+
return false;
|
|
97
|
+
break;
|
|
98
|
+
case "~=": case "match":
|
|
99
|
+
if(new RegExp(object[field],"i").test(test[t]))
|
|
100
|
+
return false;
|
|
101
|
+
break;
|
|
102
|
+
case "between": // Inclusive on both ends
|
|
103
|
+
if(object[field] < test[t][0] || object[field] > test[t][1])
|
|
104
|
+
return false;
|
|
105
|
+
break;
|
|
106
|
+
case "includes": // Only works with String, Array
|
|
107
|
+
if(object[field].indexOf(test[t]) == -1)
|
|
108
|
+
return false;
|
|
109
|
+
break;
|
|
110
|
+
default:
|
|
111
|
+
ejsLog("Invalid condition for field " + field + ": " + t + " " + test[t], "ripple-error.log");
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return true;
|
|
116
|
+
},
|
|
117
|
+
/*
|
|
118
|
+
* Returns the mapped object without modification. Useful when
|
|
119
|
+
* preceded by map phases that do filtering or link phases.
|
|
120
|
+
*/
|
|
121
|
+
mapIdentity: function(value, kd, arg){
|
|
122
|
+
return [value];
|
|
123
|
+
},
|
|
124
|
+
/*
|
|
125
|
+
* Returns the passed values without modification. Useful as an
|
|
126
|
+
* intermediary before reduce phases that require the entire
|
|
127
|
+
* result set to be present (limits).
|
|
128
|
+
*/
|
|
129
|
+
reduceIdentity: function(values, arg){
|
|
130
|
+
return values;
|
|
131
|
+
}
|
|
132
|
+
};
|