ripple 0.9.5 → 1.0.0.beta

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 (152) hide show
  1. data/.gitignore +32 -0
  2. data/Gemfile +10 -9
  3. data/Guardfile +15 -0
  4. data/Rakefile +11 -40
  5. data/lib/rails/generators/ripple/configuration/configuration_generator.rb +0 -13
  6. data/lib/rails/generators/ripple/configuration/templates/ripple.yml +4 -4
  7. data/lib/rails/generators/ripple/js/js_generator.rb +0 -13
  8. data/lib/rails/generators/ripple/js/templates/js/contrib.js +0 -17
  9. data/lib/rails/generators/ripple/js/templates/js/ripple.js +0 -13
  10. data/lib/rails/generators/ripple/model/model_generator.rb +0 -14
  11. data/lib/rails/generators/ripple/model/templates/model.rb +1 -1
  12. data/lib/rails/generators/ripple/observer/observer_generator.rb +0 -14
  13. data/lib/rails/generators/ripple/test/test_generator.rb +7 -19
  14. data/lib/rails/generators/ripple_generator.rb +1 -14
  15. data/lib/ripple.rb +7 -14
  16. data/lib/ripple/associations.rb +129 -26
  17. data/lib/ripple/associations/embedded.rb +1 -15
  18. data/lib/ripple/associations/instantiators.rb +0 -13
  19. data/lib/ripple/associations/linked.rb +41 -19
  20. data/lib/ripple/associations/many.rb +0 -14
  21. data/lib/ripple/associations/many_embedded_proxy.rb +0 -14
  22. data/lib/ripple/associations/many_linked_proxy.rb +39 -18
  23. data/lib/ripple/associations/many_reference_proxy.rb +93 -0
  24. data/lib/ripple/associations/many_stored_key_proxy.rb +76 -0
  25. data/lib/ripple/associations/one.rb +1 -15
  26. data/lib/ripple/associations/one_embedded_proxy.rb +0 -14
  27. data/lib/ripple/associations/one_key_proxy.rb +58 -0
  28. data/lib/ripple/associations/one_linked_proxy.rb +4 -14
  29. data/lib/ripple/associations/one_stored_key_proxy.rb +43 -0
  30. data/lib/ripple/associations/proxy.rb +8 -14
  31. data/lib/ripple/attribute_methods.rb +19 -17
  32. data/lib/ripple/attribute_methods/dirty.rb +19 -15
  33. data/lib/ripple/attribute_methods/query.rb +0 -14
  34. data/lib/ripple/attribute_methods/read.rb +0 -14
  35. data/lib/ripple/attribute_methods/write.rb +0 -14
  36. data/lib/ripple/callbacks.rb +10 -16
  37. data/lib/ripple/conflict/basic_resolver.rb +82 -0
  38. data/lib/ripple/conflict/document_hooks.rb +20 -0
  39. data/lib/ripple/conflict/resolver.rb +71 -0
  40. data/lib/ripple/conflict/test_helper.rb +33 -0
  41. data/lib/ripple/conversion.rb +0 -14
  42. data/lib/ripple/core_ext.rb +1 -14
  43. data/lib/ripple/core_ext/casting.rb +19 -19
  44. data/lib/ripple/core_ext/object.rb +8 -0
  45. data/lib/ripple/document.rb +21 -16
  46. data/lib/ripple/document/bucket_access.rb +0 -14
  47. data/lib/ripple/document/finders.rb +17 -23
  48. data/lib/ripple/document/key.rb +8 -28
  49. data/lib/ripple/document/link.rb +30 -0
  50. data/lib/ripple/document/persistence.rb +12 -20
  51. data/lib/ripple/embedded_document.rb +10 -15
  52. data/lib/ripple/embedded_document/around_callbacks.rb +18 -0
  53. data/lib/ripple/embedded_document/finders.rb +7 -18
  54. data/lib/ripple/embedded_document/persistence.rb +5 -17
  55. data/lib/ripple/i18n.rb +0 -14
  56. data/lib/ripple/inspection.rb +21 -15
  57. data/lib/ripple/locale/en.yml +9 -13
  58. data/lib/ripple/nested_attributes.rb +33 -39
  59. data/lib/ripple/observable.rb +0 -13
  60. data/lib/ripple/properties.rb +1 -14
  61. data/lib/ripple/property_type_mismatch.rb +0 -14
  62. data/lib/ripple/railtie.rb +4 -14
  63. data/lib/ripple/railties/ripple.rake +86 -0
  64. data/lib/ripple/serialization.rb +11 -11
  65. data/lib/ripple/test_server.rb +36 -0
  66. data/lib/ripple/timestamps.rb +0 -13
  67. data/lib/ripple/translation.rb +4 -14
  68. data/lib/ripple/validations.rb +1 -15
  69. data/lib/ripple/validations/associated_validator.rb +26 -17
  70. data/lib/ripple/version.rb +3 -0
  71. data/ripple.gemspec +24 -35
  72. data/spec/integration/ripple/associations_spec.rb +89 -58
  73. data/spec/integration/ripple/conflict_resolution_spec.rb +298 -0
  74. data/spec/integration/ripple/nested_attributes_spec.rb +19 -19
  75. data/spec/integration/ripple/persistence_spec.rb +15 -34
  76. data/spec/integration/ripple/search_associations_spec.rb +31 -0
  77. data/spec/ripple/associations/many_embedded_proxy_spec.rb +23 -36
  78. data/spec/ripple/associations/many_linked_proxy_spec.rb +133 -45
  79. data/spec/ripple/associations/many_reference_proxy_spec.rb +170 -0
  80. data/spec/ripple/associations/many_stored_key_proxy_spec.rb +158 -0
  81. data/spec/ripple/associations/one_embedded_proxy_spec.rb +24 -37
  82. data/spec/ripple/associations/one_key_proxy_spec.rb +82 -0
  83. data/spec/ripple/associations/one_linked_proxy_spec.rb +22 -23
  84. data/spec/ripple/associations/one_stored_key_proxy_spec.rb +72 -0
  85. data/spec/ripple/associations/proxy_spec.rb +21 -15
  86. data/spec/ripple/associations_spec.rb +54 -23
  87. data/spec/ripple/attribute_methods/dirty_spec.rb +56 -5
  88. data/spec/ripple/attribute_methods_spec.rb +47 -21
  89. data/spec/ripple/bucket_access_spec.rb +4 -17
  90. data/spec/ripple/callbacks_spec.rb +52 -15
  91. data/spec/ripple/conflict/resolver_spec.rb +42 -0
  92. data/spec/ripple/conversion_spec.rb +2 -15
  93. data/spec/ripple/core_ext_spec.rb +12 -15
  94. data/spec/ripple/document/link_spec.rb +67 -0
  95. data/spec/ripple/document_spec.rb +34 -19
  96. data/spec/ripple/embedded_document/finders_spec.rb +12 -19
  97. data/spec/ripple/embedded_document/persistence_spec.rb +20 -26
  98. data/spec/ripple/embedded_document_spec.rb +44 -34
  99. data/spec/ripple/finders_spec.rb +58 -29
  100. data/spec/ripple/inspection_spec.rb +40 -37
  101. data/spec/ripple/key_spec.rb +5 -17
  102. data/spec/ripple/observable_spec.rb +3 -16
  103. data/spec/ripple/persistence_spec.rb +134 -18
  104. data/spec/ripple/properties_spec.rb +21 -15
  105. data/spec/ripple/ripple_spec.rb +1 -14
  106. data/spec/ripple/serialization_spec.rb +16 -17
  107. data/spec/ripple/timestamps_spec.rb +73 -52
  108. data/spec/ripple/validations/associated_validator_spec.rb +69 -25
  109. data/spec/ripple/validations_spec.rb +3 -16
  110. data/spec/spec_helper.rb +17 -18
  111. data/spec/support/associations.rb +1 -1
  112. data/spec/support/associations/proxies.rb +0 -13
  113. data/spec/support/integration_setup.rb +11 -0
  114. data/spec/support/mocks.rb +0 -13
  115. data/spec/support/models.rb +33 -2
  116. data/spec/support/models/address.rb +1 -16
  117. data/spec/support/models/box.rb +7 -14
  118. data/spec/support/models/car.rb +27 -1
  119. data/spec/support/models/cardboard_box.rb +0 -14
  120. data/spec/support/models/clock.rb +6 -15
  121. data/spec/support/models/clock_observer.rb +0 -14
  122. data/spec/support/models/credit_card.rb +5 -0
  123. data/spec/support/models/customer.rb +0 -14
  124. data/spec/support/models/email.rb +0 -14
  125. data/spec/support/models/family.rb +1 -13
  126. data/spec/support/models/favorite.rb +0 -14
  127. data/spec/support/models/invoice.rb +0 -14
  128. data/spec/support/models/late_invoice.rb +0 -14
  129. data/spec/support/models/nested.rb +12 -0
  130. data/spec/support/models/ninja.rb +7 -0
  131. data/spec/support/models/note.rb +0 -14
  132. data/spec/support/models/page.rb +1 -15
  133. data/spec/support/models/paid_invoice.rb +0 -14
  134. data/spec/support/models/post.rb +12 -0
  135. data/spec/support/models/profile.rb +7 -0
  136. data/spec/support/models/subscription.rb +26 -0
  137. data/spec/support/models/tasks.rb +0 -18
  138. data/spec/support/models/team.rb +11 -0
  139. data/spec/support/models/transactions.rb +17 -0
  140. data/spec/support/models/tree.rb +2 -16
  141. data/spec/support/models/user.rb +14 -16
  142. data/spec/support/models/widget.rb +8 -14
  143. data/spec/support/search.rb +14 -0
  144. data/spec/support/test_server.rb +22 -12
  145. data/spec/support/test_server.yml.example +14 -2
  146. metadata +223 -59
  147. data/lib/rails/generators/ripple/test/templates/test_server.rb +0 -46
  148. data/spec/support/models/driver.rb +0 -5
  149. data/spec/support/models/engine.rb +0 -4
  150. data/spec/support/models/passenger.rb +0 -5
  151. data/spec/support/models/seat.rb +0 -4
  152. data/spec/support/models/wheel.rb +0 -5
@@ -0,0 +1,32 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage/**/*
18
+ rdoc/**/*
19
+ pkg/**/*
20
+
21
+ ## PROJECT::SPECIFIC
22
+ doc/*
23
+ .yardoc
24
+ .bundle
25
+ spec/support/test_server.yml
26
+ Gemfile.lock
27
+ **/bin
28
+ *.rbc
29
+ .rvmrc
30
+
31
+ .ripplenode
32
+ .riaktest
data/Gemfile CHANGED
@@ -1,16 +1,18 @@
1
1
  source :rubygems
2
2
 
3
- gem 'bundler'
4
- gem 'riak-client', :path => "../riak-client"
5
- gem 'activemodel', '~>3.0.0'
6
- gem 'rspec', '~>2.4.0'
7
- gem 'tzinfo'
8
- gem 'rake'
3
+ gemspec
9
4
 
10
- platforms :mri do
11
- gem 'yajl-ruby'
5
+ if ENV['RAILS31']
6
+ gem 'activemodel', '~> 3.1.0'
7
+ else
8
+ gem 'activemodel', '~> 3.0.10'
12
9
  end
13
10
 
11
+ gem 'riak-client', :path => "../riak-client"
12
+ gem 'guard-rspec'
13
+ gem 'rb-fsevent'
14
+ gem 'growl'
15
+
14
16
  platforms :mri_18, :jruby do
15
17
  gem 'ruby-debug'
16
18
  end
@@ -20,6 +22,5 @@ platforms :mri_19 do
20
22
  end
21
23
 
22
24
  platforms :jruby do
23
- gem 'json'
24
25
  gem 'jruby-openssl'
25
26
  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 => '--profile', :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 CHANGED
@@ -1,48 +1,22 @@
1
1
  require 'rubygems'
2
- require 'rake/gempackagetask'
3
-
4
- version = File.read('../VERSION').strip
5
-
6
- gemspec = Gem::Specification.new do |gem|
7
- gem.name = "ripple"
8
- gem.summary = %Q{ripple is an object-mapper library for Riak, the distributed database by Basho.}
9
- 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.}
10
- gem.version = version
11
- gem.email = "sean@basho.com"
12
- gem.homepage = "http://seancribbs.github.com/ripple"
13
- gem.authors = ["Sean Cribbs"]
14
- gem.add_development_dependency "rspec", "~>2.4.0"
15
- gem.add_dependency "riak-client", "~>#{version}"
16
- gem.add_dependency "activesupport", "~>3.0.0"
17
- gem.add_dependency "activemodel", "~>3.0.0"
18
-
19
- files = FileList["**/*"]
20
- # Editor and O/S files
21
- files.exclude ".DS_Store", "*~", "\#*", ".\#*", "*.swp", "*.tmproj", "tmtags"
22
- # Generated artifacts
23
- files.exclude "coverage", "rdoc", "pkg", ".bundle", "*.rbc", ".rvmrc", ".watchr", ".rspec"
24
- # Project-specific
25
- files.exclude "Gemfile.lock", %r{spec/support/test_server.yml$}, "bin"
26
- # Remove directories
27
- files.exclude {|d| File.directory?(d) }
28
-
29
- gem.files = files.to_a
2
+ require 'rubygems/package_task'
3
+ require 'rspec/core'
4
+ require 'rspec/core/rake_task'
30
5
 
31
- gem.test_files = gem.files.grep(/_spec\.rb$/)
6
+ def gemspec
7
+ $ripple_gemspec ||= Gem::Specification.load("ripple.gemspec")
32
8
  end
33
9
 
34
- # Gem packaging tasks
35
- Rake::GemPackageTask.new(gemspec) do |pkg|
10
+ Gem::PackageTask.new(gemspec) do |pkg|
36
11
  pkg.need_zip = false
37
12
  pkg.need_tar = false
38
13
  end
39
14
 
40
15
  task :gem => :gemspec
41
16
 
42
- desc %{Build the gemspec file.}
17
+ desc %{Validate the gemspec file.}
43
18
  task :gemspec do
44
19
  gemspec.validate
45
- File.open("#{gemspec.name}.gemspec", 'w'){|f| f.write gemspec.to_ruby }
46
20
  end
47
21
 
48
22
  desc %{Release the gem to RubyGems.org}
@@ -50,24 +24,21 @@ task :release => :gem do
50
24
  system "gem push pkg/#{gemspec.name}-#{gemspec.version}.gem"
51
25
  end
52
26
 
53
- require 'rspec/core'
54
- require 'rspec/core/rake_task'
55
-
56
27
  desc "Run Unit Specs Only"
57
28
  RSpec::Core::RakeTask.new(:spec) do |spec|
58
- spec.pattern = "spec/ripple/**/*_spec.rb"
29
+ spec.rspec_opts = %w[--profile --tag ~integration]
59
30
  end
60
31
 
61
32
  namespace :spec do
62
33
  desc "Run Integration Specs Only"
63
34
  RSpec::Core::RakeTask.new(:integration) do |spec|
64
- spec.pattern = "spec/integration/**/*_spec.rb"
35
+ spec.rspec_opts = %w[--profile --tag integration]
65
36
  end
66
37
 
67
38
  desc "Run All Specs"
68
39
  RSpec::Core::RakeTask.new(:all) do |spec|
69
- spec.pattern = "spec/{ripple,integration}/**/*_spec.rb"
40
+ spec.rspec_opts = %w[--profile]
70
41
  end
71
42
  end
72
43
 
73
- task :default => :spec
44
+ task :default => "spec:all"
@@ -1,16 +1,3 @@
1
- # Copyright 2010 Sean Cribbs, Sonian Inc., 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
1
  require 'rails/generators/ripple_generator'
15
2
 
16
3
  module Ripple
@@ -2,7 +2,7 @@
2
2
  development:
3
3
  http_port: 8098
4
4
  pb_port: 8087
5
- host: localhost
5
+ host: 127.0.0.1
6
6
 
7
7
  # The test environment has additional keys for configuring the
8
8
  # Riak::TestServer for your test/spec suite:
@@ -14,11 +14,11 @@ development:
14
14
  test:
15
15
  http_port: 9000
16
16
  pb_port: 9002
17
- host: localhost
18
- bin_dir: /usr/local/bin # Default for Homebrew.
17
+ host: 127.0.0.1
18
+ source: /usr/local/bin # Default for Homebrew.
19
19
  js_source_dir: <%%= Rails.root + "app/mapreduce" %>
20
20
 
21
21
  production:
22
22
  http_port: 8098
23
23
  pb_port: 8087
24
- host: localhost
24
+ host: 127.0.0.1
@@ -1,16 +1,3 @@
1
- # Copyright 2010 Sean Cribbs, Sonian Inc., 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
1
  require 'rails/generators/ripple_generator'
15
2
 
16
3
  module Ripple
@@ -1,22 +1,5 @@
1
1
  // -------------------------------------------------------------------
2
2
  //
3
- //
4
- // This file is provided to you under the Apache License,
5
- // Version 2.0 (the "License"); you may not use this file
6
- // except in compliance with the License. You may obtain
7
- // 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,
12
- // software distributed under the License is distributed on an
13
- // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
- // KIND, either express or implied. See the License for the
15
- // specific language governing permissions and limitations
16
- // under the License.
17
- //
18
- // -------------------------------------------------------------------
19
- //
20
3
  // This file contains Javascript MapReduce functions copied from the
21
4
  // "Riak Function Contrib" project.
22
5
  //
@@ -1,16 +1,3 @@
1
- // Copyright 2010 Sean Cribbs, Sonian Inc., 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
1
 
15
2
  /*
16
3
  * Namespace for Ripple's built-in MapReduce functions.
@@ -1,17 +1,3 @@
1
- # Copyright 2010 Sean Cribbs, Sonian Inc., 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
-
15
1
  require 'rails/generators/ripple_generator'
16
2
 
17
3
  module Ripple
@@ -1,7 +1,7 @@
1
1
  class <%= class_name %><%= " < #{options[:parent].classify}" if options[:parent] %>
2
2
  <% unless options[:parent] -%>
3
3
  include Ripple::<%= "Embedded" if options[:embedded] || options[:embedded_in] %>Document
4
- <% if options[:embedded_in] -%>embedded_in :<%= options[:embedded_in].underscore %><% end -%>
4
+ <% if options[:embedded_in] -%>embedded_in :<%= options[:embedded_in].underscore %><% end -%>
5
5
  <% end -%>
6
6
 
7
7
  <% attributes.reject{|attr| attr.reference?}.each do |attribute| -%>
@@ -1,17 +1,3 @@
1
- # Copyright 2010 Sean Cribbs, Sonian Inc., 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
-
15
1
  require 'rails/generators/ripple_generator'
16
2
 
17
3
  module Ripple
@@ -1,16 +1,3 @@
1
- # Copyright 2010 Sean Cribbs, Sonian Inc., 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
1
  require 'rails/generators/ripple_generator'
15
2
 
16
3
  module Ripple
@@ -20,7 +7,6 @@ module Ripple
20
7
  # Cucumber
21
8
  def create_cucumber_file
22
9
  if File.directory?(Rails.root + "features/support")
23
- template 'test_server.rb', 'features/support/ripple.rb'
24
10
  insert_into_file 'features/support/ripple.rb', "\n\nAfter do\n Ripple::TestServer.clear\nend", :after => "Ripple::TestServer.setup"
25
11
  end
26
12
  end
@@ -28,9 +14,12 @@ module Ripple
28
14
  # RSpec
29
15
  def create_rspec_file
30
16
  if File.file?(Rails.root + 'spec/spec_helper.rb')
31
- template 'test_server.rb', 'spec/support/ripple.rb'
17
+ inject_into_file 'spec/spec_helper.rb', :before => /R[Ss]pec\.configure do \|config\|/ do
18
+ "require 'ripple/test_server'\n"
19
+ end
32
20
  inject_into_file 'spec/spec_helper.rb', :after => /R[Ss]pec\.configure do \|config\|/ do
33
- "\n config.after(:each) do\n Ripple::TestServer.clear\n end\n"
21
+ "\n config.before(:all){ Ripple::TestServer.setup }" +
22
+ "\n config.after(:each){ Ripple::TestServer.clear }\n"
34
23
  end
35
24
  end
36
25
  end
@@ -38,12 +27,11 @@ module Ripple
38
27
  # Test::Unit
39
28
  def create_test_unit_file
40
29
  if File.file?(Rails.root + 'test/test_helper.rb')
41
- template 'test_server.rb', 'test/ripple_test_helper.rb'
42
30
  inject_into_file "test/test_helper.rb", :before => "class ActiveSupport::TestCase" do
43
- "# Setup in-memory test server for Riak\nrequire File.expand_path('../ripple_test_helper.rb', __FILE__)\n\n"
31
+ "# Setup in-memory test server for Riak\nrequire 'ripple/test_server'\n\n"
44
32
  end
45
33
  inject_into_class "test/test_helper.rb", ActiveSupport::TestCase do
46
- " teardown { Ripple::TestServer.clear }\n\n"
34
+ " setup { Ripple::TestServer.setup }\n teardown { Ripple::TestServer.clear }\n\n"
47
35
  end
48
36
  end
49
37
  end
@@ -1,16 +1,3 @@
1
- # Copyright 2010 Sean Cribbs, Sonian Inc., 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
1
  require "rails/generators/named_base"
15
2
  require "rails/generators/active_model"
16
3
 
@@ -43,7 +30,7 @@ module Ripple
43
30
  # Generator for a {Ripple::Document} model
44
31
  class ActiveModel < ::Rails::Generators::ActiveModel
45
32
  def self.all(klass)
46
- "#{klass}.all"
33
+ "#{klass}.list"
47
34
  end
48
35
 
49
36
  def self.find(klass, params=nil)
@@ -1,17 +1,3 @@
1
- # Copyright 2010 Sean Cribbs, Sonian Inc., 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
-
15
1
  require 'riak'
16
2
  require 'erb'
17
3
  require 'yaml'
@@ -68,6 +54,7 @@ module Ripple
68
54
  config_file = File.expand_path(config_file)
69
55
  config_hash = YAML.load(ERB.new(File.read(config_file)).result).with_indifferent_access
70
56
  config_keys.each {|k| config_hash = config_hash[k]}
57
+ configure_ports(config_hash)
71
58
  self.config = config_hash || {}
72
59
  rescue Errno::ENOENT
73
60
  raise Ripple::MissingConfiguration.new(config_file)
@@ -78,6 +65,12 @@ module Ripple
78
65
  def client_config
79
66
  config.slice(*Riak::Client::VALID_OPTIONS)
80
67
  end
68
+
69
+ def configure_ports(config)
70
+ return unless config && config[:min_port]
71
+ config[:http_port] ||= (config[:min_port].to_i)
72
+ config[:pb_port] ||= (config[:min_port].to_i + 1)
73
+ end
81
74
  end
82
75
 
83
76
  # Exception raised when the path passed to
@@ -1,18 +1,5 @@
1
- # Copyright 2010 Sean Cribbs, Sonian Inc., 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
-
15
1
  require 'active_support/concern'
2
+ require 'active_support/dependencies'
16
3
  require 'riak/walk_spec'
17
4
  require 'ripple/translation'
18
5
  require 'ripple/associations/proxy'
@@ -26,11 +13,15 @@ require 'ripple/associations/one_embedded_proxy'
26
13
  require 'ripple/associations/many_embedded_proxy'
27
14
  require 'ripple/associations/one_linked_proxy'
28
15
  require 'ripple/associations/many_linked_proxy'
16
+ require 'ripple/associations/many_stored_key_proxy'
17
+ require 'ripple/associations/one_key_proxy'
18
+ require 'ripple/associations/one_stored_key_proxy'
19
+ require 'ripple/associations/many_reference_proxy'
29
20
 
30
21
  module Ripple
31
22
  # Adds associations via links and embedding to {Ripple::Document}
32
23
  # models. Examples:
33
- #
24
+ #
34
25
  # # Documents can contain embedded documents, and link to other standalone documents
35
26
  # # via associations using the many and one class methods.
36
27
  # class Person
@@ -40,14 +31,14 @@ module Ripple
40
31
  # many :friends, :class_name => "Person"
41
32
  # one :account
42
33
  # end
43
- #
34
+ #
44
35
  # # Account and Address are embeddable documents
45
36
  # class Account
46
37
  # include Ripple::EmbeddedDocument
47
38
  # property :paid_until, Time
48
39
  # embedded_in :person # Adds "person" method to get parent document
49
40
  # end
50
- #
41
+ #
51
42
  # class Address
52
43
  # include Ripple::EmbeddedDocument
53
44
  # property :street, String
@@ -55,7 +46,7 @@ module Ripple
55
46
  # property :state, String
56
47
  # property :zip, String
57
48
  # end
58
- #
49
+ #
59
50
  # person = Person.find("adamhunter")
60
51
  # person.friends << Person.find("seancribbs") # Links to people/seancribbs with tag "friend"
61
52
  # person.addresses << Address.new(:street => "100 Main Street") # Adds an embedded address
@@ -64,6 +55,7 @@ module Ripple
64
55
  extend ActiveSupport::Concern
65
56
 
66
57
  module ClassMethods
58
+ include Translation
67
59
  # @private
68
60
  def inherited(subclass)
69
61
  super
@@ -77,22 +69,39 @@ module Ripple
77
69
 
78
70
  # Associations of embedded documents
79
71
  def embedded_associations
80
- associations.values.select(&:embeddable?)
72
+ associations.values.select(&:embedded?)
73
+ end
74
+
75
+ # Associations of linked documents
76
+ def linked_associations
77
+ associations.values.select(&:linked?)
78
+ end
79
+
80
+ # Associations of stored_key documents
81
+ def stored_key_associations
82
+ associations.values.select(&:stored_key?)
81
83
  end
82
84
 
83
85
  # Creates a singular association
84
86
  def one(name, options={})
87
+ configure_for_key_correspondence if options[:using] === :key
85
88
  create_association(:one, name, options)
86
89
  end
87
90
 
88
91
  # Creates a plural association
89
92
  def many(name, options={})
93
+ raise ArgumentError, t('many_key_association') if options[:using] === :key
90
94
  create_association(:many, name, options)
91
95
  end
92
96
 
97
+ def configure_for_key_correspondence
98
+ include Ripple::Associations::KeyDelegator
99
+ end
100
+
93
101
  private
94
102
  def create_association(type, name, options={})
95
103
  association = associations[name] = Association.new(type, name, options)
104
+ association.setup_on(self)
96
105
 
97
106
  define_method(name) do
98
107
  get_proxy(association)
@@ -121,6 +130,13 @@ module Ripple
121
130
  proxy
122
131
  end
123
132
 
133
+ # @private
134
+ def reset_associations
135
+ self.class.associations.each do |name, assoc_object|
136
+ send(name).reset
137
+ end
138
+ end
139
+
124
140
  # Adds embedded documents to the attributes
125
141
  # @private
126
142
  def attributes_for_persistence
@@ -137,6 +153,39 @@ module Ripple
137
153
  attrs
138
154
  end
139
155
  end
156
+
157
+ def propagate_callbacks_to_embedded_associations(name, kind)
158
+ self.class.embedded_associations.each do |association|
159
+ documents = instance_variable_get(association.ivar)
160
+ # We must explicitly check #nil? (rather than just saying `if documents`)
161
+ # because documents can be an association proxy that is proxying nil.
162
+ # In this case ruby treats documents as true because it is not _really_ nil,
163
+ # but #nil? will tell us if it is proxying nil.
164
+ next if documents.nil?
165
+
166
+ Array(documents).each do |doc|
167
+ doc.send("_#{name}_callbacks").each do |callback|
168
+ next unless callback.kind == kind
169
+ doc.send(callback.filter)
170
+ end
171
+ end
172
+ end
173
+ end
174
+
175
+ # Propagates callbacks (save/create/update/destroy) to embedded associated documents.
176
+ # This is necessary so that when a parent is saved, the embedded child's before_save
177
+ # hooks are run as well.
178
+ # @private
179
+ def run_callbacks(name, *args, &block)
180
+ # validation is already propagated to embedded documents via the
181
+ # AssociatedValidator. We don't need to duplicate the propgation here.
182
+ return super if name == :validation
183
+
184
+ propagate_callbacks_to_embedded_associations(name, :before)
185
+ return_value = super
186
+ propagate_callbacks_to_embedded_associations(name, :after)
187
+ return_value
188
+ end
140
189
  end
141
190
  end
142
191
 
@@ -169,7 +218,7 @@ module Ripple
169
218
 
170
219
  # @return [Class] The class of the associated object(s)
171
220
  def klass
172
- @klass ||= options[:class] || class_name.constantize
221
+ @klass ||= discover_class
173
222
  end
174
223
 
175
224
  # @return [true,false] Is the cardinality of the association > 1
@@ -183,7 +232,7 @@ module Ripple
183
232
  end
184
233
 
185
234
  # @return [true,false] Is the associated class an EmbeddedDocument
186
- def embeddable?
235
+ def embedded?
187
236
  klass.embeddable?
188
237
  end
189
238
 
@@ -198,6 +247,11 @@ module Ripple
198
247
  using == :linked
199
248
  end
200
249
 
250
+ # @return [true,false] Does the association use stored_key
251
+ def stored_key?
252
+ using == :stored_key
253
+ end
254
+
201
255
  # @return [String] the instance variable in the owner where the association will be stored
202
256
  def ivar
203
257
  "@_#{name}"
@@ -224,13 +278,16 @@ module Ripple
224
278
  linked? ? Array(link_spec).first.tag : nil
225
279
  end
226
280
 
281
+ def bucket_name
282
+ polymorphic? ? '_' : klass.bucket_name
283
+ end
284
+
227
285
  # @return [Riak::WalkSpec] when #linked? is true, a specification for which links to follow to retrieve the associated documents
228
286
  def link_spec
229
287
  # TODO: support transitive linked associations
230
288
  if linked?
231
289
  tag = name.to_s
232
- bucket = polymorphic? ? '_' : klass.bucket_name
233
- Riak::WalkSpec.new(:tag => tag, :bucket => bucket)
290
+ Riak::WalkSpec.new(:tag => tag, :bucket => bucket_name)
234
291
  else
235
292
  nil
236
293
  end
@@ -238,7 +295,7 @@ module Ripple
238
295
 
239
296
  # @return [Symbol] which method is used for representing the association - currently only supports :embedded and :linked
240
297
  def using
241
- @using ||= options[:using] || (embeddable? ? :embedded : :linked)
298
+ @using ||= options[:using] || (embedded? ? :embedded : :linked)
242
299
  end
243
300
 
244
301
  # @raise [ArgumentError] if the value does not match the class of the association
@@ -258,10 +315,56 @@ module Ripple
258
315
  when polymorphic?
259
316
  one? || Array === value
260
317
  when many?
261
- Array === value && value.all? {|d| (embeddable? && Hash === d) || klass === d }
318
+ Array === value && value.all? {|d| (embedded? && Hash === d) || klass === d }
262
319
  when one?
263
- value.nil? || (embeddable? && Hash === value) || value.kind_of?(klass)
320
+ value.nil? || (embedded? && Hash === value) || value.kind_of?(klass)
321
+ end
322
+ end
323
+
324
+ def uses_search?
325
+ (options[:using] == :reference)
326
+ end
327
+
328
+ def setup_on(model)
329
+ @model = model
330
+ define_callbacks_on(model)
331
+ if uses_search?
332
+ klass.before_save do |o|
333
+ unless o.class.bucket.is_indexed?
334
+ o.class.bucket.enable_index!
335
+ end
336
+ end
264
337
  end
265
338
  end
339
+
340
+ def define_callbacks_on(klass)
341
+ _association = self
342
+
343
+ klass.before_save do
344
+ if _association.linked? && !@_in_save_loaded_documents_callback
345
+ @_in_save_loaded_documents_callback = true
346
+
347
+ begin
348
+ send(_association.name).loaded_documents.each do |document|
349
+ document.save if document.new? || document.changed?
350
+ end
351
+ ensure
352
+ remove_instance_variable(:@_in_save_loaded_documents_callback)
353
+ end
354
+ end
355
+ end
356
+ end
357
+
358
+ private
359
+ def discover_class
360
+ options[:class] || (@model && find_class(@model, class_name)) || class_name.constantize
361
+ end
362
+
363
+ def find_class(scope, class_name)
364
+ return nil if class_name.include?("::")
365
+ class_sym = class_name.to_sym
366
+ parent_scope = scope.parents.unshift(scope).find {|s| ActiveSupport::Dependencies.local_const_defined?(s, class_sym) }
367
+ parent_scope.const_get(class_sym) if parent_scope
368
+ end
266
369
  end
267
370
  end