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,30 @@
1
+ require 'riak/link'
2
+
3
+ module Ripple
4
+ module Document
5
+ # A Link that is tied to a particular document and tag.
6
+ # The key is fetched from the document lazily when needed.
7
+ class Link < Riak::Link
8
+ attr_reader :document
9
+ private :document
10
+
11
+ def initialize(document, tag)
12
+ @document = document
13
+ super(document.class.bucket_name, nil, tag)
14
+ end
15
+
16
+ def key
17
+ document.key
18
+ end
19
+
20
+ def hash
21
+ document.hash
22
+ end
23
+ end
24
+
25
+ def to_link(tag)
26
+ Link.new(self, tag)
27
+ end
28
+ end
29
+ end
30
+
@@ -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 'active_support/concern'
16
2
 
17
3
  module Ripple
@@ -29,7 +15,7 @@ module Ripple
29
15
  # Destroys all records one at a time.
30
16
  # Place holder while :delete to bucket is being developed.
31
17
  def destroy_all
32
- all(&:destroy)
18
+ list(&:destroy)
33
19
  end
34
20
 
35
21
  attr_writer :quorums
@@ -74,8 +60,7 @@ module Ripple
74
60
  end
75
61
 
76
62
  def really_save(*args)
77
- robject.key = key if robject.key != key
78
- robject.data = attributes_for_persistence
63
+ update_robject
79
64
  robject.store(self.class.quorums.slice(:w,:dw))
80
65
  self.key = robject.key
81
66
  @new = false
@@ -86,8 +71,9 @@ module Ripple
86
71
  # @return self
87
72
  def reload
88
73
  return self if new?
89
- robject.reload(:force => true)
90
- self.__send__(:attributes=, @robject.data.except("_type"), false)
74
+ @robject = @robject.reload(:force => true)
75
+ self.__send__(:raw_attributes=, @robject.data.except("_type"))
76
+ reset_associations
91
77
  self
92
78
  end
93
79
 
@@ -113,9 +99,15 @@ module Ripple
113
99
  end
114
100
  end
115
101
 
102
+ def update_robject
103
+ robject.key = key if robject.key != key
104
+ robject.content_type = 'application/json'
105
+ robject.data = attributes_for_persistence
106
+ end
107
+
116
108
  private
117
109
  def attributes_for_persistence
118
- attributes.merge("_type" => self.class.name)
110
+ raw_attributes.merge("_type" => self.class.name)
119
111
  end
120
112
  end
121
113
  end
@@ -1,20 +1,7 @@
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'
16
2
  require 'active_support/core_ext/hash/except'
17
3
  require 'ripple/translation'
4
+ require 'ripple/embedded_document/around_callbacks'
18
5
  require 'ripple/embedded_document/finders'
19
6
  require 'ripple/embedded_document/persistence'
20
7
  require 'ripple/properties'
@@ -45,6 +32,7 @@ module Ripple
45
32
  include Ripple::Validations
46
33
  include Ripple::Associations
47
34
  include Ripple::Callbacks
35
+ include Ripple::EmbeddedDocument::AroundCallbacks
48
36
  include Ripple::Conversion
49
37
  include Finders
50
38
  include Ripple::Inspection
@@ -62,7 +50,14 @@ module Ripple
62
50
  def ==(other)
63
51
  self.class == other.class &&
64
52
  _parent_document == other._parent_document &&
65
- attributes.except('_type') == other.attributes.except('_type')
53
+ serializable_hash == other.serializable_hash
54
+ end
55
+ alias eql? ==
56
+
57
+ def hash
58
+ parent = [_parent_document.class]
59
+ parent << [_parent_document.key] if _parent_document.respond_to?(:key)
60
+ [ self.class, parent, serializable_hash ].hash
66
61
  end
67
62
  end
68
63
  end
@@ -0,0 +1,18 @@
1
+ require 'ripple/callbacks'
2
+
3
+ module Ripple
4
+ module EmbeddedDocument
5
+ module AroundCallbacks
6
+ extend ActiveSupport::Concern
7
+ extend Translation
8
+
9
+ included do
10
+ Ripple::Callbacks::CALLBACK_TYPES.each do |type|
11
+ define_singleton_method "around_#{type}" do |*args|
12
+ raise NotImplementedError.new(t("around_callbacks_not_supported", :type => type))
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -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 'active_support/concern'
16
2
  require 'active_support/inflector'
17
3
 
@@ -24,14 +10,17 @@ module Ripple
24
10
  module ClassMethods
25
11
  def instantiate(attrs)
26
12
  begin
27
- klass = attrs['_type'].present? ? attrs['_type'].constantize : self
28
- klass.new(attrs)
13
+ klass = attrs['_type'].present? ? attrs.delete('_type').constantize : self
29
14
  rescue NameError
30
- new(attrs)
15
+ klass = self
16
+ end
17
+ klass.new.tap do |object|
18
+ object.raw_attributes = attrs
19
+ object.changed_attributes.clear
31
20
  end
32
21
  end
33
22
  end
34
-
23
+
35
24
  end
36
25
  end
37
26
  end
@@ -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 'active_support/concern'
16
2
  require 'ripple/translation'
17
3
 
@@ -32,7 +18,7 @@ module Ripple
32
18
  extend ActiveSupport::Concern
33
19
 
34
20
  module ClassMethods
35
- # Creates a method that points to the parent document.
21
+ # Creates a method that points to the parent document.
36
22
  def embedded_in(parent)
37
23
  define_method(parent) { @_parent_document }
38
24
  end
@@ -68,7 +54,9 @@ module Ripple
68
54
  # Saves this embedded document by delegating to the root document.
69
55
  def save(*args)
70
56
  if _root_document
71
- _root_document.save(*args)
57
+ run_save_callbacks do
58
+ _root_document.save(*args)
59
+ end
72
60
  else
73
61
  raise NoRootDocument.new(self, :save)
74
62
  end
@@ -76,7 +64,7 @@ module Ripple
76
64
 
77
65
  # @private
78
66
  def attributes_for_persistence
79
- attributes.merge("_type" => self.class.name)
67
+ raw_attributes.merge("_type" => self.class.name)
80
68
  end
81
69
 
82
70
  # The root {Ripple::Document} to which this embedded document belongs.
@@ -1,16 +1,2 @@
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/i18n'
16
2
  I18n.load_path << File.expand_path("../locale/en.yml", __FILE__)
@@ -1,26 +1,32 @@
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 'ripple'
15
2
 
16
3
  module Ripple
17
4
  # Makes IRB and other inspect output a bit friendlier
18
5
  module Inspection
6
+
19
7
  # A human-readable version of the {Ripple::Document} or {Ripple::EmbeddedDocument}
8
+ # plus attributes
20
9
  def inspect
21
10
  attribute_list = attributes_for_persistence.except("_type").map {|k,v| "#{k}=#{v.inspect}" }.join(' ')
22
- identifier = self.class.embeddable? ? "" : ":#{key || '[new]'}"
23
- "<#{self.class.name}#{identifier} #{attribute_list}>"
11
+ inspection_string(attribute_list)
12
+ end
13
+
14
+ # A string representation of the {Ripple::Document} or {Ripple::EmbeddedDocument}
15
+ def to_s
16
+ inspection_string
24
17
  end
18
+
19
+ private
20
+
21
+ def inspection_string(extra = nil)
22
+ body = self.class.name + persistance_identifier
23
+ body += " #{extra}" if extra
24
+ "<#{body}>"
25
+ end
26
+
27
+ def persistance_identifier
28
+ self.class.embeddable? ? "" : ":#{key || '[new]'}"
29
+ end
30
+
25
31
  end
26
32
  end
@@ -1,26 +1,22 @@
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
  en:
15
2
  ripple:
3
+ around_callbacks_not_supported: "around_%{type} callbacks are not supported on embedded documents. See https://github.com/seancribbs/ripple/issues/188 for more detail."
4
+ associated_document_error_summary: "for %{doc_type} %{doc_id}: %{errors}"
16
5
  attribute_hash: "value of attributes must be a Hash"
6
+ cluster_not_created: "The cluster for the current environment is not created yet. Run `rake riak:create` first."
7
+ conflict_handler_not_implemented: "No on_conflict handler has been implemented for %{document}"
17
8
  document_invalid: "Validation failed: %{errors}"
18
9
  document_not_found:
19
10
  no_key: "Couldn't find document without a key"
20
11
  one_key: "Couldn't find document with key: %{key}"
21
12
  many_keys: "Couldn't find documents with keys: %{keys}"
22
13
  invalid_association_value: "Invalid value %{value} for association %{name} of type %{klass} on %{owner}"
14
+ many_association_validation_error: "are invalid (%{association_errors})"
15
+ many_key_association: "You cannot use a many association using :key"
23
16
  missing_configuration: "You are missing your ripple configuration file that should be at %{file}"
24
17
  no_root_document: "You cannot call %{method} on %{doc} without a root document"
18
+ one_association_validation_error: "is invalid (%{association_errors})"
25
19
  property_type_mismatch: "Cannot cast %{value} into a %{class}"
20
+ undefined_property: "Undefined property :%{prop} for class '%{class}'"
21
+ unexpected_conflicts: "Conflict cannot be resolved for %{conflicts} (for %{document})"
26
22
 
@@ -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 'active_support/concern'
16
2
  require 'active_support/core_ext/class/inheritable_attributes'
17
3
 
@@ -23,10 +9,14 @@ module Ripple
23
9
  TRUE_VALUES = [ true, "true", 1, "1", "yes", "ok", "y" ]
24
10
 
25
11
  included do
26
- class_inheritable_accessor :nested_attributes_options, :instance_writer => false
12
+ if respond_to?(:class_attribute) # ActiveSupport 3.1
13
+ class_attribute :nested_attributes_options, :instance_writer => false
14
+ else
15
+ class_inheritable_accessor :nested_attributes_options, :instance_writer => false
16
+ end
27
17
  self.nested_attributes_options = {}
28
18
  end
29
-
19
+
30
20
  # = Nested Attributes
31
21
  #
32
22
  # This is similar to the `accepts_nested_attributes` functionality
@@ -87,7 +77,7 @@ module Ripple
87
77
  # { :key => 'yyy', :reference => 'updated foo2' } ])
88
78
  # manifest.shipments.first.reference # => updated foo1
89
79
  # manifest.shipments.second.reference # => updated foo2
90
- #
80
+ #
91
81
  # NOTE: On many embedded, then entire collection of embedded documents is replaced, as there
92
82
  # is no key to specifically update.
93
83
  #
@@ -105,41 +95,45 @@ module Ripple
105
95
  # end
106
96
  #
107
97
  # The assigning of attributes replaces existing:
108
- #
98
+ #
109
99
  # manifest = Manifest.create(:signature_attributes => [ { :esig => 'a00001' }, { :esig => 'b00001' } ]
110
100
  # manifest.signatures # => [<Signature esig="a00001">, <Signature esig="b00001">]
111
101
  #
112
102
  # manifest.signature_attributes = [ { :esig => 'c00001' } ]
113
103
  # manifest.signatures # => [<Signature esig="c00001">]
114
- #
104
+ #
115
105
  module ClassMethods
116
-
106
+
117
107
  def accepts_nested_attributes_for(*attr_names)
118
108
  options = { :allow_destroy => false }
119
109
  options.update(attr_names.extract_options!)
120
-
110
+
121
111
  attr_names.each do |association_name|
122
112
  if association = self.associations[association_name]
123
113
  nested_attributes_options[association_name.to_sym] = options
124
-
125
- class_eval %{
126
- def #{association_name}_attributes=(attributes)
127
- assign_nested_attributes_for_#{association.type}_association(:#{association_name}, attributes)
128
- end
129
114
 
130
- before_save :autosave_nested_attributes_for_#{association_name}
131
- before_save :destroy_marked_for_destruction
115
+ define_method "#{association_name}_attributes=" do |attributes|
116
+ send("assign_nested_attributes_for_#{association.type}_association",
117
+ association_name, attributes
118
+ )
119
+ end
132
120
 
133
- private
121
+ before_save :"autosave_nested_attributes_for_#{association_name}"
122
+ before_save :destroy_marked_for_destruction
134
123
 
135
- def autosave_nested_attributes_for_#{association_name}
136
- save_nested_attributes_for_#{association.type}_association(:#{association_name}) if self.autosave[:#{association_name}]
124
+ define_method "autosave_nested_attributes_for_#{association_name}" do
125
+ if self.autosave[association_name]
126
+ send("save_nested_attributes_for_#{association.type}_association",
127
+ association_name
128
+ )
137
129
  end
138
- }, __FILE__, __LINE__
130
+ end
131
+ private :"autosave_nested_attributes_for_#{association_name}"
132
+
139
133
  else
140
134
  raise ArgumentError, "Association #{association_name} not found!"
141
135
  end
142
- end
136
+ end
143
137
  end
144
138
  end
145
139
 
@@ -156,7 +150,7 @@ module Ripple
156
150
  end
157
151
 
158
152
  private
159
-
153
+
160
154
  def save_nested_attributes_for_one_association(association_name)
161
155
  send(association_name).save
162
156
  end
@@ -178,14 +172,14 @@ module Ripple
178
172
 
179
173
  def assign_nested_attributes_for_one_association(association_name, attributes)
180
174
  association = self.class.associations[association_name]
181
- if association.embeddable?
175
+ if association.embedded?
182
176
  assign_nested_attributes_for_one_embedded_association(association_name, attributes)
183
177
  else
184
178
  self.autosave[association_name] = true
185
179
  assign_nested_attributes_for_one_linked_association(association_name, attributes)
186
180
  end
187
181
  end
188
-
182
+
189
183
  def assign_nested_attributes_for_one_embedded_association(association_name, attributes)
190
184
  send(association_name).build(attributes.except(*UNASSIGNABLE_KEYS))
191
185
  end
@@ -215,7 +209,7 @@ module Ripple
215
209
  end
216
210
 
217
211
  association = self.class.associations[association_name]
218
- if association.embeddable?
212
+ if association.embedded?
219
213
  assign_nested_attributes_for_many_embedded_association(association_name, attributes_collection)
220
214
  else
221
215
  self.autosave[association_name] = true
@@ -255,7 +249,7 @@ module Ripple
255
249
  record.attributes = attributes.except(*UNASSIGNABLE_KEYS)
256
250
  end
257
251
  end
258
-
252
+
259
253
  def has_destroy_flag?(hash)
260
254
  TRUE_VALUES.include?(hash.stringify_keys['_destroy'])
261
255
  end
@@ -275,5 +269,5 @@ module Ripple
275
269
  end
276
270
 
277
271
  end
278
-
272
+
279
273
  end