ripple 0.7.0 → 0.7.1

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 (51) hide show
  1. data/lib/ripple.rb +17 -1
  2. data/lib/ripple/associations.rb +157 -0
  3. data/lib/ripple/associations/embedded.rb +42 -0
  4. data/lib/ripple/associations/instantiators.rb +39 -0
  5. data/lib/ripple/{document/associations → associations}/linked.rb +9 -11
  6. data/lib/ripple/{document/associations/one_embedded_proxy.rb → associations/many.rb} +30 -21
  7. data/lib/ripple/{document/associations/embedded.rb → associations/many_embedded_proxy.rb} +26 -23
  8. data/lib/ripple/{embedded_document/conversion.rb → associations/one.rb} +8 -13
  9. data/lib/ripple/{document/associations/instantiators.rb → associations/one_embedded_proxy.rb} +17 -19
  10. data/lib/ripple/associations/proxy.rb +123 -0
  11. data/lib/ripple/attribute_methods.rb +116 -0
  12. data/lib/ripple/{document/attribute_methods/write.rb → attribute_methods/dirty.rb} +26 -16
  13. data/lib/ripple/attribute_methods/query.rb +48 -0
  14. data/lib/ripple/{document/attribute_methods → attribute_methods}/read.rb +16 -18
  15. data/lib/ripple/attribute_methods/write.rb +38 -0
  16. data/lib/ripple/callbacks.rb +73 -0
  17. data/lib/ripple/{document/associations/one.rb → conversion.rb} +18 -13
  18. data/lib/ripple/document.rb +19 -9
  19. data/lib/ripple/embedded_document.rb +10 -10
  20. data/lib/ripple/embedded_document/persistence.rb +12 -53
  21. data/lib/ripple/properties.rb +83 -0
  22. data/lib/ripple/timestamps.rb +34 -0
  23. data/lib/ripple/{document/validations.rb → validations.rb} +31 -33
  24. data/lib/ripple/{document/validations → validations}/associated_validator.rb +9 -10
  25. data/spec/integration/ripple/associations_spec.rb +1 -2
  26. data/spec/integration/ripple/persistence_spec.rb +2 -3
  27. data/spec/ripple/associations/many_embedded_proxy_spec.rb +2 -2
  28. data/spec/ripple/associations/one_embedded_proxy_spec.rb +2 -2
  29. data/spec/ripple/associations/proxy_spec.rb +1 -1
  30. data/spec/ripple/associations_spec.rb +15 -20
  31. data/spec/ripple/attribute_methods_spec.rb +3 -6
  32. data/spec/ripple/callbacks_spec.rb +1 -1
  33. data/spec/ripple/{embedded_document/conversion_spec.rb → conversion_spec.rb} +4 -4
  34. data/spec/ripple/embedded_document/persistence_spec.rb +4 -16
  35. data/spec/ripple/properties_spec.rb +17 -18
  36. data/spec/ripple/timestamps_spec.rb +1 -1
  37. data/spec/ripple/validations_spec.rb +1 -1
  38. data/spec/spec_helper.rb +1 -1
  39. data/spec/support/associations/proxies.rb +4 -4
  40. metadata +27 -29
  41. data/lib/ripple/document/associations.rb +0 -154
  42. data/lib/ripple/document/associations/many.rb +0 -52
  43. data/lib/ripple/document/associations/many_embedded_proxy.rb +0 -49
  44. data/lib/ripple/document/associations/proxy.rb +0 -125
  45. data/lib/ripple/document/attribute_methods.rb +0 -118
  46. data/lib/ripple/document/attribute_methods/dirty.rb +0 -52
  47. data/lib/ripple/document/attribute_methods/query.rb +0 -49
  48. data/lib/ripple/document/callbacks.rb +0 -75
  49. data/lib/ripple/document/properties.rb +0 -85
  50. data/lib/ripple/document/timestamps.rb +0 -22
  51. data/spec/support/integration.rb +0 -4
@@ -14,28 +14,26 @@
14
14
  require 'ripple'
15
15
 
16
16
  module Ripple
17
- module Document
18
- module Associations
19
- module Instantiators
20
-
21
- def build(attrs={})
22
- instantiate_target(:new, attrs)
23
- end
17
+ module Associations
18
+ class OneEmbeddedProxy < Proxy
19
+ include One
20
+ include Embedded
24
21
 
25
- def create(attrs={})
26
- instantiate_target(:create, attrs)
27
- end
22
+ def replace(doc)
23
+ @_doc = doc.respond_to?(:attributes_for_persistence) ? doc.attributes_for_persistence : doc
24
+ assign_references(doc)
25
+ reset
26
+ @_doc
27
+ end
28
28
 
29
- def create!(attrs={})
30
- instantiate_target(:create!, attrs)
29
+ protected
30
+ def find_target
31
+ return nil unless @_doc
32
+ klass.instantiate(@_doc).tap do |doc|
33
+ assign_references(doc)
31
34
  end
32
-
33
- protected
34
- def instantiate_target
35
- raise NotImplementedError
36
- end
37
-
38
35
  end
36
+
39
37
  end
40
38
  end
41
- end
39
+ end
@@ -0,0 +1,123 @@
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
+ require 'ripple'
15
+
16
+ module Ripple
17
+ module Associations
18
+ class Proxy
19
+ alias :proxy_respond_to? :respond_to?
20
+ alias :proxy_extend :extend
21
+
22
+ instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?$|^send$|proxy_|^object_id$)/ }
23
+
24
+ attr_reader :owner, :reflection, :target
25
+
26
+ alias :proxy_owner :owner
27
+ alias :proxy_target :target
28
+ alias :proxy_reflection :reflection
29
+
30
+ delegate :klass, :to => :proxy_reflection
31
+ delegate :options, :to => :proxy_reflection
32
+ delegate :collection, :to => :klass
33
+
34
+ def initialize(owner, reflection)
35
+ @owner, @reflection = owner, reflection
36
+ Array(reflection.options[:extend]).each { |ext| proxy_extend(ext) }
37
+ reset
38
+ end
39
+
40
+ def inspect
41
+ load_target
42
+ target.inspect
43
+ end
44
+
45
+ def loaded?
46
+ @loaded
47
+ end
48
+
49
+ def loaded
50
+ @loaded = true
51
+ end
52
+
53
+ def nil?
54
+ load_target
55
+ target.nil?
56
+ end
57
+
58
+ def blank?
59
+ load_target
60
+ target.blank?
61
+ end
62
+
63
+ def present?
64
+ load_target
65
+ target.present?
66
+ end
67
+
68
+ def reload
69
+ reset
70
+ load_target
71
+ self unless target.nil?
72
+ end
73
+
74
+ def replace(v)
75
+ raise NotImplementedError
76
+ end
77
+
78
+ def reset
79
+ @loaded = false
80
+ @target = nil
81
+ end
82
+
83
+ def respond_to?(*args)
84
+ proxy_respond_to?(*args) || (load_target && target.respond_to?(*args))
85
+ end
86
+
87
+ def send(method, *args, &block)
88
+ if proxy_respond_to?(method)
89
+ super
90
+ else
91
+ load_target
92
+ target.send(method, *args, &block)
93
+ end
94
+ end
95
+
96
+ def ===(other)
97
+ load_target
98
+ other === target
99
+ end
100
+
101
+ protected
102
+ def method_missing(method, *args, &block)
103
+ if load_target
104
+ if block_given?
105
+ target.send(method, *args) { |*block_args| block.call(*block_args) }
106
+ else
107
+ target.send(method, *args)
108
+ end
109
+ end
110
+ end
111
+
112
+ def load_target
113
+ @target = find_target unless loaded?
114
+ loaded
115
+ @target
116
+ end
117
+
118
+ def find_target
119
+ raise NotImplementedError
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,116 @@
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
+ require 'ripple'
15
+
16
+ module Ripple
17
+ # Makes ActiveRecord-like attribute accessors based on your
18
+ # {Document}'s properties.
19
+ module AttributeMethods
20
+ extend ActiveSupport::Concern
21
+ extend ActiveSupport::Autoload
22
+ include ActiveModel::AttributeMethods
23
+
24
+ autoload :Read
25
+ autoload :Write
26
+ autoload :Query
27
+ autoload :Dirty
28
+
29
+ included do
30
+ include Read
31
+ include Write
32
+ include Query
33
+ include Dirty
34
+ end
35
+
36
+ module ClassMethods
37
+ # @private
38
+ def property(key, type, options={})
39
+ undefine_attribute_methods
40
+ super
41
+ end
42
+
43
+ # Generates all the attribute-related methods for properties defined
44
+ # on the document, including accessors, mutators and query methods.
45
+ def define_attribute_methods
46
+ super(properties.keys)
47
+ end
48
+ end
49
+
50
+ module InstanceMethods
51
+ attr_accessor :key
52
+
53
+ # A copy of the values of all attributes in the Document. The result
54
+ # is not memoized, so use sparingly. This does not include associated objects,
55
+ # nor embedded documents.
56
+ # @return [Hash] all document attributes, by key
57
+ def attributes
58
+ self.class.properties.values.inject({}) do |hash, prop|
59
+ hash[prop.key] = attribute(prop.key)
60
+ hash
61
+ end.with_indifferent_access
62
+ end
63
+
64
+ # Mass assign the document's attributes.
65
+ # @param [Hash] attrs the attributes to assign
66
+ def attributes=(attrs)
67
+ raise ArgumentError, t('attribute_hash') unless Hash === attrs
68
+ attrs.each do |k,v|
69
+ next if k.to_sym == :key
70
+ if respond_to?("#{k}=")
71
+ __send__("#{k}=",v)
72
+ else
73
+ __send__(:attribute=,k,v)
74
+ end
75
+ end
76
+ end
77
+
78
+ def key=(value)
79
+ @key = value.to_s
80
+ end
81
+
82
+ # @private
83
+ def initialize(attrs={})
84
+ super()
85
+ @attributes = attributes_from_property_defaults
86
+ self.attributes = attrs
87
+ yield self if block_given?
88
+ end
89
+
90
+ # @private
91
+ def method_missing(method, *args, &block)
92
+ self.class.define_attribute_methods
93
+ super
94
+ end
95
+
96
+ # @private
97
+ def respond_to?(*args)
98
+ self.class.define_attribute_methods
99
+ super
100
+ end
101
+
102
+ protected
103
+ # @private
104
+ def attribute_method?(attr_name)
105
+ self.class.properties.include?(attr_name)
106
+ end
107
+
108
+ def attributes_from_property_defaults
109
+ self.class.properties.values.inject({}) do |hash, prop|
110
+ hash[prop.key] = prop.default if prop.default
111
+ hash
112
+ end.with_indifferent_access
113
+ end
114
+ end
115
+ end
116
+ end
@@ -14,27 +14,37 @@
14
14
  require 'ripple'
15
15
 
16
16
  module Ripple
17
- module Document
18
- module AttributeMethods
19
- module Write
20
- extend ActiveSupport::Concern
17
+ module AttributeMethods
18
+ module Dirty
19
+ extend ActiveSupport::Concern
20
+ include ActiveModel::Dirty
21
21
 
22
- included do
23
- attribute_method_suffix "="
24
- end
25
-
26
- def []=(attr_name, value)
27
- __send__(:attribute=, attr_name, value)
22
+ # @private
23
+ def save
24
+ if result = super
25
+ changed_attributes.clear
28
26
  end
27
+ result
28
+ end
29
29
 
30
- private
31
- def attribute=(attr_name, value)
32
- if prop = self.class.properties[attr_name]
33
- value = prop.type_cast(value)
34
- end
35
- @attributes[attr_name] = value
30
+ # @private
31
+ def reload
32
+ returning super do
33
+ changed_attributes.clear
36
34
  end
37
35
  end
36
+
37
+ # @private
38
+ def initialize(attrs={})
39
+ super(attrs)
40
+ changed_attributes.clear
41
+ end
42
+
43
+ private
44
+ def attribute=(attr_name, value)
45
+ attribute_will_change!(attr_name)
46
+ super
47
+ end
38
48
  end
39
49
  end
40
50
  end
@@ -0,0 +1,48 @@
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
+ require 'ripple'
15
+
16
+ module Ripple
17
+
18
+ module AttributeMethods
19
+ module Query
20
+ extend ActiveSupport::Concern
21
+
22
+ included do
23
+ attribute_method_suffix "?"
24
+ end
25
+
26
+ private
27
+ # Based on code from ActiveRecord
28
+ def attribute?(attr_name)
29
+ unless value = attribute(attr_name)
30
+ false
31
+ else
32
+ prop = self.class.properties[attr_name]
33
+ if prop.nil?
34
+ if Numeric === value || value !~ /[^0-9]/
35
+ !value.to_i.zero?
36
+ else
37
+ Boolean.ripple_cast(value) || value.present?
38
+ end
39
+ elsif prop.type <= Numeric
40
+ !value.zero?
41
+ else
42
+ value.present?
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -14,26 +14,24 @@
14
14
  require 'ripple'
15
15
 
16
16
  module Ripple
17
- module Document
18
- module AttributeMethods
19
- module Read
20
- extend ActiveSupport::Concern
17
+ module AttributeMethods
18
+ module Read
19
+ extend ActiveSupport::Concern
21
20
 
22
- included do
23
- attribute_method_suffix ""
24
- end
25
-
26
- def [](attr_name)
27
- attribute(attr_name)
28
- end
21
+ included do
22
+ attribute_method_suffix ""
23
+ end
24
+
25
+ def [](attr_name)
26
+ attribute(attr_name)
27
+ end
29
28
 
30
- private
31
- def attribute(attr_name)
32
- if @attributes.include?(attr_name)
33
- @attributes[attr_name]
34
- else
35
- nil
36
- end
29
+ private
30
+ def attribute(attr_name)
31
+ if @attributes.include?(attr_name)
32
+ @attributes[attr_name]
33
+ else
34
+ nil
37
35
  end
38
36
  end
39
37
  end
@@ -0,0 +1,38 @@
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
+ require 'ripple'
15
+
16
+ module Ripple
17
+ module AttributeMethods
18
+ module Write
19
+ extend ActiveSupport::Concern
20
+
21
+ included do
22
+ attribute_method_suffix "="
23
+ end
24
+
25
+ def []=(attr_name, value)
26
+ __send__(:attribute=, attr_name, value)
27
+ end
28
+
29
+ private
30
+ def attribute=(attr_name, value)
31
+ if prop = self.class.properties[attr_name]
32
+ value = prop.type_cast(value)
33
+ end
34
+ @attributes[attr_name] = value
35
+ end
36
+ end
37
+ end
38
+ end