ripple 0.5.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/.document +5 -0
- data/.gitignore +26 -0
- data/LICENSE +13 -0
- data/README.textile +126 -0
- data/RELEASE_NOTES.textile +24 -0
- data/Rakefile +61 -0
- data/VERSION +1 -0
- data/lib/riak.rb +45 -0
- data/lib/riak/bucket.rb +105 -0
- data/lib/riak/client.rb +138 -0
- data/lib/riak/client/curb_backend.rb +63 -0
- data/lib/riak/client/http_backend.rb +209 -0
- data/lib/riak/client/net_http_backend.rb +49 -0
- data/lib/riak/failed_request.rb +37 -0
- data/lib/riak/i18n.rb +15 -0
- data/lib/riak/invalid_response.rb +25 -0
- data/lib/riak/link.rb +54 -0
- data/lib/riak/locale/en.yml +37 -0
- data/lib/riak/map_reduce.rb +240 -0
- data/lib/riak/map_reduce_error.rb +20 -0
- data/lib/riak/robject.rb +234 -0
- data/lib/riak/util/headers.rb +44 -0
- data/lib/riak/util/multipart.rb +52 -0
- data/lib/riak/util/translation.rb +29 -0
- data/lib/riak/walk_spec.rb +113 -0
- data/lib/ripple.rb +48 -0
- data/lib/ripple/core_ext/casting.rb +96 -0
- data/lib/ripple/document.rb +60 -0
- data/lib/ripple/document/attribute_methods.rb +111 -0
- data/lib/ripple/document/attribute_methods/dirty.rb +52 -0
- data/lib/ripple/document/attribute_methods/query.rb +49 -0
- data/lib/ripple/document/attribute_methods/read.rb +38 -0
- data/lib/ripple/document/attribute_methods/write.rb +36 -0
- data/lib/ripple/document/bucket_access.rb +38 -0
- data/lib/ripple/document/finders.rb +84 -0
- data/lib/ripple/document/persistence.rb +93 -0
- data/lib/ripple/document/persistence/callbacks.rb +48 -0
- data/lib/ripple/document/properties.rb +85 -0
- data/lib/ripple/document/validations.rb +44 -0
- data/lib/ripple/embedded_document.rb +38 -0
- data/lib/ripple/embedded_document/persistence.rb +46 -0
- data/lib/ripple/i18n.rb +15 -0
- data/lib/ripple/locale/en.yml +16 -0
- data/lib/ripple/property_type_mismatch.rb +23 -0
- data/lib/ripple/translation.rb +24 -0
- data/ripple.gemspec +159 -0
- data/spec/fixtures/cat.jpg +0 -0
- data/spec/fixtures/multipart-blank.txt +7 -0
- data/spec/fixtures/multipart-with-body.txt +16 -0
- data/spec/riak/bucket_spec.rb +141 -0
- data/spec/riak/client_spec.rb +169 -0
- data/spec/riak/curb_backend_spec.rb +50 -0
- data/spec/riak/headers_spec.rb +34 -0
- data/spec/riak/http_backend_spec.rb +136 -0
- data/spec/riak/link_spec.rb +50 -0
- data/spec/riak/map_reduce_spec.rb +347 -0
- data/spec/riak/multipart_spec.rb +36 -0
- data/spec/riak/net_http_backend_spec.rb +28 -0
- data/spec/riak/object_spec.rb +444 -0
- data/spec/riak/walk_spec_spec.rb +208 -0
- data/spec/ripple/attribute_methods_spec.rb +149 -0
- data/spec/ripple/bucket_access_spec.rb +48 -0
- data/spec/ripple/callbacks_spec.rb +86 -0
- data/spec/ripple/document_spec.rb +35 -0
- data/spec/ripple/embedded_document_spec.rb +52 -0
- data/spec/ripple/finders_spec.rb +146 -0
- data/spec/ripple/persistence_spec.rb +89 -0
- data/spec/ripple/properties_spec.rb +195 -0
- data/spec/ripple/ripple_spec.rb +43 -0
- data/spec/ripple/validations_spec.rb +64 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/support/http_backend_implementation_examples.rb +215 -0
- data/spec/support/mock_server.rb +58 -0
- metadata +221 -0
@@ -0,0 +1,44 @@
|
|
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 'riak'
|
15
|
+
|
16
|
+
module Riak
|
17
|
+
module Util
|
18
|
+
# Represents headers from an HTTP response
|
19
|
+
class Headers
|
20
|
+
include Net::HTTPHeader
|
21
|
+
|
22
|
+
def initialize
|
23
|
+
initialize_http_header({})
|
24
|
+
end
|
25
|
+
|
26
|
+
# Parse a single header line into its key and value
|
27
|
+
# @param [String] chunk a single header line
|
28
|
+
def self.parse(chunk)
|
29
|
+
line = chunk.strip
|
30
|
+
# thanks Net::HTTPResponse
|
31
|
+
return [nil,nil] if chunk =~ /\AHTTP(?:\/(\d+\.\d+))?\s+(\d\d\d)\s*(.*)\z/in
|
32
|
+
m = /\A([^:]+):\s*/.match(line)
|
33
|
+
[m[1], m.post_match] rescue [nil, nil]
|
34
|
+
end
|
35
|
+
|
36
|
+
# Parses a header line and adds it to the header collection
|
37
|
+
# @param [String] chunk a single header line
|
38
|
+
def parse(chunk)
|
39
|
+
key, value = self.class.parse(chunk)
|
40
|
+
add_field(key, value) if key && value
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,52 @@
|
|
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 'riak'
|
15
|
+
|
16
|
+
module Riak
|
17
|
+
module Util
|
18
|
+
# Utility methods for handling multipart/mixed responses
|
19
|
+
module Multipart
|
20
|
+
extend self
|
21
|
+
# Parses a multipart/mixed body into its constituent parts, including nested multipart/mixed sections
|
22
|
+
# @param [String] data the multipart body data
|
23
|
+
# @param [String] boundary the boundary string given in the Content-Type header
|
24
|
+
def parse(data, boundary)
|
25
|
+
contents = data.match(/\n--#{Regexp.escape(boundary)}--\n/).pre_match rescue ""
|
26
|
+
contents.split(/\n--#{Regexp.escape(boundary)}\n/).reject(&:blank?).map do |part|
|
27
|
+
headers = Headers.new
|
28
|
+
if md = part.match(/\r?\n\r?\n/)
|
29
|
+
body = md.post_match
|
30
|
+
md.pre_match.split(/\r?\n/).each do |line|
|
31
|
+
headers.parse(line)
|
32
|
+
end
|
33
|
+
|
34
|
+
if headers["content-type"] =~ /multipart\/mixed/
|
35
|
+
boundary = extract_boundary(headers.to_hash["content-type"].first)
|
36
|
+
parse(body, boundary)
|
37
|
+
else
|
38
|
+
{:headers => headers.to_hash, :body => body}
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end.compact
|
42
|
+
end
|
43
|
+
|
44
|
+
# Extracts the boundary string from a Content-Type header that is a multipart type
|
45
|
+
# @param [String] header_string the Content-Type header
|
46
|
+
# @return [String] the boundary string separating each part
|
47
|
+
def extract_boundary(header_string)
|
48
|
+
$1 if header_string =~ /boundary=([A-Za-z0-9\'()+_,-.\/:=?]+)/
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,29 @@
|
|
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 'riak'
|
15
|
+
|
16
|
+
module Riak
|
17
|
+
module Util
|
18
|
+
module Translation
|
19
|
+
def i18n_scope
|
20
|
+
:riak
|
21
|
+
end
|
22
|
+
|
23
|
+
def t(message, options={})
|
24
|
+
I18n.t("#{i18n_scope}.#{message}", options)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
@@ -0,0 +1,113 @@
|
|
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 'riak'
|
15
|
+
|
16
|
+
module Riak
|
17
|
+
|
18
|
+
# The specification of how to follow links from one object to another in Riak,
|
19
|
+
# when using the link-walker resource.
|
20
|
+
# Example link-walking operation:
|
21
|
+
# GET /raw/artists/REM/albums,_,_/tracks,_,1
|
22
|
+
# This operation would have two WalkSpecs:
|
23
|
+
# Riak::WalkSpec.new({:bucket => 'albums'})
|
24
|
+
# Riak::WalkSpec.new({:bucket => 'tracks', :result => true})
|
25
|
+
class WalkSpec
|
26
|
+
include Util::Translation
|
27
|
+
# @return [String] The bucket followed links should be restricted to. "_" represents all buckets.
|
28
|
+
attr_accessor :bucket
|
29
|
+
|
30
|
+
# @return [String] The "riaktag" or "rel" that followed links should be restricted to. "_" represents all tags.
|
31
|
+
attr_accessor :tag
|
32
|
+
|
33
|
+
# @return [Boolean] Whether objects should be returned from this phase of link walking. Default is false.
|
34
|
+
attr_accessor :keep
|
35
|
+
|
36
|
+
# Normalize a list of walk specs into WalkSpec objects.
|
37
|
+
def self.normalize(*params)
|
38
|
+
params.flatten!
|
39
|
+
specs = []
|
40
|
+
while params.length > 0
|
41
|
+
param = params.shift
|
42
|
+
case param
|
43
|
+
when Hash
|
44
|
+
specs << new(param)
|
45
|
+
when WalkSpec
|
46
|
+
specs << param
|
47
|
+
else
|
48
|
+
if params.length >= 2
|
49
|
+
specs << new(param, params.shift, params.shift)
|
50
|
+
else
|
51
|
+
raise ArgumentError, t("too_few_arguments", :params => params.inspect)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
specs
|
56
|
+
end
|
57
|
+
|
58
|
+
# Creates a walk-spec for use in finding other objects in Riak.
|
59
|
+
# @overload initialize(hash)
|
60
|
+
# Creates a walk-spec from a hash.
|
61
|
+
# @param [Hash] hash options for the walk-spec
|
62
|
+
# @option hash [String] :bucket ("_") the bucket the links should point to (default '_' is all)
|
63
|
+
# @option hash [String] :tag ("_") the tag to filter links by (default '_' is all)
|
64
|
+
# @option hash [Boolean] :keep (false) whether to return results from following this link specification
|
65
|
+
# @overload initialize(bucket, tag, keep)
|
66
|
+
# Creates a walk-spec from a bucket-tag-result triple.
|
67
|
+
# @param [String] bucket the bucket the links should point to (default '_' is all)
|
68
|
+
# @param [String] tag the tag to filter links by (default '_' is all)
|
69
|
+
# @param [Boolean] keep whether to return results from following this link specification
|
70
|
+
# @see {Riak::RObject#walk}
|
71
|
+
def initialize(*args)
|
72
|
+
args.flatten!
|
73
|
+
case args.size
|
74
|
+
when 1
|
75
|
+
hash = args.first
|
76
|
+
raise ArgumentError, t("hash_type", :hash => hash.inspect) unless Hash === hash
|
77
|
+
assign(hash[:bucket], hash[:tag], hash[:keep])
|
78
|
+
when 3
|
79
|
+
assign(*args)
|
80
|
+
else
|
81
|
+
raise ArgumentError, t("wrong_argument_count_walk_spec")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Converts the walk-spec into the form required by the link-walker resource URL
|
86
|
+
def to_s
|
87
|
+
"#{@bucket || '_'},#{@tag || '_'},#{@keep ? '1' : '_'}"
|
88
|
+
end
|
89
|
+
|
90
|
+
def ==(other)
|
91
|
+
other.is_a?(WalkSpec) && other.bucket == bucket && other.tag == tag && other.keep == keep
|
92
|
+
end
|
93
|
+
|
94
|
+
def ===(other)
|
95
|
+
self == other || case other
|
96
|
+
when WalkSpec
|
97
|
+
other.keep == keep &&
|
98
|
+
(bucket == "_" || bucket == other.bucket) &&
|
99
|
+
(tag == "_" || tag == other.tag)
|
100
|
+
when Link
|
101
|
+
(bucket == "_" || bucket == other.url.split("/")[2]) &&
|
102
|
+
(tag == "_" || tag == other.rel)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
def assign(bucket, tag, result)
|
108
|
+
@bucket = bucket || "_"
|
109
|
+
@tag = tag || "_"
|
110
|
+
@keep = result || false
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
data/lib/ripple.rb
ADDED
@@ -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
|
+
|
15
|
+
require 'riak'
|
16
|
+
require 'active_support/all'
|
17
|
+
require 'active_model'
|
18
|
+
require 'ripple/i18n'
|
19
|
+
|
20
|
+
# Contains the classes and modules related to the ODM built on top of
|
21
|
+
# the basic Riak client.
|
22
|
+
module Ripple
|
23
|
+
extend ActiveSupport::Autoload
|
24
|
+
include ActiveSupport::Configurable
|
25
|
+
|
26
|
+
autoload :EmbeddedDocument
|
27
|
+
autoload :Document
|
28
|
+
autoload :PropertyTypeMismatch
|
29
|
+
autoload :Translation
|
30
|
+
|
31
|
+
class << self
|
32
|
+
# @return [Riak::Client] The client for the current thread.
|
33
|
+
def client
|
34
|
+
Thread.current[:ripple_client] ||= Riak::Client.new
|
35
|
+
end
|
36
|
+
|
37
|
+
# Sets the client for the current thread.
|
38
|
+
# @param [Riak::Client] value the client
|
39
|
+
def client=(value)
|
40
|
+
Thread.current[:ripple_client] = value
|
41
|
+
end
|
42
|
+
|
43
|
+
def config=(value)
|
44
|
+
self.client = nil
|
45
|
+
super
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,96 @@
|
|
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
|
+
# @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.nil?
|
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.nil?
|
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?
|
45
|
+
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?
|
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
|
+
value.respond_to?(:to_s) && value.to_s or raise Ripple::PropertyTypeMismatch.new(self, value)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Stand-in for true/false property types.
|
65
|
+
module Boolean
|
66
|
+
def self.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*t/i
|
75
|
+
true
|
76
|
+
when /^\s*f/i
|
77
|
+
false
|
78
|
+
else
|
79
|
+
value.present?
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# @private
|
85
|
+
class TrueClass
|
86
|
+
def self.ripple_cast(value)
|
87
|
+
Boolean.ripple_cast(value)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# @private
|
92
|
+
class FalseClass
|
93
|
+
def self.ripple_cast(value)
|
94
|
+
Boolean.ripple_cast(value)
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,60 @@
|
|
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
|
+
# Represents a model stored in Riak, serialized in JSON object (document).
|
18
|
+
# Ripple::Document models aim to be fully ActiveModel compatible, with a keen
|
19
|
+
# eye toward features that developers expect from ActiveRecord, DataMapper and MongoMapper.
|
20
|
+
#
|
21
|
+
# Example:
|
22
|
+
#
|
23
|
+
# class Email
|
24
|
+
# include Ripple::Document
|
25
|
+
# property :from, String, :presence => true
|
26
|
+
# property :to, String, :presence => true
|
27
|
+
# property :sent, Time, :default => proc { Time.now }
|
28
|
+
# property :body, String
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# email = Email.find("37458abc752f8413e") # GET /raw/emails/37458abc752f8413e
|
32
|
+
# email.from = "someone@nowhere.net"
|
33
|
+
# email.save # PUT /raw/emails/37458abc752f8413e
|
34
|
+
#
|
35
|
+
# reply = Email.new
|
36
|
+
# reply.from = "justin@bashoooo.com"
|
37
|
+
# reply.to = "sean@geeemail.com"
|
38
|
+
# reply.body = "Riak is a good fit for scalable Ruby apps."
|
39
|
+
# reply.save # POST /raw/emails (Riak-assigned key)
|
40
|
+
#
|
41
|
+
module Document
|
42
|
+
extend ActiveSupport::Concern
|
43
|
+
extend ActiveSupport::Autoload
|
44
|
+
|
45
|
+
autoload :AttributeMethods
|
46
|
+
autoload :BucketAccess
|
47
|
+
autoload :Finders
|
48
|
+
autoload :Persistence
|
49
|
+
autoload :Properties
|
50
|
+
autoload :Property, "ripple/document/properties"
|
51
|
+
autoload :Validations
|
52
|
+
|
53
|
+
included do
|
54
|
+
extend BucketAccess
|
55
|
+
include Persistence
|
56
|
+
include EmbeddedDocument
|
57
|
+
include Finders
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|