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
data/lib/ripple.rb CHANGED
@@ -23,9 +23,25 @@ module Ripple
23
23
  extend ActiveSupport::Autoload
24
24
  include ActiveSupport::Configurable
25
25
 
26
+ # Primary models
26
27
  autoload :EmbeddedDocument
27
28
  autoload :Document
29
+
30
+ # Model mixins and support classes
31
+ autoload :Association, "ripple/associations"
32
+ autoload :Associations
33
+ autoload :AttributeMethods
34
+ autoload :Callbacks
35
+ autoload :Conversion
36
+ autoload :Properties
37
+ autoload :Property, "ripple/properties"
38
+ autoload :Timestamps
39
+ autoload :Validations
40
+
41
+ # Exceptions
28
42
  autoload :PropertyTypeMismatch
43
+
44
+ # Utilities
29
45
  autoload :Translation
30
46
 
31
47
  DEFAULT_CONFIG = {}
@@ -46,7 +62,7 @@ module Ripple
46
62
  self.client = nil
47
63
  super
48
64
  end
49
-
65
+
50
66
  def load_config(config_file)
51
67
  self.config = YAML.load_file(File.expand_path config_file).with_indifferent_access[:ripple]
52
68
  end
@@ -0,0 +1,157 @@
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
+ extend ActiveSupport::Concern
19
+ extend ActiveSupport::Autoload
20
+
21
+ autoload :Proxy
22
+ autoload :One
23
+ autoload :Many
24
+ autoload :Embedded
25
+ autoload :Instantiators
26
+ autoload :OneEmbeddedProxy
27
+ autoload :ManyEmbeddedProxy
28
+
29
+ module ClassMethods
30
+ # @private
31
+ def inherited(subclass)
32
+ super
33
+ subclass.associations.merge!(associations)
34
+ end
35
+
36
+ # Associations defined on the document
37
+ def associations
38
+ @associations ||= {}.with_indifferent_access
39
+ end
40
+
41
+ # Associations of embedded documents
42
+ def embedded_associations
43
+ associations.values.select(&:embeddable?)
44
+ end
45
+
46
+ # Creates a singular association
47
+ def one(name, options={})
48
+ create_association(:one, name, options)
49
+ end
50
+
51
+ # Creates a plural association
52
+ def many(name, options={})
53
+ create_association(:many, name, options)
54
+ end
55
+
56
+ private
57
+ def create_association(type, name, options={})
58
+ association = associations[name] = Association.new(type, name, options)
59
+
60
+ define_method(name) do
61
+ get_proxy(association)
62
+ end
63
+
64
+ define_method("#{name}=") do |value|
65
+ get_proxy(association).replace(value)
66
+ value
67
+ end
68
+
69
+ if association.one?
70
+ define_method("#{name}?") do
71
+ get_proxy(association).present?
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ module InstanceMethods
78
+ # @private
79
+ def get_proxy(association)
80
+ unless proxy = instance_variable_get(association.ivar)
81
+ proxy = association.proxy_class.new(self, association)
82
+ instance_variable_set(association.ivar, proxy)
83
+ end
84
+ proxy
85
+ end
86
+
87
+ # Adds embedded documents to the attributes
88
+ # @private
89
+ def attributes_for_persistence
90
+ self.class.embedded_associations.inject(super) do |attrs, association|
91
+ if documents = instance_variable_get(association.ivar)
92
+ attrs[association.name] = documents.is_a?(Array) ? documents.map(&:attributes_for_persistence) : documents.attributes_for_persistence
93
+ end
94
+ attrs
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ class Association
101
+ attr_reader :type, :name, :options
102
+
103
+ # association options :using, :class_name, :class, :extend,
104
+ # options that may be added :validate
105
+
106
+ def initialize(type, name, options={})
107
+ @type, @name, @options = type, name, options.to_options
108
+ end
109
+
110
+ def class_name
111
+ @class_name ||= case
112
+ when @options[:class_name]
113
+ @options[:class_name]
114
+ when @options[:class]
115
+ @options[:class].to_s
116
+ when many?
117
+ @name.to_s.classify
118
+ else
119
+ @name.to_s.camelize
120
+ end
121
+ end
122
+
123
+ def klass
124
+ @klass ||= options[:class] || class_name.constantize
125
+ end
126
+
127
+ def many?
128
+ @type == :many
129
+ end
130
+
131
+ def one?
132
+ @type == :one
133
+ end
134
+
135
+ def embeddable?
136
+ klass.embeddable?
137
+ end
138
+
139
+ def polymorphic?
140
+ false
141
+ end
142
+
143
+ def ivar
144
+ "@_#{name}"
145
+ end
146
+
147
+ def proxy_class
148
+ @proxy_class ||= proxy_class_name.constantize
149
+ end
150
+
151
+ def proxy_class_name
152
+ @using ||= options[:using] || (embeddable? ? :embedded : :link)
153
+ klass_name = (many? ? 'Many' : 'One') + @using.to_s.camelize + ('Polymorphic' if polymorphic?).to_s + 'Proxy'
154
+ "Ripple::Associations::#{klass_name}"
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,42 @@
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
+ module Embedded
19
+
20
+ def initialize(*args)
21
+ super
22
+ owner.class.validates reflection.name, :associated => true
23
+ end
24
+
25
+ protected
26
+
27
+ def assign_references(docs)
28
+ Array(docs).each do |doc|
29
+ next unless doc.respond_to?(:_parent_document=)
30
+ doc._parent_document = owner
31
+ end
32
+ end
33
+
34
+ def instantiate_target(*args)
35
+ doc = super
36
+ assign_references(doc)
37
+ doc
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,39 @@
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
+ module Instantiators
19
+
20
+ def build(attrs={})
21
+ instantiate_target(:new, attrs)
22
+ end
23
+
24
+ def create(attrs={})
25
+ instantiate_target(:create, attrs)
26
+ end
27
+
28
+ def create!(attrs={})
29
+ instantiate_target(:create!, attrs)
30
+ end
31
+
32
+ protected
33
+ def instantiate_target
34
+ raise NotImplementedError
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -14,19 +14,17 @@
14
14
  require 'ripple'
15
15
 
16
16
  module Ripple
17
- module Document
18
- module Associations
19
- module Linked
17
+ module Associations
18
+ module Linked
20
19
 
21
- def create(attrs={})
22
- instantiate_target(:create, attrs)
23
- end
20
+ def create(attrs={})
21
+ instantiate_target(:create, attrs)
22
+ end
24
23
 
25
- def create!(attrs={})
26
- instantiate_target(:create!, attrs)
27
- end
28
-
24
+ def create!(attrs={})
25
+ instantiate_target(:create!, attrs)
29
26
  end
27
+
30
28
  end
31
29
  end
32
- end
30
+ end
@@ -14,28 +14,37 @@
14
14
  require 'ripple'
15
15
 
16
16
  module Ripple
17
- module Document
18
- module Associations
19
- class OneEmbeddedProxy < Proxy
20
- include One
21
- include Embedded
22
-
23
- def replace(doc)
24
- @_doc = doc.respond_to?(:attributes_for_persistence) ? doc.attributes_for_persistence : doc
25
- assign_references(doc)
26
- reset
27
- @_doc
28
- end
29
-
17
+ module Associations
18
+ module Many
19
+ include Instantiators
20
+
21
+ def to_ary
22
+ load_target
23
+ Array === target ? target.to_ary : Array(target)
24
+ end
25
+
26
+ def count
27
+ load_target
28
+ target.size
29
+ end
30
+
31
+ def reset
32
+ super
33
+ @target = []
34
+ end
35
+
36
+ def <<
37
+ raise NotImplementedError
38
+ end
39
+ alias_method :push, :<<
40
+ alias_method :concat, :<<
41
+
30
42
  protected
31
- def find_target
32
- return nil unless @_doc
33
- klass.instantiate(@_doc).tap do |doc|
34
- assign_references(doc)
35
- end
36
- end
37
-
43
+ def instantiate_target(instantiator, attrs={})
44
+ doc = klass.send(instantiator, attrs)
45
+ self << doc
46
+ doc
38
47
  end
39
48
  end
40
49
  end
41
- end
50
+ end
@@ -14,31 +14,34 @@
14
14
  require 'ripple'
15
15
 
16
16
  module Ripple
17
- module Document
18
- module Associations
19
- module Embedded
20
-
21
- def initialize(*args)
22
- super
23
- owner.class.validates reflection.name, :associated => true
24
- end
25
-
26
- protected
27
-
28
- def assign_references(docs)
29
- Array(docs).each do |doc|
30
- next unless doc.respond_to?(:_parent_document=)
31
- doc._parent_document = owner
32
- end
33
- end
34
-
35
- def instantiate_target(*args)
36
- doc = super
17
+ module Associations
18
+ class ManyEmbeddedProxy < Proxy
19
+ include Many
20
+ include Embedded
21
+
22
+ def <<(docs)
23
+ load_target
24
+ assign_references(docs)
25
+ @target += Array(docs)
26
+ self
27
+ end
28
+
29
+ def replace(docs)
30
+ @_docs = docs.map { |doc| attrs = doc.respond_to?(:attributes_for_persistence) ? doc.attributes_for_persistence : doc }
31
+ assign_references(docs)
32
+ reset
33
+ @_docs
34
+ end
35
+
36
+ protected
37
+ def find_target
38
+ (@_docs || []).map do |attrs|
39
+ klass.instantiate(attrs).tap do |doc|
37
40
  assign_references(doc)
38
- doc
39
41
  end
40
-
42
+ end
41
43
  end
44
+
42
45
  end
43
46
  end
44
- end
47
+ end
@@ -14,20 +14,15 @@
14
14
  require 'ripple'
15
15
 
16
16
  module Ripple
17
- module EmbeddedDocument
18
- module Conversion
19
- extend ActiveSupport::Concern
17
+ module Associations
18
+ module One
19
+ include Instantiators
20
20
 
21
- module InstanceMethods
22
- include ActiveModel::Conversion
23
-
24
- def to_key
25
- new? ? nil : [key]
26
- end
27
-
28
- def to_param
29
- key
30
- end
21
+ protected
22
+ def instantiate_target(instantiator, attrs={})
23
+ @target = klass.send(instantiator, attrs)
24
+ loaded
25
+ @target
31
26
  end
32
27
  end
33
28
  end