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.
Files changed (149) hide show
  1. data/Gemfile +20 -0
  2. data/Guardfile +15 -0
  3. data/Rakefile +88 -0
  4. data/lib/rails/generators/ripple/configuration/configuration_generator.rb +13 -0
  5. data/lib/rails/generators/ripple/configuration/templates/ripple.yml +24 -0
  6. data/lib/rails/generators/ripple/js/js_generator.rb +13 -0
  7. data/lib/rails/generators/ripple/js/templates/js/contrib.js +63 -0
  8. data/lib/rails/generators/ripple/js/templates/js/iso8601.js +76 -0
  9. data/lib/rails/generators/ripple/js/templates/js/ripple.js +132 -0
  10. data/lib/rails/generators/ripple/model/model_generator.rb +20 -0
  11. data/lib/rails/generators/ripple/model/templates/model.rb +10 -0
  12. data/lib/rails/generators/ripple/observer/observer_generator.rb +16 -0
  13. data/lib/rails/generators/ripple/observer/templates/observer.rb +4 -0
  14. data/lib/rails/generators/ripple/test/templates/test_server.rb +46 -0
  15. data/lib/rails/generators/ripple/test/test_generator.rb +39 -0
  16. data/lib/rails/generators/ripple_generator.rb +78 -0
  17. data/lib/ripple.rb +79 -0
  18. data/lib/ripple/associations.rb +356 -0
  19. data/lib/ripple/associations/embedded.rb +35 -0
  20. data/lib/ripple/associations/instantiators.rb +26 -0
  21. data/lib/ripple/associations/linked.rb +65 -0
  22. data/lib/ripple/associations/many.rb +38 -0
  23. data/lib/ripple/associations/many_embedded_proxy.rb +38 -0
  24. data/lib/ripple/associations/many_linked_proxy.rb +66 -0
  25. data/lib/ripple/associations/many_reference_proxy.rb +93 -0
  26. data/lib/ripple/associations/many_stored_key_proxy.rb +76 -0
  27. data/lib/ripple/associations/one.rb +20 -0
  28. data/lib/ripple/associations/one_embedded_proxy.rb +35 -0
  29. data/lib/ripple/associations/one_key_proxy.rb +58 -0
  30. data/lib/ripple/associations/one_linked_proxy.rb +22 -0
  31. data/lib/ripple/associations/one_stored_key_proxy.rb +43 -0
  32. data/lib/ripple/associations/proxy.rb +118 -0
  33. data/lib/ripple/attribute_methods.rb +118 -0
  34. data/lib/ripple/attribute_methods/dirty.rb +50 -0
  35. data/lib/ripple/attribute_methods/query.rb +34 -0
  36. data/lib/ripple/attribute_methods/read.rb +26 -0
  37. data/lib/ripple/attribute_methods/write.rb +25 -0
  38. data/lib/ripple/callbacks.rb +74 -0
  39. data/lib/ripple/conflict/basic_resolver.rb +82 -0
  40. data/lib/ripple/conflict/document_hooks.rb +20 -0
  41. data/lib/ripple/conflict/resolver.rb +71 -0
  42. data/lib/ripple/conflict/test_helper.rb +33 -0
  43. data/lib/ripple/conversion.rb +28 -0
  44. data/lib/ripple/core_ext.rb +2 -0
  45. data/lib/ripple/core_ext/casting.rb +148 -0
  46. data/lib/ripple/core_ext/object.rb +8 -0
  47. data/lib/ripple/document.rb +104 -0
  48. data/lib/ripple/document/bucket_access.rb +25 -0
  49. data/lib/ripple/document/finders.rb +131 -0
  50. data/lib/ripple/document/key.rb +43 -0
  51. data/lib/ripple/document/link.rb +30 -0
  52. data/lib/ripple/document/persistence.rb +115 -0
  53. data/lib/ripple/embedded_document.rb +64 -0
  54. data/lib/ripple/embedded_document/around_callbacks.rb +18 -0
  55. data/lib/ripple/embedded_document/finders.rb +26 -0
  56. data/lib/ripple/embedded_document/persistence.rb +77 -0
  57. data/lib/ripple/i18n.rb +2 -0
  58. data/lib/ripple/inspection.rb +32 -0
  59. data/lib/ripple/locale/en.yml +21 -0
  60. data/lib/ripple/nested_attributes.rb +265 -0
  61. data/lib/ripple/observable.rb +28 -0
  62. data/lib/ripple/properties.rb +73 -0
  63. data/lib/ripple/property_type_mismatch.rb +12 -0
  64. data/lib/ripple/railtie.rb +13 -0
  65. data/lib/ripple/serialization.rb +84 -0
  66. data/lib/ripple/timestamps.rb +27 -0
  67. data/lib/ripple/translation.rb +14 -0
  68. data/lib/ripple/validations.rb +67 -0
  69. data/lib/ripple/validations/associated_validator.rb +43 -0
  70. data/ripple.gemspec +46 -0
  71. data/seomoz-ripple.gemspec +46 -0
  72. data/spec/fixtures/config.yml +8 -0
  73. data/spec/integration/ripple/associations_spec.rb +220 -0
  74. data/spec/integration/ripple/conflict_resolution_spec.rb +293 -0
  75. data/spec/integration/ripple/nested_attributes_spec.rb +264 -0
  76. data/spec/integration/ripple/persistence_spec.rb +57 -0
  77. data/spec/integration/ripple/search_associations_spec.rb +42 -0
  78. data/spec/ripple/associations/many_embedded_proxy_spec.rb +122 -0
  79. data/spec/ripple/associations/many_linked_proxy_spec.rb +191 -0
  80. data/spec/ripple/associations/many_reference_proxy_spec.rb +170 -0
  81. data/spec/ripple/associations/many_stored_key_proxy_spec.rb +158 -0
  82. data/spec/ripple/associations/one_embedded_proxy_spec.rb +125 -0
  83. data/spec/ripple/associations/one_key_proxy_spec.rb +82 -0
  84. data/spec/ripple/associations/one_linked_proxy_spec.rb +91 -0
  85. data/spec/ripple/associations/one_stored_key_proxy_spec.rb +72 -0
  86. data/spec/ripple/associations/proxy_spec.rb +84 -0
  87. data/spec/ripple/associations_spec.rb +129 -0
  88. data/spec/ripple/attribute_methods/dirty_spec.rb +80 -0
  89. data/spec/ripple/attribute_methods_spec.rb +230 -0
  90. data/spec/ripple/bucket_access_spec.rb +25 -0
  91. data/spec/ripple/callbacks_spec.rb +176 -0
  92. data/spec/ripple/conflict/resolver_spec.rb +42 -0
  93. data/spec/ripple/conversion_spec.rb +22 -0
  94. data/spec/ripple/core_ext_spec.rb +103 -0
  95. data/spec/ripple/document/link_spec.rb +67 -0
  96. data/spec/ripple/document_spec.rb +96 -0
  97. data/spec/ripple/embedded_document/finders_spec.rb +29 -0
  98. data/spec/ripple/embedded_document/persistence_spec.rb +80 -0
  99. data/spec/ripple/embedded_document_spec.rb +84 -0
  100. data/spec/ripple/finders_spec.rb +217 -0
  101. data/spec/ripple/inspection_spec.rb +51 -0
  102. data/spec/ripple/key_spec.rb +30 -0
  103. data/spec/ripple/observable_spec.rb +121 -0
  104. data/spec/ripple/persistence_spec.rb +326 -0
  105. data/spec/ripple/properties_spec.rb +262 -0
  106. data/spec/ripple/ripple_spec.rb +71 -0
  107. data/spec/ripple/serialization_spec.rb +51 -0
  108. data/spec/ripple/timestamps_spec.rb +76 -0
  109. data/spec/ripple/validations/associated_validator_spec.rb +77 -0
  110. data/spec/ripple/validations_spec.rb +104 -0
  111. data/spec/spec_helper.rb +26 -0
  112. data/spec/support/associations.rb +1 -0
  113. data/spec/support/associations/proxies.rb +17 -0
  114. data/spec/support/integration_setup.rb +11 -0
  115. data/spec/support/mocks.rb +4 -0
  116. data/spec/support/models.rb +4 -0
  117. data/spec/support/models/address.rb +12 -0
  118. data/spec/support/models/box.rb +13 -0
  119. data/spec/support/models/car.rb +16 -0
  120. data/spec/support/models/cardboard_box.rb +3 -0
  121. data/spec/support/models/clock.rb +12 -0
  122. data/spec/support/models/clock_observer.rb +3 -0
  123. data/spec/support/models/company.rb +23 -0
  124. data/spec/support/models/customer.rb +4 -0
  125. data/spec/support/models/driver.rb +6 -0
  126. data/spec/support/models/email.rb +4 -0
  127. data/spec/support/models/engine.rb +5 -0
  128. data/spec/support/models/family.rb +16 -0
  129. data/spec/support/models/favorite.rb +4 -0
  130. data/spec/support/models/invoice.rb +7 -0
  131. data/spec/support/models/late_invoice.rb +3 -0
  132. data/spec/support/models/ninja.rb +9 -0
  133. data/spec/support/models/note.rb +5 -0
  134. data/spec/support/models/page.rb +4 -0
  135. data/spec/support/models/paid_invoice.rb +4 -0
  136. data/spec/support/models/passenger.rb +6 -0
  137. data/spec/support/models/profile.rb +10 -0
  138. data/spec/support/models/seat.rb +5 -0
  139. data/spec/support/models/subscription.rb +27 -0
  140. data/spec/support/models/tasks.rb +14 -0
  141. data/spec/support/models/team.rb +11 -0
  142. data/spec/support/models/transactions.rb +17 -0
  143. data/spec/support/models/tree.rb +4 -0
  144. data/spec/support/models/user.rb +10 -0
  145. data/spec/support/models/wheel.rb +6 -0
  146. data/spec/support/models/widget.rb +22 -0
  147. data/spec/support/test_server.rb +18 -0
  148. data/spec/support/test_server.yml.example +2 -0
  149. 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
@@ -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
+
@@ -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
+ };