better-ripple 1.0.0
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.
- data/LICENSE +17 -0
- data/README.md +182 -0
- data/RELEASE_NOTES.md +284 -0
- data/better-ripple.gemspec +55 -0
- data/lib/rails/generators/ripple/configuration/configuration_generator.rb +13 -0
- data/lib/rails/generators/ripple/configuration/templates/ripple.yml +25 -0
- data/lib/rails/generators/ripple/js/js_generator.rb +13 -0
- data/lib/rails/generators/ripple/js/templates/js/contrib.js +63 -0
- data/lib/rails/generators/ripple/js/templates/js/iso8601.js +76 -0
- data/lib/rails/generators/ripple/js/templates/js/ripple.js +132 -0
- data/lib/rails/generators/ripple/model/model_generator.rb +20 -0
- data/lib/rails/generators/ripple/model/templates/model.rb.erb +10 -0
- data/lib/rails/generators/ripple/observer/observer_generator.rb +16 -0
- data/lib/rails/generators/ripple/observer/templates/observer.rb.erb +2 -0
- data/lib/rails/generators/ripple/test/templates/cucumber.rb.erb +7 -0
- data/lib/rails/generators/ripple/test/test_generator.rb +44 -0
- data/lib/rails/generators/ripple_generator.rb +79 -0
- data/lib/ripple.rb +86 -0
- data/lib/ripple/associations.rb +380 -0
- data/lib/ripple/associations/embedded.rb +35 -0
- data/lib/ripple/associations/instantiators.rb +26 -0
- data/lib/ripple/associations/linked.rb +65 -0
- data/lib/ripple/associations/many.rb +38 -0
- data/lib/ripple/associations/many_embedded_proxy.rb +39 -0
- data/lib/ripple/associations/many_linked_proxy.rb +66 -0
- data/lib/ripple/associations/many_reference_proxy.rb +95 -0
- data/lib/ripple/associations/many_stored_key_proxy.rb +76 -0
- data/lib/ripple/associations/one.rb +20 -0
- data/lib/ripple/associations/one_embedded_proxy.rb +35 -0
- data/lib/ripple/associations/one_key_proxy.rb +58 -0
- data/lib/ripple/associations/one_linked_proxy.rb +26 -0
- data/lib/ripple/associations/one_stored_key_proxy.rb +43 -0
- data/lib/ripple/associations/proxy.rb +118 -0
- data/lib/ripple/attribute_methods.rb +132 -0
- data/lib/ripple/attribute_methods/dirty.rb +59 -0
- data/lib/ripple/attribute_methods/query.rb +34 -0
- data/lib/ripple/attribute_methods/read.rb +28 -0
- data/lib/ripple/attribute_methods/write.rb +25 -0
- data/lib/ripple/callbacks.rb +71 -0
- data/lib/ripple/conflict/basic_resolver.rb +86 -0
- data/lib/ripple/conflict/document_hooks.rb +46 -0
- data/lib/ripple/conflict/resolver.rb +79 -0
- data/lib/ripple/conflict/test_helper.rb +34 -0
- data/lib/ripple/conversion.rb +29 -0
- data/lib/ripple/core_ext.rb +3 -0
- data/lib/ripple/core_ext/casting.rb +151 -0
- data/lib/ripple/core_ext/indexes.rb +89 -0
- data/lib/ripple/core_ext/object.rb +8 -0
- data/lib/ripple/document.rb +105 -0
- data/lib/ripple/document/bucket_access.rb +25 -0
- data/lib/ripple/document/finders.rb +131 -0
- data/lib/ripple/document/key.rb +35 -0
- data/lib/ripple/document/link.rb +30 -0
- data/lib/ripple/document/persistence.rb +130 -0
- data/lib/ripple/embedded_document.rb +63 -0
- data/lib/ripple/embedded_document/around_callbacks.rb +18 -0
- data/lib/ripple/embedded_document/finders.rb +26 -0
- data/lib/ripple/embedded_document/persistence.rb +75 -0
- data/lib/ripple/i18n.rb +5 -0
- data/lib/ripple/indexes.rb +151 -0
- data/lib/ripple/inspection.rb +32 -0
- data/lib/ripple/locale/en.yml +26 -0
- data/lib/ripple/locale/fr.yml +24 -0
- data/lib/ripple/nested_attributes.rb +275 -0
- data/lib/ripple/observable.rb +28 -0
- data/lib/ripple/properties.rb +74 -0
- data/lib/ripple/property_type_mismatch.rb +12 -0
- data/lib/ripple/railtie.rb +26 -0
- data/lib/ripple/railties/ripple.rake +103 -0
- data/lib/ripple/serialization.rb +82 -0
- data/lib/ripple/test_server.rb +35 -0
- data/lib/ripple/timestamps.rb +25 -0
- data/lib/ripple/translation.rb +18 -0
- data/lib/ripple/validations.rb +65 -0
- data/lib/ripple/validations/associated_validator.rb +43 -0
- data/lib/ripple/version.rb +3 -0
- metadata +310 -0
@@ -0,0 +1,151 @@
|
|
1
|
+
require 'tzinfo'
|
2
|
+
require 'active_support/json'
|
3
|
+
require 'active_support/core_ext/object/blank'
|
4
|
+
require 'active_support/core_ext/object/to_json'
|
5
|
+
require 'active_support/core_ext/date/conversions'
|
6
|
+
require 'active_support/core_ext/date/zones'
|
7
|
+
require 'active_support/core_ext/date_time/conversions'
|
8
|
+
require 'active_support/core_ext/date_time/zones'
|
9
|
+
require 'active_support/core_ext/time/conversions'
|
10
|
+
require 'active_support/core_ext/time/zones'
|
11
|
+
require 'active_support/core_ext/string/conversions'
|
12
|
+
require 'ripple/property_type_mismatch'
|
13
|
+
require 'set'
|
14
|
+
|
15
|
+
# @private
|
16
|
+
class Object
|
17
|
+
def self.ripple_cast(value)
|
18
|
+
value
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# @private
|
23
|
+
class Symbol
|
24
|
+
def self.ripple_cast(value)
|
25
|
+
return nil if value.blank?
|
26
|
+
value.respond_to?(:to_s) && value.to_s.intern or raise Ripple::PropertyTypeMismatch.new(self, value)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# @private
|
31
|
+
class Numeric
|
32
|
+
def self.ripple_cast(value)
|
33
|
+
return nil if value.blank?
|
34
|
+
raise Ripple::PropertyTypeMismatch.new(self,value) unless value.respond_to?(:to_i) && value.respond_to?(:to_f)
|
35
|
+
float_value = value.to_f
|
36
|
+
int_value = value.to_i
|
37
|
+
float_value == int_value ? int_value : float_value
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# @private
|
42
|
+
class Integer
|
43
|
+
def self.ripple_cast(value)
|
44
|
+
return nil if value.nil? || (String === value && value.blank?)
|
45
|
+
!value.is_a?(Symbol) && value.respond_to?(:to_i) && value.to_i or raise Ripple::PropertyTypeMismatch.new(self, value)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# @private
|
50
|
+
class Float
|
51
|
+
def self.ripple_cast(value)
|
52
|
+
return nil if value.nil? || (String === value && value.blank?)
|
53
|
+
value.respond_to?(:to_f) && value.to_f or raise Ripple::PropertyTypeMismatch.new(self, value)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# @private
|
58
|
+
class String
|
59
|
+
def self.ripple_cast(value)
|
60
|
+
return nil if value.nil?
|
61
|
+
value.respond_to?(:to_s) && value.to_s or raise Ripple::PropertyTypeMismatch.new(self, value)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
BooleanCast = Module.new do
|
66
|
+
def ripple_cast(value)
|
67
|
+
case value
|
68
|
+
when NilClass
|
69
|
+
nil
|
70
|
+
when Numeric
|
71
|
+
!value.zero?
|
72
|
+
when TrueClass, FalseClass
|
73
|
+
value
|
74
|
+
when /^\s*0/
|
75
|
+
false
|
76
|
+
when /^\s*t/i
|
77
|
+
true
|
78
|
+
when /^\s*f/i
|
79
|
+
false
|
80
|
+
else
|
81
|
+
value.present?
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
unless defined?(::Boolean)
|
87
|
+
# Stand-in for true/false property types.
|
88
|
+
module ::Boolean; end
|
89
|
+
end
|
90
|
+
|
91
|
+
::Boolean.send(:extend, BooleanCast)
|
92
|
+
TrueClass.send(:extend, BooleanCast)
|
93
|
+
FalseClass.send(:extend, BooleanCast)
|
94
|
+
|
95
|
+
# @private
|
96
|
+
class Time
|
97
|
+
def as_json(options={})
|
98
|
+
self.utc.send(Ripple.date_format)
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.ripple_cast(value)
|
102
|
+
return nil if value.blank?
|
103
|
+
value.respond_to?(:to_time) && value.to_time or raise Ripple::PropertyTypeMismatch.new(self, value)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# @private
|
108
|
+
class Date
|
109
|
+
def as_json(options={})
|
110
|
+
self.to_s(Ripple.date_format)
|
111
|
+
end
|
112
|
+
|
113
|
+
def self.ripple_cast(value)
|
114
|
+
return nil if value.blank?
|
115
|
+
value.respond_to?(:to_date) && value.to_date or raise Ripple::PropertyTypeMismatch.new(self, value)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# @private
|
120
|
+
class DateTime
|
121
|
+
def as_json(options={})
|
122
|
+
self.utc.to_s(Ripple.date_format)
|
123
|
+
end
|
124
|
+
|
125
|
+
def self.ripple_cast(value)
|
126
|
+
return nil if value.blank?
|
127
|
+
value.respond_to?(:to_datetime) && value.to_datetime or raise Ripple::PropertyTypeMismatch.new(self, value)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# @private
|
132
|
+
module ActiveSupport
|
133
|
+
class TimeWithZone
|
134
|
+
def as_json(options={})
|
135
|
+
self.utc.send(Ripple.date_format)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# @private
|
141
|
+
class Set
|
142
|
+
def as_json(options = {})
|
143
|
+
map { |e| e.as_json(options) }
|
144
|
+
end
|
145
|
+
|
146
|
+
def self.ripple_cast(value)
|
147
|
+
return nil if value.nil?
|
148
|
+
value.is_a?(Enumerable) && new(value) or raise Ripple::PropertyTypeMismatch.new(self, value)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'tzinfo'
|
2
|
+
require 'active_support/core_ext/date/conversions'
|
3
|
+
require 'active_support/core_ext/date/zones'
|
4
|
+
require 'active_support/core_ext/date_time/conversions'
|
5
|
+
require 'active_support/core_ext/date_time/zones'
|
6
|
+
require 'active_support/core_ext/time/conversions'
|
7
|
+
require 'active_support/core_ext/time/zones'
|
8
|
+
require 'active_support/core_ext/string/conversions'
|
9
|
+
require 'ripple/property_type_mismatch'
|
10
|
+
require 'set'
|
11
|
+
|
12
|
+
# @private
|
13
|
+
class Object
|
14
|
+
def to_ripple_index(type)
|
15
|
+
case type
|
16
|
+
when 'bin'
|
17
|
+
to_s
|
18
|
+
when 'int'
|
19
|
+
to_i
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# @private
|
25
|
+
class Time
|
26
|
+
def to_ripple_index(type)
|
27
|
+
case type
|
28
|
+
when 'bin'
|
29
|
+
utc.send(Ripple.date_format)
|
30
|
+
when 'int'
|
31
|
+
# Use millisecond-precision
|
32
|
+
(utc.to_f * 1000).round
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# @private
|
38
|
+
class Date
|
39
|
+
def to_ripple_index(type)
|
40
|
+
case type
|
41
|
+
when 'bin'
|
42
|
+
to_s(Ripple.date_format)
|
43
|
+
when 'int'
|
44
|
+
to_time(:utc).to_ripple_index(type)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# @private
|
50
|
+
class DateTime
|
51
|
+
def to_ripple_index(type)
|
52
|
+
case type
|
53
|
+
when 'bin'
|
54
|
+
utc.to_s(Ripple.date_format)
|
55
|
+
when 'int'
|
56
|
+
(utc.to_f * 1000).round
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# @private
|
62
|
+
module ActiveSupport
|
63
|
+
class TimeWithZone
|
64
|
+
def to_ripple_index(type)
|
65
|
+
utc.to_ripple_index(type)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# @private
|
71
|
+
module Enumerable
|
72
|
+
def to_ripple_index(type)
|
73
|
+
Set.new(map {|v| v.to_ripple_index(type) })
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
if String < Enumerable
|
78
|
+
# Fix for 1.8, in which String is Enumerable
|
79
|
+
class String
|
80
|
+
def to_ripple_index(type)
|
81
|
+
case type
|
82
|
+
when 'bin'
|
83
|
+
to_s
|
84
|
+
when 'int'
|
85
|
+
to_i
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
require 'active_model/naming'
|
3
|
+
require 'ripple/conflict/document_hooks'
|
4
|
+
require 'ripple/document/bucket_access'
|
5
|
+
require 'ripple/document/key'
|
6
|
+
require 'ripple/document/persistence'
|
7
|
+
require 'ripple/document/finders'
|
8
|
+
require 'ripple/document/link'
|
9
|
+
require 'ripple/properties'
|
10
|
+
require 'ripple/attribute_methods'
|
11
|
+
require 'ripple/indexes'
|
12
|
+
require 'ripple/timestamps'
|
13
|
+
require 'ripple/validations'
|
14
|
+
require 'ripple/associations'
|
15
|
+
require 'ripple/callbacks'
|
16
|
+
require 'ripple/observable'
|
17
|
+
require 'ripple/conversion'
|
18
|
+
require 'ripple/inspection'
|
19
|
+
require 'ripple/nested_attributes'
|
20
|
+
require 'ripple/serialization'
|
21
|
+
|
22
|
+
module Ripple
|
23
|
+
# Represents a model stored in Riak, serialized in JSON object (document).
|
24
|
+
# Ripple::Document models aim to be fully ActiveModel compatible, with a keen
|
25
|
+
# eye toward features that developers expect from ActiveRecord, DataMapper and MongoMapper.
|
26
|
+
#
|
27
|
+
# Example:
|
28
|
+
#
|
29
|
+
# class Email
|
30
|
+
# include Ripple::Document
|
31
|
+
# property :from, String, :presence => true
|
32
|
+
# property :to, String, :presence => true
|
33
|
+
# property :sent, Time, :default => proc { Time.now }
|
34
|
+
# property :body, String
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# email = Email.find("37458abc752f8413e") # GET /riak/emails/37458abc752f8413e
|
38
|
+
# email.from = "someone@nowhere.net"
|
39
|
+
# email.save # PUT /riak/emails/37458abc752f8413e
|
40
|
+
#
|
41
|
+
# reply = Email.new
|
42
|
+
# reply.from = "justin@bashoooo.com"
|
43
|
+
# reply.to = "sean@geeemail.com"
|
44
|
+
# reply.body = "Riak is a good fit for scalable Ruby apps."
|
45
|
+
# reply.save # POST /riak/emails (Riak-assigned key)
|
46
|
+
#
|
47
|
+
module Document
|
48
|
+
extend ActiveSupport::Concern
|
49
|
+
|
50
|
+
included do
|
51
|
+
extend ActiveModel::Naming
|
52
|
+
extend BucketAccess
|
53
|
+
include Ripple::Document::Key
|
54
|
+
include Ripple::Document::Persistence
|
55
|
+
extend Ripple::Properties
|
56
|
+
include Ripple::Document::Finders
|
57
|
+
include Ripple::AttributeMethods
|
58
|
+
include Ripple::Timestamps
|
59
|
+
include Ripple::Indexes
|
60
|
+
include Ripple::Indexes::DocumentMethods
|
61
|
+
include Ripple::Validations
|
62
|
+
include Ripple::Associations
|
63
|
+
include Ripple::Callbacks
|
64
|
+
include Ripple::Observable
|
65
|
+
include Ripple::Conversion
|
66
|
+
include Ripple::Inspection
|
67
|
+
include Ripple::NestedAttributes
|
68
|
+
include Ripple::Serialization
|
69
|
+
include Ripple::Conflict::DocumentHooks
|
70
|
+
end
|
71
|
+
|
72
|
+
module ClassMethods
|
73
|
+
def embeddable?
|
74
|
+
false
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def _root_document
|
79
|
+
self
|
80
|
+
end
|
81
|
+
|
82
|
+
# Returns true if the +comparison_object+ is the same object, or is of the same type and has the same key.
|
83
|
+
def ==(comparison_object)
|
84
|
+
comparison_object.equal?(self) ||
|
85
|
+
(comparison_object.class < Document && (comparison_object.instance_of?(self.class) || comparison_object.class.bucket.name == self.class.bucket.name) &&
|
86
|
+
!new? && comparison_object.key == key && !comparison_object.new?)
|
87
|
+
end
|
88
|
+
|
89
|
+
def eql?(other)
|
90
|
+
return true if other.equal?(self)
|
91
|
+
|
92
|
+
(other.class.equal?(self.class)) &&
|
93
|
+
!other.new? && !new? &&
|
94
|
+
(other.key == key)
|
95
|
+
end
|
96
|
+
|
97
|
+
def hash
|
98
|
+
if new?
|
99
|
+
super # every new document should be treated as a different doc
|
100
|
+
else
|
101
|
+
[self.class, key].hash
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'ripple'
|
2
|
+
|
3
|
+
module Ripple
|
4
|
+
module Document
|
5
|
+
# Similar to ActiveRecord's tables or MongoMapper's collections, we
|
6
|
+
# provide a sane default bucket in which to store your documents.
|
7
|
+
module BucketAccess
|
8
|
+
# @return [String] The bucket name assigned to the document class. Subclasses will inherit their bucket name from their parent class unless they redefine it.
|
9
|
+
def bucket_name
|
10
|
+
superclass.respond_to?(:bucket_name) ? superclass.bucket_name : model_name.plural
|
11
|
+
end
|
12
|
+
|
13
|
+
# @return [Riak::Bucket] The bucket assigned to this class.
|
14
|
+
def bucket
|
15
|
+
Ripple.client.bucket(bucket_name)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Set the bucket name for this class and its subclasses.
|
19
|
+
# @param [String] value the new bucket name
|
20
|
+
def bucket_name=(value)
|
21
|
+
(class << self; self; end).send(:define_method, :bucket_name){ value }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require 'ripple/translation'
|
2
|
+
require 'active_support/concern'
|
3
|
+
require 'active_support/inflector'
|
4
|
+
require 'active_support/core_ext/hash/except'
|
5
|
+
require 'active_support/core_ext/hash/slice'
|
6
|
+
require 'ripple/conflict/resolver'
|
7
|
+
|
8
|
+
module Ripple
|
9
|
+
|
10
|
+
# Raised by <tt>find!</tt> when a document cannot be found with the given key.
|
11
|
+
# begin
|
12
|
+
# Example.find!('badkey')
|
13
|
+
# rescue Ripple::DocumentNotFound
|
14
|
+
# puts 'No Document here!'
|
15
|
+
# end
|
16
|
+
class DocumentNotFound < StandardError
|
17
|
+
include Translation
|
18
|
+
def initialize(keys, found)
|
19
|
+
if keys.empty?
|
20
|
+
super(t("document_not_found.no_key"))
|
21
|
+
elsif keys.size == 1
|
22
|
+
super(t("document_not_found.one_key", :key => keys.first))
|
23
|
+
else
|
24
|
+
missing = keys - found.compact.map(&:key)
|
25
|
+
super(t("document_not_found.many_keys", :keys => missing.join(', ')))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module Document
|
31
|
+
module Finders
|
32
|
+
extend ActiveSupport::Concern
|
33
|
+
|
34
|
+
module ClassMethods
|
35
|
+
# Retrieve single or multiple documents from Riak.
|
36
|
+
# @overload find(key)
|
37
|
+
# Find a single document.
|
38
|
+
# @param [String] key the key of a document to find
|
39
|
+
# @return [Document] the found document, or nil
|
40
|
+
# @overload find(key1, key2, ...)
|
41
|
+
# Find a list of documents.
|
42
|
+
# @param [String] key1 the key of a document to find
|
43
|
+
# @param [String] key2 the key of a document to find
|
44
|
+
# @return [Array<Document>] a list of found documents, including nil for missing documents
|
45
|
+
# @overload find(keylist)
|
46
|
+
# Find a list of documents.
|
47
|
+
# @param [Array<String>] keylist an array of keys to find
|
48
|
+
# @return [Array<Document>] a list of found documents, including nil for missing documents
|
49
|
+
def find(*args)
|
50
|
+
if args.first.is_a?(Array)
|
51
|
+
args.flatten.map {|key| find_one(key) }
|
52
|
+
else
|
53
|
+
args.flatten!
|
54
|
+
return nil if args.empty? || args.all?(&:blank?)
|
55
|
+
return find_one(args.first) if args.size == 1
|
56
|
+
args.map {|key| find_one(key) }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Retrieve single or multiple documents from Riak
|
61
|
+
# but raise Ripple::DocumentNotFound if a key can
|
62
|
+
# not be found in the bucket.
|
63
|
+
def find!(*args)
|
64
|
+
found = find(*args)
|
65
|
+
raise DocumentNotFound.new(args, found) if !found || Array(found).include?(nil)
|
66
|
+
found
|
67
|
+
end
|
68
|
+
|
69
|
+
# Find the first object using the first key in the
|
70
|
+
# bucket's keys using find. You should not expect to
|
71
|
+
# actually get the first object you added to the bucket.
|
72
|
+
# This is just a convenience method.
|
73
|
+
def first
|
74
|
+
find(bucket.keys.first)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Find the first object using the first key in the
|
78
|
+
# bucket's keys using find!
|
79
|
+
def first!
|
80
|
+
find!(bucket.keys.first)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Find all documents in the Document's bucket and return them.
|
84
|
+
# @overload list()
|
85
|
+
# Get all documents and return them in an array.
|
86
|
+
# @param [Hash] options options to be passed to the
|
87
|
+
# underlying {Bucket#keys} method.
|
88
|
+
# @return [Array<Document>] all found documents in the bucket
|
89
|
+
# @overload list() {|doc| ... }
|
90
|
+
# Stream all documents in the bucket through the block.
|
91
|
+
# @yield [Document] doc a found document
|
92
|
+
# @note This operation is incredibly expensive and should not
|
93
|
+
# be used in production applications.
|
94
|
+
def list
|
95
|
+
if block_given?
|
96
|
+
bucket.keys do |keys|
|
97
|
+
keys.each do |key|
|
98
|
+
obj = find_one(key)
|
99
|
+
yield obj if obj
|
100
|
+
end
|
101
|
+
end
|
102
|
+
[]
|
103
|
+
else
|
104
|
+
bucket.keys.inject([]) do |acc, k|
|
105
|
+
obj = find_one(k)
|
106
|
+
obj ? acc << obj : acc
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
private
|
112
|
+
def find_one(key)
|
113
|
+
instantiate(bucket.get(key, quorums.slice(:r)))
|
114
|
+
rescue Riak::FailedRequest => fr
|
115
|
+
raise fr unless fr.not_found?
|
116
|
+
end
|
117
|
+
|
118
|
+
def instantiate(robject)
|
119
|
+
klass = robject.data['_type'].constantize rescue self
|
120
|
+
klass.new.tap do |doc|
|
121
|
+
doc.key = robject.key
|
122
|
+
doc.__send__(:raw_attributes=, robject.data.except("_type")) if robject.data
|
123
|
+
doc.instance_variable_set(:@new, false)
|
124
|
+
doc.instance_variable_set(:@robject, robject)
|
125
|
+
doc.changed_attributes.clear
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|