ripple 0.7.0 → 0.7.1

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