synamoid 1.2.1 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,47 +0,0 @@
1
- module Dynamoid
2
- module Dirty
3
- extend ActiveSupport::Concern
4
- include ActiveModel::Dirty
5
-
6
- module ClassMethods
7
- def from_database(*)
8
- super.tap { |d| d.changed_attributes.clear }
9
- end
10
- end
11
-
12
- def save(*)
13
- clear_changes { super }
14
- end
15
-
16
- def update!(*)
17
- ret = super
18
- clear_changes #update! completely reloads all fields on the class, so any extant changes are wiped out
19
- ret
20
- end
21
-
22
- def reload
23
- super.tap { clear_changes }
24
- end
25
-
26
- def clear_changes
27
- previous = changes
28
- (block_given? ? yield : true).tap do |result|
29
- unless result == false #failed validation; nil is OK.
30
- @previously_changed = previous
31
- changed_attributes.clear
32
- end
33
- end
34
- end
35
-
36
- def write_attribute(name, value)
37
- attribute_will_change!(name) unless self.read_attribute(name) == value
38
- super
39
- end
40
-
41
- protected
42
-
43
- def attribute_method?(attr)
44
- super || self.class.attributes.has_key?(attr.to_sym)
45
- end
46
- end
47
- end
@@ -1,201 +0,0 @@
1
- # encoding: utf-8
2
- module Dynamoid #:nodoc:
3
-
4
- # This is the base module for all domain objects that need to be persisted to
5
- # the database as documents.
6
- module Document
7
- extend ActiveSupport::Concern
8
- include Dynamoid::Components
9
-
10
- included do
11
- class_attribute :options, :read_only_attributes, :base_class
12
- self.options = {}
13
- self.read_only_attributes = []
14
- self.base_class = self
15
-
16
- Dynamoid.included_models << self
17
- end
18
-
19
- module ClassMethods
20
- # Set up table options, including naming it whatever you want, setting the id key, and manually overriding read and
21
- # write capacity.
22
- #
23
- # @param [Hash] options options to pass for this table
24
- # @option options [Symbol] :name the name for the table; this still gets namespaced
25
- # @option options [Symbol] :id id column for the table
26
- # @option options [Integer] :read_capacity set the read capacity for the table; does not work on existing tables
27
- # @option options [Integer] :write_capacity set the write capacity for the table; does not work on existing tables
28
- #
29
- # @since 0.4.0
30
- def table(options = {})
31
- self.options = options
32
- super if defined? super
33
- end
34
-
35
- def attr_readonly(*read_only_attributes)
36
- self.read_only_attributes.concat read_only_attributes.map(&:to_s)
37
- end
38
-
39
- # Returns the read_capacity for this table.
40
- #
41
- # @since 0.4.0
42
- def read_capacity
43
- options[:read_capacity] || Dynamoid::Config.read_capacity
44
- end
45
-
46
- # Returns the write_capacity for this table.
47
- #
48
- # @since 0.4.0
49
- def write_capacity
50
- options[:write_capacity] || Dynamoid::Config.write_capacity
51
- end
52
-
53
- # Returns the id field for this class.
54
- #
55
- # @since 0.4.0
56
- def hash_key
57
- options[:key] || :id
58
- end
59
-
60
- # Returns the number of items for this class.
61
- #
62
- # @since 0.6.1
63
- def count
64
- Dynamoid.adapter.count(table_name)
65
- end
66
-
67
- # Initialize a new object and immediately save it to the database.
68
- #
69
- # @param [Hash] attrs Attributes with which to create the object.
70
- #
71
- # @return [Dynamoid::Document] the saved document
72
- #
73
- # @since 0.2.0
74
- def create(attrs = {})
75
- build(attrs).tap(&:save)
76
- end
77
-
78
- # Initialize a new object and immediately save it to the database. Raise an exception if persistence failed.
79
- #
80
- # @param [Hash] attrs Attributes with which to create the object.
81
- #
82
- # @return [Dynamoid::Document] the saved document
83
- #
84
- # @since 0.2.0
85
- def create!(attrs = {})
86
- build(attrs).tap(&:save!)
87
- end
88
-
89
- # Initialize a new object.
90
- #
91
- # @param [Hash] attrs Attributes with which to create the object.
92
- #
93
- # @return [Dynamoid::Document] the new document
94
- #
95
- # @since 0.2.0
96
- def build(attrs = {})
97
- attrs[:type] ? attrs[:type].constantize.new(attrs) : new(attrs)
98
- end
99
-
100
- # Does this object exist?
101
- #
102
- # @param [Mixed] id_or_conditions the id of the object or a hash with the options to filter from.
103
- #
104
- # @return [Boolean] true/false
105
- #
106
- # @since 0.2.0
107
- def exists?(id_or_conditions = {})
108
- case id_or_conditions
109
- when Hash then ! where(id_or_conditions).all.empty?
110
- else !! find(id_or_conditions)
111
- end
112
- end
113
- end
114
-
115
- # Initialize a new object.
116
- #
117
- # @param [Hash] attrs Attributes with which to create the object.
118
- #
119
- # @return [Dynamoid::Document] the new document
120
- #
121
- # @since 0.2.0
122
- def initialize(attrs = {})
123
- run_callbacks :initialize do
124
- @new_record = true
125
- @attributes ||= {}
126
- @associations ||= {}
127
-
128
- load(attrs)
129
- end
130
- end
131
-
132
- def load(attrs)
133
- self.class.undump(attrs).each do |key, value|
134
- send("#{key}=", value) if self.respond_to?("#{key}=")
135
- end
136
- end
137
-
138
- # An object is equal to another object if their ids are equal.
139
- #
140
- # @since 0.2.0
141
- def ==(other)
142
- if self.class.identity_map_on?
143
- super
144
- else
145
- return false if other.nil?
146
- other.is_a?(Dynamoid::Document) && self.hash_key == other.hash_key && self.range_value == other.range_value
147
- end
148
- end
149
-
150
- def eql?(other)
151
- self == other
152
- end
153
-
154
- def hash
155
- hash_key.hash ^ range_value.hash
156
- end
157
-
158
- # Reload an object from the database -- if you suspect the object has changed in the datastore and you need those
159
- # changes to be reflected immediately, you would call this method. This is a consistent read.
160
- #
161
- # @return [Dynamoid::Document] the document this method was called on
162
- #
163
- # @since 0.2.0
164
- def reload
165
- range_key_value = range_value ? dumped_range_value : nil
166
- self.attributes = self.class.find(hash_key, :range_key => range_key_value, :consistent_read => true).attributes
167
- @associations.values.each(&:reset)
168
- self
169
- end
170
-
171
- # Return an object's hash key, regardless of what it might be called to the object.
172
- #
173
- # @since 0.4.0
174
- def hash_key
175
- self.send(self.class.hash_key)
176
- end
177
-
178
- # Assign an object's hash key, regardless of what it might be called to the object.
179
- #
180
- # @since 0.4.0
181
- def hash_key=(value)
182
- self.send("#{self.class.hash_key}=", value)
183
- end
184
-
185
- def range_value
186
- if range_key = self.class.range_key
187
- self.send(range_key)
188
- end
189
- end
190
-
191
- def range_value=(value)
192
- self.send("#{self.class.range_key}=", value)
193
- end
194
-
195
- private
196
-
197
- def dumped_range_value
198
- dump_field(range_value, self.class.attributes[self.class.range_key])
199
- end
200
- end
201
- end
@@ -1,66 +0,0 @@
1
- # encoding: utf-8
2
- module Dynamoid
3
-
4
- # All the errors specific to Dynamoid. The goal is to mimic ActiveRecord.
5
- module Errors
6
-
7
- # Generic Dynamoid error
8
- class Error < StandardError; end
9
-
10
- class MissingRangeKey < Error; end
11
-
12
- class MissingIndex < Error; end
13
-
14
- # InvalidIndex is raised when an invalid index is specified, for example if
15
- # specified key attribute(s) or projected attributes do not exist.
16
- class InvalidIndex < Error
17
- def initialize(item)
18
- if (item.is_a? String)
19
- super(item)
20
- else
21
- super("Validation failed: #{item.errors.full_messages.join(", ")}")
22
- end
23
- end
24
- end
25
-
26
- # This class is intended to be private to Dynamoid.
27
- class ConditionalCheckFailedException < Error
28
- attr_reader :inner_exception
29
-
30
- def initialize(inner)
31
- super
32
- @inner_exception = inner
33
- end
34
- end
35
-
36
- class RecordNotUnique < ConditionalCheckFailedException
37
- attr_reader :original_exception
38
-
39
- def initialize(original_exception, record)
40
- super("Attempted to write record #{record} when its key already exists")
41
- @original_exception = original_exception
42
- end
43
- end
44
-
45
- class StaleObjectError < ConditionalCheckFailedException
46
- attr_reader :record, :attempted_action
47
-
48
- def initialize(record, attempted_action)
49
- super("Attempted to #{attempted_action} a stale object #{record}")
50
- @record = record
51
- @attempted_action = attempted_action
52
- end
53
- end
54
-
55
- class DocumentNotValid < Error
56
- attr_reader :document
57
-
58
- def initialize(document)
59
- super("Validation failed: #{document.errors.full_messages.join(", ")}")
60
- @document = document
61
- end
62
- end
63
-
64
- class InvalidQuery < Error; end
65
- end
66
- end
@@ -1,164 +0,0 @@
1
- # encoding: utf-8
2
- module Dynamoid #:nodoc:
3
- # All fields on a Dynamoid::Document must be explicitly defined -- if you have fields in the database that are not
4
- # specified with field, then they will be ignored.
5
- module Fields
6
- extend ActiveSupport::Concern
7
-
8
- PERMITTED_KEY_TYPES = [
9
- :number,
10
- :integer,
11
- :string,
12
- :datetime
13
- ]
14
-
15
- # Initialize the attributes we know the class has, in addition to our magic attributes: id, created_at, and updated_at.
16
- included do
17
- class_attribute :attributes
18
- class_attribute :range_key
19
-
20
- self.attributes = {}
21
- field :created_at, :datetime
22
- field :updated_at, :datetime
23
-
24
- field :id #Default primary key
25
- end
26
-
27
- module ClassMethods
28
-
29
- # Specify a field for a document.
30
- #
31
- # Its type determines how it is coerced when read in and out of the datastore.
32
- # You can specify :integer, :number, :set, :array, :datetime, and :serialized,
33
- # or specify a class that defines a serialization strategy.
34
- #
35
- # If you specify a class for field type, Dynamoid will serialize using
36
- # `dynamoid_dump` or `dump` methods, and load using `dynamoid_load` or `load` methods.
37
- #
38
- # Default field type is :string.
39
- #
40
- # @param [Symbol] name the name of the field
41
- # @param [Symbol] type the type of the field (refer to method description for details)
42
- # @param [Hash] options any additional options for the field
43
- #
44
- # @since 0.2.0
45
- def field(name, type = :string, options = {})
46
- named = name.to_s
47
- if type == :float
48
- Dynamoid.logger.warn("Field type :float, which you declared for '#{name}', is deprecated in favor of :number.")
49
- type = :number
50
- end
51
- self.attributes = attributes.merge(name => {:type => type}.merge(options))
52
-
53
- define_method(named) { read_attribute(named) }
54
- define_method("#{named}?") do
55
- value = read_attribute(named)
56
- case value
57
- when true then true
58
- when false, nil then false
59
- else
60
- !value.nil?
61
- end
62
- end
63
- define_method("#{named}=") {|value| write_attribute(named, value) }
64
- end
65
-
66
- def range(name, type = :string)
67
- field(name, type)
68
- self.range_key = name
69
- end
70
-
71
- def table(options)
72
- #a default 'id' column is created when Dynamoid::Document is included
73
- unless(attributes.has_key? hash_key)
74
- remove_field :id
75
- field(hash_key)
76
- end
77
- end
78
-
79
- def remove_field(field)
80
- field = field.to_sym
81
- attributes.delete(field) or raise "No such field"
82
- remove_method field
83
- remove_method :"#{field}="
84
- remove_method :"#{field}?"
85
- end
86
- end
87
-
88
- # You can access the attributes of an object directly on its attributes method, which is by default an empty hash.
89
- attr_accessor :attributes
90
- alias :raw_attributes :attributes
91
-
92
- # Write an attribute on the object. Also marks the previous value as dirty.
93
- #
94
- # @param [Symbol] name the name of the field
95
- # @param [Object] value the value to assign to that field
96
- #
97
- # @since 0.2.0
98
- def write_attribute(name, value)
99
- if (size = value.to_s.size) > MAX_ITEM_SIZE
100
- Dynamoid.logger.warn "DynamoDB can't store items larger than #{MAX_ITEM_SIZE} and the #{name} field has a length of #{size}."
101
- end
102
-
103
- if association = @associations[name]
104
- association.reset
105
- end
106
-
107
- attributes[name.to_sym] = value
108
- end
109
- alias :[]= :write_attribute
110
-
111
- # Read an attribute from an object.
112
- #
113
- # @param [Symbol] name the name of the field
114
- #
115
- # @since 0.2.0
116
- def read_attribute(name)
117
- attributes[name.to_sym]
118
- end
119
- alias :[] :read_attribute
120
-
121
- # Updates multiple attibutes at once, saving the object once the updates are complete.
122
- #
123
- # @param [Hash] attributes a hash of attributes to update
124
- #
125
- # @since 0.2.0
126
- def update_attributes(attributes)
127
- attributes.each {|attribute, value| self.write_attribute(attribute, value)} unless attributes.nil? || attributes.empty?
128
- save
129
- end
130
-
131
- # Update a single attribute, saving the object afterwards.
132
- #
133
- # @param [Symbol] attribute the attribute to update
134
- # @param [Object] value the value to assign it
135
- #
136
- # @since 0.2.0
137
- def update_attribute(attribute, value)
138
- write_attribute(attribute, value)
139
- save
140
- end
141
-
142
- private
143
-
144
- # Automatically called during the created callback to set the created_at time.
145
- #
146
- # @since 0.2.0
147
- def set_created_at
148
- self.created_at = DateTime.now if Dynamoid::Config.timestamps
149
- end
150
-
151
- # Automatically called during the save callback to set the updated_at time.
152
- #
153
- # @since 0.2.0
154
- def set_updated_at
155
- self.updated_at = DateTime.now if Dynamoid::Config.timestamps
156
- end
157
-
158
- def set_type
159
- self.type ||= self.class.to_s if self.class.attributes[:type]
160
- end
161
-
162
- end
163
-
164
- end