tiny_dyno 0.1.7 → 0.1.9

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5260b6e451ace6f876c6778496c4e3fe1b5d7337
4
- data.tar.gz: a7ff251eba21480888716e3833f632f37916da1f
3
+ metadata.gz: 2a57635fe6ebcd452a54d007997380f6616bb0f3
4
+ data.tar.gz: 3e7518b99d5034175ea1781ac4f39812a722c7fa
5
5
  SHA512:
6
- metadata.gz: 3d12c868b43577811890db7671e8c8498d7d53fe146bedfc7ef66474f19d79ba177c8265de3667f6fd4680ecb46876f65af1171c2d80fec869412d3b86698e37
7
- data.tar.gz: 03b3fb815185cf31fddd8eadb81c1fcf4bcbc4694238c9d2242ea901bc0fffbb649d3d10ffdaa5981bd4b0cfaefad41c39a39bbd687142b4215203d7e4641628
6
+ metadata.gz: cd0dc92db501ed54364de063d527acb8ccb3a115ed27585a1c6c4c5f3e0f73ed65a9441d569150fb6c095f52b58eb0c59bcf313e21949a100cd92a6e3dada745
7
+ data.tar.gz: e6d2aee6af7d226e667e0e7f522d227daf5662b1f725c961b95ce097e4b5f4a8a88696d95cef8c4da2adc6afb4aa352affef3732e463a47973d2693e9efd345d
data/CHANGES.md ADDED
@@ -0,0 +1,12 @@
1
+ 0.1.9 (2015-07-01)
2
+ -----------------
3
+
4
+ * Fixes - clean up of a few stale require 'pry'
5
+
6
+ 0.1.8 (2015-07-01)
7
+ ------------------
8
+
9
+ * Fixes - Raise Error, if multiple hash keys are being defined
10
+ * Fixes - On Create use 'expected' clause to achieve intended behavior on create,
11
+ to not overwrite an existing record, but only create a new record
12
+
@@ -63,7 +63,7 @@ module TinyDyno
63
63
  # @since 2.1.0
64
64
  def attribute_change(attr)
65
65
  attr = database_field_name(attr)
66
- [changed_attributes[attr], attributes[attr]] if attribute_changed?(attr)
66
+ [changed_attributes[attr], attributes[attr]] if (attribute_changed?(attr) && !attr.nil?)
67
67
  end
68
68
 
69
69
  end
@@ -70,10 +70,10 @@ module TinyDyno
70
70
  # check that each option key relates to a hash_key present on the model
71
71
  # do not permit scan queries
72
72
  def valid_option_keys(options)
73
- options.keys.each do |name|
74
- named = name.to_s
75
- raise TinyDyno::Errors::HashKeysOnly.new(klass: self.class, name: named) unless hash_key_is_defined?(named)
76
- end
73
+ raise TinyDyno::Errors::HashKeyOnly.new(klass: self.class, name: 'primary_key') if primary_key.nil?
74
+ # options.keys.each do |name|
75
+ # named = name.to_s
76
+ # end
77
77
  end
78
78
 
79
79
  # minimimum implementation for now
@@ -3,27 +3,29 @@ require 'tiny_dyno/changeable'
3
3
  require 'tiny_dyno/fields'
4
4
  require 'tiny_dyno/stateful'
5
5
  require 'tiny_dyno/tables'
6
- require 'tiny_dyno/hash_keys'
6
+ require 'tiny_dyno/hash_key'
7
7
  require 'tiny_dyno/persistable'
8
+ require 'tiny_dyno/expected'
8
9
 
9
10
  module TinyDyno
10
11
  module DocumentComposition
11
12
  extend ActiveSupport::Concern
12
13
 
13
14
  include Attributes
15
+ include Expected
14
16
  include Changeable
15
17
  include Fields
16
- include HashKeys
18
+ include HashKey
17
19
  include Persistable
18
20
  include Stateful
19
21
  include Tables
20
22
 
21
-
22
23
  MODULES = [
23
24
  Attributes,
25
+ Expected,
24
26
  Changeable,
25
27
  Fields,
26
- HashKeys,
28
+ HashKey,
27
29
  Persistable,
28
30
  Stateful,
29
31
  Tables,
@@ -50,14 +50,13 @@ module TinyDyno
50
50
  end
51
51
  end
52
52
 
53
-
54
53
  # encoding: utf-8
55
54
  module TinyDyno
56
55
  module Errors
57
56
 
58
57
  # This error is raised, when a query is performed with fields specified
59
58
  # that are not HashKeys, which would result in a table scan
60
- class HashKeysOnly < TinyDynoError
59
+ class HashKeyOnly < TinyDynoError
61
60
 
62
61
  # Create the new error.
63
62
  #
@@ -76,3 +75,30 @@ module TinyDyno
76
75
  end
77
76
  end
78
77
  end
78
+
79
+ # encoding: utf-8
80
+ module TinyDyno
81
+ module Errors
82
+
83
+ # This error is raised, when a query is performed with fields specified
84
+ # that are not HashKeys, which would result in a table scan
85
+ class OnlyOneHashKeyPermitted < TinyDynoError
86
+
87
+ # Create the new error.
88
+ #
89
+ # @example Instantiate the error.
90
+ # OnlyOneHashKeyPermitted.new(Person, "gender")
91
+ #
92
+ # @param [ Class ] klass The model class.
93
+ # @param [ String, Symbol ] name The name of the attribute.
94
+ #
95
+ # @since 3.0.0
96
+ def initialize(klass:, name:)
97
+ super(
98
+ compose_message("you can only define one hash_key", { klass: klass.name, name: name })
99
+ )
100
+ end
101
+ end
102
+ end
103
+ end
104
+
@@ -0,0 +1,18 @@
1
+ module TinyDyno
2
+ module Expected
3
+ extend ActiveSupport::Concern
4
+
5
+ # insert Expected clause, which will ensure
6
+ # that INSERTs will only take place
7
+ # if there is no record with that hash key yet
8
+ def request_as_new_record(request)
9
+ request.merge({
10
+ expected: {
11
+ "#{ primary_key[:attr] }": {
12
+ comparison_operator: 'NULL'
13
+ }
14
+ }})
15
+ end
16
+
17
+ end
18
+ end
@@ -41,24 +41,24 @@ module TinyDyno
41
41
 
42
42
  private
43
43
 
44
- # Is the field included in the fields that were returned from the
45
- # database? We can apply the default if:
46
- # 1. The field is included in an only limitation (field: 1)
47
- # 2. The field is not excluded in a without limitation (field: 0)
48
- #
49
- # @example Is the field included?
50
- # field.included?(fields)
51
- #
52
- # @param [ Hash ] fields The field limitations.
53
- #
54
- # @return [ true, false ] If the field was included.
44
+ # # Is the field included in the fields that were returned from the
45
+ # # database? We can apply the default if:
46
+ # # 1. The field is included in an only limitation (field: 1)
47
+ # # 2. The field is not excluded in a without limitation (field: 0)
48
+ # #
49
+ # # @example Is the field included?
50
+ # # field.included?(fields)
51
+ # #
52
+ # # @param [ Hash ] fields The field limitations.
53
+ # #
54
+ # # @return [ true, false ] If the field was included.
55
+ # #
56
+ # # @since 2.4.4
57
+ # def included?(fields)
58
+ # (fields.values.first == 1 && fields[name.to_s] == 1) ||
59
+ # (fields.values.first == 0 && !fields.has_key?(name.to_s))
60
+ # end
55
61
  #
56
- # @since 2.4.4
57
- def included?(fields)
58
- (fields.values.first == 1 && fields[name.to_s] == 1) ||
59
- (fields.values.first == 0 && !fields.has_key?(name.to_s))
60
- end
61
-
62
62
  end
63
63
  end
64
64
  end
@@ -0,0 +1,109 @@
1
+ module TinyDyno
2
+ module HashKey
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ class_attribute :attribute_definitions, :key_schema, :primary_key
7
+
8
+ # TODO :local_secondary_indexes, :global_secondary_indexes
9
+ self.attribute_definitions ||= []
10
+ self.key_schema ||= []
11
+ self.primary_key ||= {}
12
+ end
13
+
14
+ # return all defined hash keys on an instantiated object
15
+ # for further use in DynamoDB queries, i.e. to look up an object
16
+ #
17
+ def hash_key_as_selector
18
+ { "#{ self.class.primary_key[:attr] }": attributes[self.class.primary_key[:attr]] }
19
+ end
20
+
21
+ module ClassMethods
22
+
23
+ # Defines the primary key for the Document
24
+ # Only one primary key = hash_key is allowed in DynamoDB
25
+ #
26
+ # @example Define a field.
27
+ # hash_key :score, :type => Integer
28
+ #
29
+ # @param [ Symbol ] name The name of the hash_key.
30
+ # @param [ Hash ] options The options to pass to the hash_key.
31
+ #
32
+ # @option options [ Class ] :type The type of the field.
33
+ # @option options [ String ] :label The label for the field.
34
+ #
35
+ # @return [ Field ] The generated field
36
+ def hash_key(name, options = {})
37
+ raise TinyDyno::Errors::OnlyOneHashKeyPermitted.new(klass: self.class, name: name) unless primary_key.empty?
38
+ named = name.to_s
39
+ attribute_definition = build_attribute_definition(named,options[:type])
40
+ key_schema = build_key_schema(named)
41
+ unless attribute_definition_meets_spec?(attribute_definition)
42
+ raise TinyDyno::Errors::InvalidHashKey.new(klass: self.class, name: name)
43
+ end
44
+ # we need the accessors as well
45
+ add_field(named, options)
46
+ self.attribute_definitions << attribute_definition
47
+ self.key_schema << key_schema
48
+ self.primary_key = {
49
+ attr: attribute_definition[:attribute_name],
50
+ attr_type: attribute_definition[:attribute_type],
51
+ key_type: key_schema[:key_type],
52
+ }
53
+ end
54
+
55
+ # convert a hash key into a format as expected by
56
+ # put_item and update_item request
57
+ def as_item_entry(hash_key)
58
+
59
+ end
60
+
61
+ private
62
+
63
+ # Return true or false, depending on whether the attribute_definitions on the model
64
+ # meet the specification of the Aws Sdk
65
+ # This is a syntax, not a logic check
66
+ def attribute_definitions_meet_spec?
67
+ attribute_definitions.each do |definition|
68
+ return false unless attribute_definition_meets_spec?(definition)
69
+ end
70
+ end
71
+
72
+ def attribute_definition_meets_spec?(definition)
73
+ return (definition.has_key?(:attribute_name) && \
74
+ definition.has_key?(:attribute_type) && \
75
+ definition[:attribute_name].class == String && \
76
+ definition[:attribute_type].class == String && \
77
+ ['S','N', 'B'].include?(definition[:attribute_type]))
78
+ end
79
+
80
+ def build_attribute_definition(name, key_type)
81
+ {
82
+ attribute_name: name,
83
+ attribute_type: hash_key_type(key_type)
84
+ }
85
+ end
86
+
87
+ def hash_key_type(key_type = nil)
88
+ return 'S' if key_type == String
89
+ return 'N' if key_type == Fixnum or key_type == Integer
90
+ return nil
91
+ end
92
+
93
+ def build_key_schema(name)
94
+ {
95
+ attribute_name: name,
96
+ key_type: 'HASH'
97
+ }
98
+ end
99
+
100
+ # convert values in queries to DynamoDB
101
+ # into types as expected by DynamoDB
102
+ def dyno_typed_key(key:, val:)
103
+ typed_class = self.fields[key].options[:type]
104
+ return (document_typed(klass: typed_class, value: val))
105
+ end
106
+
107
+ end
108
+ end
109
+ end
@@ -4,7 +4,13 @@ module TinyDyno
4
4
 
5
5
  def save(options = {})
6
6
  if new_record?
7
- request_put_item(options)
7
+ if request_put_item(options)
8
+ changes_applied
9
+ @new_record = nil
10
+ return true
11
+ else
12
+ return false
13
+ end
8
14
  else
9
15
  request_update_item(options)
10
16
  end
@@ -13,14 +19,8 @@ module TinyDyno
13
19
  private
14
20
 
15
21
  def request_put_item(options)
16
- request = build_put_item_request(options)
17
- if TinyDyno::Adapter.put_item(put_item_request: request)
18
- changes_applied
19
- @new_record = nil
20
- return true
21
- else
22
- return false
23
- end
22
+ request = request_as_new_record(build_item_request(options))
23
+ return(TinyDyno::Adapter.put_item(put_item_request: request))
24
24
  end
25
25
 
26
26
  # The target structure as per
@@ -51,7 +51,7 @@ module TinyDyno
51
51
  # "ExpressionAttributeValueVariable" => "value", # value <Hash,Array,String,Numeric,Boolean,IO,Set,nil>
52
52
  # },
53
53
  # })
54
- def build_put_item_request(options)
54
+ def build_item_request(options)
55
55
  {
56
56
  table_name: self.class.table_name,
57
57
  item: build_item_request_entries
File without changes
@@ -1,3 +1,3 @@
1
1
  module TinyDyno
2
- VERSION = '0.1.7'
2
+ VERSION = '0.1.9'
3
3
  end
data/lib/tiny_dyno.rb CHANGED
@@ -1,11 +1,6 @@
1
1
  require 'active_model'
2
2
  require 'aws-sdk'
3
3
 
4
- # if ENV['RACK_ENV'] == 'development'
5
- # require 'pry'
6
- # require 'awesome_print'
7
- # end
8
-
9
4
  require 'tiny_dyno/extensions'
10
5
 
11
6
  require 'tiny_dyno/version'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tiny_dyno
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.1.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Gerschner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-30 00:00:00.000000000 Z
11
+ date: 2015-07-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -162,6 +162,7 @@ files:
162
162
  - ".ruby-version"
163
163
  - ".simplecov"
164
164
  - ".travis.yml"
165
+ - CHANGES.md
165
166
  - Gemfile
166
167
  - Guardfile
167
168
  - LICENSE
@@ -185,14 +186,17 @@ files:
185
186
  - lib/tiny_dyno/errors/attribute_errors.rb
186
187
  - lib/tiny_dyno/errors/hash_key_errors.rb
187
188
  - lib/tiny_dyno/errors/tiny_dyno_error.rb
189
+ - lib/tiny_dyno/expected.rb
188
190
  - lib/tiny_dyno/extensions.rb
189
191
  - lib/tiny_dyno/extensions/module.rb
190
192
  - lib/tiny_dyno/fields.rb
191
193
  - lib/tiny_dyno/fields/standard.rb
194
+ - lib/tiny_dyno/hash_key.rb
192
195
  - lib/tiny_dyno/hash_keys.rb
193
196
  - lib/tiny_dyno/loggable.rb
194
197
  - lib/tiny_dyno/persistable.rb
195
198
  - lib/tiny_dyno/range_attributes.rb
199
+ - lib/tiny_dyno/range_key.rb
196
200
  - lib/tiny_dyno/stateful.rb
197
201
  - lib/tiny_dyno/tables.rb
198
202
  - lib/tiny_dyno/version.rb