seomoz-ripple 1.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
};
|