ripple 0.9.5 → 1.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.
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