synamoid 1.2.1 → 1.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +52 -52
- metadata +5 -41
- data/.document +0 -5
- data/.gitignore +0 -67
- data/.rspec +0 -2
- data/.travis.yml +0 -15
- data/CHANGELOG.md +0 -48
- data/Gemfile +0 -4
- data/Rakefile +0 -64
- data/dynamoid.gemspec +0 -53
- data/lib/dynamoid.rb +0 -53
- data/lib/dynamoid/adapter.rb +0 -190
- data/lib/dynamoid/adapter_plugin/aws_sdk_v2.rb +0 -892
- data/lib/dynamoid/associations.rb +0 -106
- data/lib/dynamoid/associations/association.rb +0 -116
- data/lib/dynamoid/associations/belongs_to.rb +0 -44
- data/lib/dynamoid/associations/has_and_belongs_to_many.rb +0 -40
- data/lib/dynamoid/associations/has_many.rb +0 -39
- data/lib/dynamoid/associations/has_one.rb +0 -39
- data/lib/dynamoid/associations/many_association.rb +0 -193
- data/lib/dynamoid/associations/single_association.rb +0 -69
- data/lib/dynamoid/components.rb +0 -37
- data/lib/dynamoid/config.rb +0 -58
- data/lib/dynamoid/config/options.rb +0 -78
- data/lib/dynamoid/criteria.rb +0 -29
- data/lib/dynamoid/criteria/chain.rb +0 -214
- data/lib/dynamoid/dirty.rb +0 -47
- data/lib/dynamoid/document.rb +0 -201
- data/lib/dynamoid/errors.rb +0 -66
- data/lib/dynamoid/fields.rb +0 -164
- data/lib/dynamoid/finders.rb +0 -199
- data/lib/dynamoid/identity_map.rb +0 -92
- data/lib/dynamoid/indexes.rb +0 -273
- data/lib/dynamoid/middleware/identity_map.rb +0 -16
- data/lib/dynamoid/persistence.rb +0 -359
- data/lib/dynamoid/validations.rb +0 -63
- data/lib/dynamoid/version.rb +0 -3
@@ -1,69 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
module Dynamoid #:nodoc:
|
3
|
-
|
4
|
-
module Associations
|
5
|
-
module SingleAssociation
|
6
|
-
include Association
|
7
|
-
|
8
|
-
delegate :class, :to => :target
|
9
|
-
|
10
|
-
def setter(object)
|
11
|
-
delete
|
12
|
-
source.update_attribute(source_attribute, Set[object.hash_key])
|
13
|
-
self.send(:associate_target, object) if target_association
|
14
|
-
object
|
15
|
-
end
|
16
|
-
|
17
|
-
def delete
|
18
|
-
source.update_attribute(source_attribute, nil)
|
19
|
-
self.send(:disassociate_target, target) if target && target_association
|
20
|
-
target
|
21
|
-
end
|
22
|
-
|
23
|
-
def create!(attributes = {})
|
24
|
-
setter(target_class.create!(attributes))
|
25
|
-
end
|
26
|
-
|
27
|
-
def create(attributes = {})
|
28
|
-
setter(target_class.create(attributes))
|
29
|
-
end
|
30
|
-
|
31
|
-
|
32
|
-
# Is this object equal to the association's target?
|
33
|
-
#
|
34
|
-
# @return [Boolean] true/false
|
35
|
-
#
|
36
|
-
# @since 0.2.0
|
37
|
-
def ==(other)
|
38
|
-
target == other
|
39
|
-
end
|
40
|
-
|
41
|
-
# Delegate methods we don't find directly to the target.
|
42
|
-
#
|
43
|
-
# @since 0.2.0
|
44
|
-
def method_missing(method, *args)
|
45
|
-
if target.respond_to?(method)
|
46
|
-
target.send(method, *args)
|
47
|
-
else
|
48
|
-
super
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def nil?
|
53
|
-
target.nil?
|
54
|
-
end
|
55
|
-
|
56
|
-
private
|
57
|
-
|
58
|
-
# Find the target of the has_one association.
|
59
|
-
#
|
60
|
-
# @return [Dynamoid::Document] the found target (or nil if nothing)
|
61
|
-
#
|
62
|
-
# @since 0.2.0
|
63
|
-
def find_target
|
64
|
-
return if source_ids.empty?
|
65
|
-
target_class.find(source_ids.first)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
data/lib/dynamoid/components.rb
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
module Dynamoid
|
3
|
-
|
4
|
-
# All modules that a Document is composed of are defined in this
|
5
|
-
# module, to keep the document class from getting too cluttered.
|
6
|
-
module Components
|
7
|
-
extend ActiveSupport::Concern
|
8
|
-
|
9
|
-
included do
|
10
|
-
extend ActiveModel::Translation
|
11
|
-
extend ActiveModel::Callbacks
|
12
|
-
|
13
|
-
define_model_callbacks :create, :save, :destroy, :initialize, :update
|
14
|
-
|
15
|
-
before_create :set_created_at
|
16
|
-
before_save :set_updated_at
|
17
|
-
after_initialize :set_type
|
18
|
-
end
|
19
|
-
|
20
|
-
include ActiveModel::AttributeMethods
|
21
|
-
include ActiveModel::Conversion
|
22
|
-
include ActiveModel::MassAssignmentSecurity if defined?(ActiveModel::MassAssignmentSecurity)
|
23
|
-
include ActiveModel::Naming
|
24
|
-
include ActiveModel::Observing if defined?(ActiveModel::Observing)
|
25
|
-
include ActiveModel::Serializers::JSON
|
26
|
-
include ActiveModel::Serializers::Xml
|
27
|
-
include Dynamoid::Fields
|
28
|
-
include Dynamoid::Indexes
|
29
|
-
include Dynamoid::Persistence
|
30
|
-
include Dynamoid::Finders
|
31
|
-
include Dynamoid::Associations
|
32
|
-
include Dynamoid::Criteria
|
33
|
-
include Dynamoid::Validations
|
34
|
-
include Dynamoid::IdentityMap
|
35
|
-
include Dynamoid::Dirty
|
36
|
-
end
|
37
|
-
end
|
data/lib/dynamoid/config.rb
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require "uri"
|
3
|
-
require "dynamoid/config/options"
|
4
|
-
|
5
|
-
module Dynamoid
|
6
|
-
|
7
|
-
# Contains all the basic configuration information required for Dynamoid: both sensible defaults and required fields.
|
8
|
-
module Config
|
9
|
-
extend self
|
10
|
-
extend Options
|
11
|
-
include ActiveModel::Observing if defined?(ActiveModel::Observing)
|
12
|
-
|
13
|
-
# All the default options.
|
14
|
-
option :adapter, :default => 'aws_sdk_v2'
|
15
|
-
option :namespace, :default => defined?(Rails) ? "dynamoid_#{Rails.application.class.parent_name}_#{Rails.env}" : "dynamoid"
|
16
|
-
option :logger, :default => defined?(Rails)
|
17
|
-
option :access_key
|
18
|
-
option :secret_key
|
19
|
-
option :read_capacity, :default => 100
|
20
|
-
option :write_capacity, :default => 20
|
21
|
-
option :warn_on_scan, :default => true
|
22
|
-
option :endpoint, :default => nil
|
23
|
-
option :use_ssl, :default => true
|
24
|
-
option :port, :default => '443'
|
25
|
-
option :identity_map, :default => false
|
26
|
-
option :timestamps, :default => true
|
27
|
-
option :sync_retry_max_times, :default => 60 # a bit over 2 minutes
|
28
|
-
option :sync_retry_wait_seconds, :default => 2
|
29
|
-
option :convert_big_decimal, :default => false
|
30
|
-
|
31
|
-
# The default logger for Dynamoid: either the Rails logger or just stdout.
|
32
|
-
#
|
33
|
-
# @since 0.2.0
|
34
|
-
def default_logger
|
35
|
-
defined?(Rails) && Rails.respond_to?(:logger) ? Rails.logger : ::Logger.new($stdout)
|
36
|
-
end
|
37
|
-
|
38
|
-
# Returns the assigned logger instance.
|
39
|
-
#
|
40
|
-
# @since 0.2.0
|
41
|
-
def logger
|
42
|
-
@logger ||= default_logger
|
43
|
-
end
|
44
|
-
|
45
|
-
# If you want to, set the logger manually to any output you'd like. Or pass false or nil to disable logging entirely.
|
46
|
-
#
|
47
|
-
# @since 0.2.0
|
48
|
-
def logger=(logger)
|
49
|
-
case logger
|
50
|
-
when false, nil then @logger = nil
|
51
|
-
when true then @logger = default_logger
|
52
|
-
else
|
53
|
-
@logger = logger if logger.respond_to?(:info)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
end
|
58
|
-
end
|
@@ -1,78 +0,0 @@
|
|
1
|
-
# Shamelessly stolen from Mongoid!
|
2
|
-
module Dynamoid #:nodoc
|
3
|
-
module Config
|
4
|
-
|
5
|
-
# Encapsulates logic for setting options.
|
6
|
-
module Options
|
7
|
-
|
8
|
-
# Get the defaults or initialize a new empty hash.
|
9
|
-
#
|
10
|
-
# @example Get the defaults.
|
11
|
-
# options.defaults
|
12
|
-
#
|
13
|
-
# @return [ Hash ] The default options.
|
14
|
-
#
|
15
|
-
# @since 0.2.0
|
16
|
-
def defaults
|
17
|
-
@defaults ||= {}
|
18
|
-
end
|
19
|
-
|
20
|
-
# Define a configuration option with a default.
|
21
|
-
#
|
22
|
-
# @example Define the option.
|
23
|
-
# Options.option(:persist_in_safe_mode, :default => false)
|
24
|
-
#
|
25
|
-
# @param [ Symbol ] name The name of the configuration option.
|
26
|
-
# @param [ Hash ] options Extras for the option.
|
27
|
-
#
|
28
|
-
# @option options [ Object ] :default The default value.
|
29
|
-
#
|
30
|
-
# @since 0.2.0
|
31
|
-
def option(name, options = {})
|
32
|
-
defaults[name] = settings[name] = options[:default]
|
33
|
-
|
34
|
-
class_eval <<-RUBY
|
35
|
-
def #{name}
|
36
|
-
settings[#{name.inspect}]
|
37
|
-
end
|
38
|
-
|
39
|
-
def #{name}=(value)
|
40
|
-
settings[#{name.inspect}] = value
|
41
|
-
end
|
42
|
-
|
43
|
-
def #{name}?
|
44
|
-
#{name}
|
45
|
-
end
|
46
|
-
|
47
|
-
def reset_#{name}
|
48
|
-
settings[#{name.inspect}] = defaults[#{name.inspect}]
|
49
|
-
end
|
50
|
-
RUBY
|
51
|
-
end
|
52
|
-
|
53
|
-
# Reset the configuration options to the defaults.
|
54
|
-
#
|
55
|
-
# @example Reset the configuration options.
|
56
|
-
# config.reset
|
57
|
-
#
|
58
|
-
# @return [ Hash ] The defaults.
|
59
|
-
#
|
60
|
-
# @since 0.2.0
|
61
|
-
def reset
|
62
|
-
settings.replace(defaults)
|
63
|
-
end
|
64
|
-
|
65
|
-
# Get the settings or initialize a new empty hash.
|
66
|
-
#
|
67
|
-
# @example Get the settings.
|
68
|
-
# options.settings
|
69
|
-
#
|
70
|
-
# @return [ Hash ] The setting options.
|
71
|
-
#
|
72
|
-
# @since 0.2.0
|
73
|
-
def settings
|
74
|
-
@settings ||= {}
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
data/lib/dynamoid/criteria.rb
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require 'dynamoid/criteria/chain'
|
3
|
-
|
4
|
-
module Dynamoid
|
5
|
-
|
6
|
-
# Allows classes to be queried by where, all, first, and each and return criteria chains.
|
7
|
-
module Criteria
|
8
|
-
extend ActiveSupport::Concern
|
9
|
-
|
10
|
-
module ClassMethods
|
11
|
-
|
12
|
-
[:where, :all, :first, :each, :eval_limit, :start, :scan_index_forward].each do |meth|
|
13
|
-
# Return a criteria chain in response to a method that will begin or end a chain. For more information,
|
14
|
-
# see Dynamoid::Criteria::Chain.
|
15
|
-
#
|
16
|
-
# @since 0.2.0
|
17
|
-
define_method(meth) do |*args|
|
18
|
-
chain = Dynamoid::Criteria::Chain.new(self)
|
19
|
-
if args
|
20
|
-
chain.send(meth, *args)
|
21
|
-
else
|
22
|
-
chain.send(meth)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
end
|
@@ -1,214 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
module Dynamoid #:nodoc:
|
3
|
-
module Criteria
|
4
|
-
|
5
|
-
# The criteria chain is equivalent to an ActiveRecord relation (and realistically I should change the name from
|
6
|
-
# chain to relation). It is a chainable object that builds up a query and eventually executes it by a Query or Scan.
|
7
|
-
class Chain
|
8
|
-
attr_accessor :query, :source, :values, :consistent_read
|
9
|
-
include Enumerable
|
10
|
-
|
11
|
-
# Create a new criteria chain.
|
12
|
-
#
|
13
|
-
# @param [Class] source the class upon which the ultimate query will be performed.
|
14
|
-
def initialize(source)
|
15
|
-
@query = {}
|
16
|
-
@source = source
|
17
|
-
@consistent_read = false
|
18
|
-
@scan_index_forward = true
|
19
|
-
end
|
20
|
-
|
21
|
-
# The workhorse method of the criteria chain. Each key in the passed in hash will become another criteria that the
|
22
|
-
# ultimate query must match. A key can either be a symbol or a string, and should be an attribute name or
|
23
|
-
# an attribute name with a range operator.
|
24
|
-
#
|
25
|
-
# @example A simple criteria
|
26
|
-
# where(:name => 'Josh')
|
27
|
-
#
|
28
|
-
# @example A more complicated criteria
|
29
|
-
# where(:name => 'Josh', 'created_at.gt' => DateTime.now - 1.day)
|
30
|
-
#
|
31
|
-
# @since 0.2.0
|
32
|
-
def where(args)
|
33
|
-
args.each {|k, v| query[k.to_sym] = v}
|
34
|
-
self
|
35
|
-
end
|
36
|
-
|
37
|
-
def consistent
|
38
|
-
@consistent_read = true
|
39
|
-
self
|
40
|
-
end
|
41
|
-
|
42
|
-
# Returns all the records matching the criteria.
|
43
|
-
#
|
44
|
-
# @since 0.2.0
|
45
|
-
def all
|
46
|
-
records
|
47
|
-
end
|
48
|
-
|
49
|
-
# Destroys all the records matching the criteria.
|
50
|
-
#
|
51
|
-
def destroy_all
|
52
|
-
ids = []
|
53
|
-
|
54
|
-
if key_present?
|
55
|
-
ranges = []
|
56
|
-
Dynamoid.adapter.query(source.table_name, range_query).collect do |hash|
|
57
|
-
ids << hash[source.hash_key.to_sym]
|
58
|
-
ranges << hash[source.range_key.to_sym]
|
59
|
-
end
|
60
|
-
|
61
|
-
Dynamoid.adapter.delete(source.table_name, ids,{:range_key => ranges})
|
62
|
-
else
|
63
|
-
Dynamoid.adapter.scan(source.table_name, query, scan_opts).collect do |hash|
|
64
|
-
ids << hash[source.hash_key.to_sym]
|
65
|
-
end
|
66
|
-
|
67
|
-
Dynamoid.adapter.delete(source.table_name, ids)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def eval_limit(limit)
|
72
|
-
@eval_limit = limit
|
73
|
-
self
|
74
|
-
end
|
75
|
-
|
76
|
-
def batch(batch_size)
|
77
|
-
@batch_size = batch_size
|
78
|
-
self
|
79
|
-
end
|
80
|
-
|
81
|
-
def start(start)
|
82
|
-
@start = start
|
83
|
-
self
|
84
|
-
end
|
85
|
-
|
86
|
-
def scan_index_forward(scan_index_forward)
|
87
|
-
@scan_index_forward = scan_index_forward
|
88
|
-
self
|
89
|
-
end
|
90
|
-
|
91
|
-
# Allows you to use the results of a search as an enumerable over the results found.
|
92
|
-
#
|
93
|
-
# @since 0.2.0
|
94
|
-
def each(&block)
|
95
|
-
records.each(&block)
|
96
|
-
end
|
97
|
-
|
98
|
-
def consistent_opts
|
99
|
-
{ :consistent_read => consistent_read }
|
100
|
-
end
|
101
|
-
|
102
|
-
private
|
103
|
-
|
104
|
-
# The actual records referenced by the association.
|
105
|
-
#
|
106
|
-
# @return [Enumerator] an iterator of the found records.
|
107
|
-
#
|
108
|
-
# @since 0.2.0
|
109
|
-
def records
|
110
|
-
results = if key_present?
|
111
|
-
records_via_query
|
112
|
-
else
|
113
|
-
records_via_scan
|
114
|
-
end
|
115
|
-
@batch_size ? results : Array(results)
|
116
|
-
end
|
117
|
-
|
118
|
-
def records_via_query
|
119
|
-
Enumerator.new do |yielder|
|
120
|
-
Dynamoid.adapter.query(source.table_name, range_query).each do |hash|
|
121
|
-
yielder.yield source.from_database(hash)
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
# If the query does not match an index, we'll manually scan the associated table to find results.
|
127
|
-
#
|
128
|
-
# @return [Enumerator] an iterator of the found records.
|
129
|
-
#
|
130
|
-
# @since 0.2.0
|
131
|
-
def records_via_scan
|
132
|
-
if Dynamoid::Config.warn_on_scan
|
133
|
-
Dynamoid.logger.warn 'Queries without an index are forced to use scan and are generally much slower than indexed queries!'
|
134
|
-
Dynamoid.logger.warn "You can index this query by adding this to #{source.to_s.downcase}.rb: index [#{source.attributes.sort.collect{|attr| ":#{attr}"}.join(', ')}]"
|
135
|
-
end
|
136
|
-
|
137
|
-
if @consistent_read
|
138
|
-
raise Dynamoid::Errors::InvalidQuery, 'Consistent read is not supported by SCAN operation'
|
139
|
-
end
|
140
|
-
|
141
|
-
Enumerator.new do |yielder|
|
142
|
-
Dynamoid.adapter.scan(source.table_name, query, scan_opts).each do |hash|
|
143
|
-
yielder.yield source.from_database(hash)
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
def range_hash(key)
|
149
|
-
val = query[key]
|
150
|
-
|
151
|
-
return { :range_value => query[key] } if query[key].is_a?(Range)
|
152
|
-
|
153
|
-
case key.to_s.split('.').last
|
154
|
-
when 'gt'
|
155
|
-
{ :range_greater_than => val }
|
156
|
-
when 'lt'
|
157
|
-
{ :range_less_than => val }
|
158
|
-
when 'gte'
|
159
|
-
{ :range_gte => val }
|
160
|
-
when 'lte'
|
161
|
-
{ :range_lte => val }
|
162
|
-
when 'between'
|
163
|
-
{ :range_between => val }
|
164
|
-
when 'begins_with'
|
165
|
-
{ :range_begins_with => val }
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
def range_query
|
170
|
-
opts = { :hash_value => query[source.hash_key] }
|
171
|
-
query.keys.select { |k| k.to_s.include?('.') }.each do |key|
|
172
|
-
opts.merge!(range_hash(key))
|
173
|
-
end
|
174
|
-
opts.merge(query_opts).merge(consistent_opts)
|
175
|
-
end
|
176
|
-
|
177
|
-
def query_keys
|
178
|
-
query.keys.collect{|k| k.to_s.split('.').first}
|
179
|
-
end
|
180
|
-
|
181
|
-
# [hash_key] or [hash_key, range_key] is specified in query keys.
|
182
|
-
def key_present?
|
183
|
-
query_keys == [source.hash_key.to_s] || (query_keys.to_set == [source.hash_key.to_s, source.range_key.to_s].to_set)
|
184
|
-
end
|
185
|
-
|
186
|
-
def start_key
|
187
|
-
key = { :hash_key_element => @start.hash_key }
|
188
|
-
if range_key = @start.class.range_key
|
189
|
-
key.merge!({:range_key_element => @start.send(range_key) })
|
190
|
-
end
|
191
|
-
key
|
192
|
-
end
|
193
|
-
|
194
|
-
def query_opts
|
195
|
-
opts = {}
|
196
|
-
opts[:select] = 'ALL_ATTRIBUTES'
|
197
|
-
opts[:limit] = @eval_limit if @eval_limit
|
198
|
-
opts[:next_token] = start_key if @start
|
199
|
-
opts[:scan_index_forward] = @scan_index_forward
|
200
|
-
opts
|
201
|
-
end
|
202
|
-
|
203
|
-
def scan_opts
|
204
|
-
opts = {}
|
205
|
-
opts[:limit] = @eval_limit if @eval_limit
|
206
|
-
opts[:next_token] = start_key if @start
|
207
|
-
opts[:batch_size] = @batch_size if @batch_size
|
208
|
-
opts
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
end
|
213
|
-
|
214
|
-
end
|