dynamodb-api 0.6.2 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d9be0f31417b188293408482f8661646b207c587e62f19b252cba0beecb9f7a7
4
- data.tar.gz: e449872d243d29819b761edf6503f5931cd838436eabb2584bd7ea238125573f
3
+ metadata.gz: 1276a3be5e1124f79957caee61c7585e3f59f37da5f12e2fac5d638238727ee8
4
+ data.tar.gz: c36d86b1087075fd6c154e5491cd08e6effcc0e91ffa0d96595d31fafc33eabc
5
5
  SHA512:
6
- metadata.gz: 43976f0890badbe08057345c9576d6cb48cd623ac97b1363bab6cc9dfaa245cded0cba11dc694a6d4213e0b08ab30ac8436f86b249553859220cb03224068ffa
7
- data.tar.gz: 66be89216803aeb7644a12a5107894cc1531eb14c9ca70bae8dc304fdeffd985d1ba4ac83d8ff07eaa381138e51e4b90c8aa22f056c4e62e55ec21fce12a43fc
6
+ metadata.gz: a3c366b1cd32a307c6756bb4fb50ba43cafa98b5ff69f430ec55d638a5566492ee98f8554531196b27749e83ed2af2f26267cd12d9661feb193bb6ad63d44be9
7
+ data.tar.gz: 3cac38591e633e466439a2c12eaec0311828138caeb45bdc76f6c420321725a082fba136e2c0f2f826db40ba35c5e8bd5b672ffe2bb43ec10080d4e3f3bdbb31
@@ -0,0 +1,28 @@
1
+ name: build
2
+ on: [push, pull_request]
3
+ jobs:
4
+ test:
5
+ strategy:
6
+ fail-fast: false
7
+ matrix:
8
+ ruby: [2.4, 2.5, 2.6, 2.7]
9
+ gemfile: [ aws_sdk_2_rails_5, aws_sdk_2_rails_6, aws_sdk_3_rails_5, aws_sdk_3_rails_6 ]
10
+ exclude:
11
+ - { ruby: 2.4, gemfile: aws_sdk_2_rails_6 }
12
+ - { ruby: 2.4, gemfile: aws_sdk_3_rails_6 }
13
+ runs-on: ubuntu-latest
14
+ env:
15
+ BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile
16
+ TEST_DYNAMODB_ENDPOINT: 'http://0.0.0.0:8000'
17
+ steps:
18
+ - uses: actions/checkout@v2
19
+ - uses: ruby/setup-ruby@v1
20
+ with:
21
+ ruby-version: ${{ matrix.ruby }}
22
+ bundler-cache: true
23
+ - run: bin/setup
24
+ - run: docker-compose up -d
25
+ - run: docker ps
26
+ - run: bundle exec rubocop --fail-level=C
27
+ - run: bundle exec rake spec
28
+ - run: docker-compose down
data/Appraisals CHANGED
@@ -1,7 +1,19 @@
1
- appraise "aws-sdk-2" do
1
+ appraise "aws-sdk-2-rails-5" do
2
2
  gem "aws-sdk", "~> 2"
3
+ gem "activesupport", "~> 5"
3
4
  end
4
5
 
5
- appraise "aws-sdk-3" do
6
+ appraise "aws-sdk-2-rails-6" do
7
+ gem "aws-sdk", "~> 2"
8
+ gem "activesupport", "~> 6"
9
+ end
10
+
11
+ appraise "aws-sdk-3-rails-5" do
12
+ gem "aws-sdk", "~> 3"
13
+ gem "activesupport", "~> 5"
14
+ end
15
+
16
+ appraise "aws-sdk-3-rails-6" do
6
17
  gem "aws-sdk", "~> 3"
18
+ gem "activesupport", "~> 6"
7
19
  end
data/CHANGELOG.md CHANGED
@@ -6,6 +6,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ---
10
+
11
+ ## [0.9.1] - 2020-11-21
12
+ ### Security
13
+ - [#59](https://github.com/walkersumida/dynamodb-api/pull/59) Update rake version
14
+
15
+ ### Removed
16
+ - [#57](https://github.com/walkersumida/dynamodb-api/pull/57) Unsupport ruby2.3 and activesupport4
17
+
18
+ ## [0.9.0] - 2020-02-24
19
+ ### Fixed
20
+ - [#56](https://github.com/walkersumida/dynamodb-api/pull/56) Make the `begins_with` and `between` available
21
+
22
+ ## [0.8.1] - 2019-06-03
23
+ ### Fixed
24
+ - [#49](https://github.com/walkersumida/dynamodb-api/pull/49) not be added table name prefix
25
+ - [#48](https://github.com/walkersumida/dynamodb-api/pull/48) Improvement DX
26
+
27
+ ## [0.8.0] - 2019-03-03
28
+ ### Added
29
+ - [#39](https://github.com/walkersumida/dynamodb-api/pull/39) `next` method
30
+
31
+ ## [0.7.0] - 2018-12-23
32
+ ### Added
33
+ - [#34](https://github.com/walkersumida/dynamodb-api/pull/34) `scan` method
34
+
9
35
  ## [0.6.2] - 2018-12-13
10
36
  ### Added
11
37
  - [#32](https://github.com/walkersumida/dynamodb-api/pull/32) `remove_attributes` method
data/Dockerfile ADDED
@@ -0,0 +1,15 @@
1
+ FROM ruby:2.5.5
2
+
3
+ ENV APP_ROOT /app
4
+ WORKDIR $APP_ROOT
5
+
6
+ COPY . $APP_ROOT
7
+
8
+ RUN \
9
+ echo 'gem: --no-document' >> ~/.gemrc && \
10
+ cp ~/.gemrc /etc/gemrc && \
11
+ chmod uog+r /etc/gemrc && \
12
+ bundle config --global build.nokogiri --use-system-libraries && \
13
+ bundle config --global jobs 4 && \
14
+ bin/setup && \
15
+ rm -rf ~/.gem
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Dynamodb::Api
2
2
 
3
- [![Build Status](https://travis-ci.org/walkersumida/dynamodb-api.svg?branch=master)](https://travis-ci.org/walkersumida/dynamodb-api)
3
+ ![Build Status](https://github.com/walkersumida/dynamodb-api/workflows/build/badge.svg?branch=master)
4
4
  [![Gem Version](https://badge.fury.io/rb/dynamodb-api.svg)](https://badge.fury.io/rb/dynamodb-api)
5
5
 
6
6
  ## Installation
@@ -57,6 +57,64 @@ cars table.
57
57
  |3 |3 |Model S |0.20120601e8 |0 |
58
58
  |4 |1 |S2000 |0.19980101e8 |1 |
59
59
 
60
+ ### Scan
61
+
62
+ Scan returns items in random order.
63
+
64
+ ```ruby
65
+ scan = Dynamodb::Api.scan
66
+ scan.from('cars')
67
+ items = scan.all.items
68
+ ```
69
+
70
+ | id | maker_id(Partition key) | model | release_date(Sort key) | status |
71
+ |:---|:---|:---|:---|:---|
72
+ |1 |1 |Accord |0.19760508e8 |0 |
73
+ |2 |2 |CROWN |0.19550101e8 |0 |
74
+ |3 |3 |Model S |0.20120601e8 |0 |
75
+ |4 |1 |S2000 |0.19980101e8 |1 |
76
+
77
+ #### Filter
78
+
79
+ ```ruby
80
+ scan = Dynamodb::Api.scan
81
+ scan.from('cars').
82
+ filter('model = :model', ':model': 'S2000')
83
+ items = scan.all.items
84
+ ```
85
+
86
+ | id | maker_id(Partition key) | model | release_date(Sort key) | status |
87
+ |:---|:---|:---|:---|:---|
88
+ |4 |1 |S2000 |0.19980101e8 |1 |
89
+
90
+ #### Limit
91
+
92
+ ```ruby
93
+ scan = Dynamodb::Api.scan
94
+ scan.from('cars').
95
+ limit(1)
96
+ items = scan.all.items
97
+ ```
98
+
99
+ | id | maker_id(Partition key) | model | release_date(Sort key) | status |
100
+ |:---|:---|:---|:---|:---|
101
+ |1 |1 |Accord |0.19760508e8 |0 |
102
+
103
+ #### Next(Paging)
104
+
105
+ ```ruby
106
+ scan = Dynamodb::Api.scan
107
+ scan.from('cars').
108
+ limit(1)
109
+ _items = scan.all.items
110
+ items = scan.next.items
111
+ ```
112
+
113
+ | id | maker_id(Partition key) | model | release_date(Sort key) | status |
114
+ |:---|:---|:---|:---|:---|
115
+ |2 |2 |CROWN |0.19550101e8 |0 |
116
+
117
+
60
118
  ### Query
61
119
  https://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#query-instance_method
62
120
 
@@ -131,6 +189,22 @@ items = query.all.items
131
189
  |:---|:---|:---|:---|:---|
132
190
  |1 |1 |Accord |0.19760508e8 |0 |
133
191
 
192
+ #### Next(Paging)
193
+
194
+ ```ruby
195
+ query = Dynamodb::Api.query
196
+ query.from('cars').index('index_maker_id_release_date').
197
+ where(['maker_id', '=', 1]).
198
+ order('asc'). # default: 'desc'
199
+ limit(1)
200
+ _items = query.all.items
201
+ items = query.next.items
202
+ ```
203
+
204
+ | id | maker_id(Partition key) | model | release_date(Sort key) | status |
205
+ |:---|:---|:---|:---|:---|
206
+ |4 |1 |S2000 |0.19980101e8 |1 |
207
+
134
208
  #### Expression Attribute Names
135
209
 
136
210
  Words reserved in DynamoDB can not be used without special processing.
@@ -211,11 +285,10 @@ client.create_backup(
211
285
  ## Development
212
286
 
213
287
  - Run `docker-compose up` to run the dynamodb_local.
214
- - After checking out the repo, run `bin/setup` to install dependencies.
215
- - Run `bundle exec rake spec` to run the tests. Or run `bundle exec appraisal aws-sdk-* rake spec` to run the tests. Replase `*` with aws sdk major version.
216
- - You can also run `bin/console` for an interactive prompt that will allow you to experiment.
288
+ - Run `docker-compose run ruby bundle exec rake spec` to run the tests. Or run `docker-compose run ruby bundle exec appraisal aws-sdk-* rake spec` to run the tests. Replase `*` with aws sdk major version.
289
+ - You can also run `docker-compose run ruby bin/console` for an interactive prompt that will allow you to experiment.
217
290
 
218
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
291
+ To install this gem onto your local machine, run `docker-compose run ruby bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `docker-compose run ruby bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
219
292
 
220
293
  ## Contributing
221
294
 
data/bin/console CHANGED
@@ -21,7 +21,7 @@ Aws.config.update(
21
21
  )
22
22
 
23
23
  Dynamodb::Api.config do |config|
24
- config.endpoint = 'http://0.0.0.0:8000'
24
+ config.endpoint = 'http://dynamodb:8000'
25
25
  end
26
26
 
27
27
  IRB.start(__FILE__)
data/docker-compose.yml CHANGED
@@ -1,6 +1,12 @@
1
1
  version: '3'
2
2
  services:
3
+ ruby:
4
+ build:
5
+ context: .
6
+ dockerfile: Dockerfile
7
+ volumes:
8
+ - .:/app
3
9
  dynamodb:
4
- image: cnadiminti/dynamodb-local:2018-04-11
10
+ image: amazon/dynamodb-local
5
11
  ports:
6
12
  - 8000:8000
data/dynamodb-api.gemspec CHANGED
@@ -23,10 +23,9 @@ Gem::Specification.new do |spec|
23
23
  spec.require_paths = ['lib']
24
24
 
25
25
  spec.add_runtime_dependency 'aws-sdk', '>= 2'
26
- spec.add_runtime_dependency('activesupport', '>= 4')
26
+ spec.add_runtime_dependency('activesupport', '>= 5')
27
27
 
28
- spec.add_development_dependency 'bundler', '~> 1.16'
29
- spec.add_development_dependency 'rake', '~> 10.0'
28
+ spec.add_development_dependency 'rake', '>= 12.3.3'
30
29
  spec.add_development_dependency 'rspec', '~> 3.0'
31
30
  spec.add_development_dependency 'pry'
32
31
  spec.add_development_dependency 'rubocop-airbnb'
@@ -4,5 +4,6 @@ source "https://rubygems.org"
4
4
 
5
5
  gem "pry-byebug", platforms: :ruby
6
6
  gem "aws-sdk", "~> 2"
7
+ gem "activesupport", "~> 5"
7
8
 
8
9
  gemspec path: "../"
@@ -0,0 +1,9 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "pry-byebug", platforms: :ruby
6
+ gem "aws-sdk", "~> 2"
7
+ gem "activesupport", "~> 6"
8
+
9
+ gemspec path: "../"
@@ -4,5 +4,6 @@ source "https://rubygems.org"
4
4
 
5
5
  gem "pry-byebug", platforms: :ruby
6
6
  gem "aws-sdk", "~> 3"
7
+ gem "activesupport", "~> 5"
7
8
 
8
9
  gemspec path: "../"
@@ -0,0 +1,9 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "pry-byebug", platforms: :ruby
6
+ gem "aws-sdk", "~> 3"
7
+ gem "activesupport", "~> 6"
8
+
9
+ gemspec path: "../"
data/lib/dynamodb/api.rb CHANGED
@@ -5,7 +5,9 @@ require 'active_support/core_ext'
5
5
  require 'dynamodb/api/version'
6
6
  require 'dynamodb/api/config'
7
7
  require 'dynamodb/api/adapter'
8
+ require 'dynamodb/api/base'
8
9
  require 'dynamodb/api/query'
10
+ require 'dynamodb/api/scan'
9
11
  require 'dynamodb/api/relation'
10
12
  require 'dynamodb/api/relation/query_methods'
11
13
  require 'dynamodb/api/relation/from_clause'
@@ -40,6 +42,10 @@ module Dynamodb
40
42
  Delete::Tables.delete_tables
41
43
  end
42
44
 
45
+ def scan
46
+ Scan.new
47
+ end
48
+
43
49
  def query
44
50
  Query.new
45
51
  end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dynamodb/api/relation'
4
+
5
+ module Dynamodb
6
+ module Api
7
+ class Base # :nodoc:
8
+ include Relation
9
+ attr_accessor :last_evaluated_key
10
+
11
+ def all
12
+ raise NotImplementedError, "You must implement #{self.class}##{__method__}"
13
+ end
14
+
15
+ def next
16
+ raise NotImplementedError, "You must implement #{self.class}##{__method__}"
17
+ end
18
+
19
+ private
20
+
21
+ def build_input
22
+ raise NotImplementedError, "You must implement #{self.class}##{__method__}"
23
+ end
24
+
25
+ def base_params
26
+ raise NotImplementedError, "You must implement #{self.class}##{__method__}"
27
+ end
28
+
29
+ def order_direct(clause)
30
+ clause&.direct ? clause.direct : OrderClause.new.direct
31
+ end
32
+
33
+ def select_name(clause)
34
+ clause&.name ? clause.name : SelectClause.new.name
35
+ end
36
+
37
+ # Build filter clause.
38
+ # `filter_expression`: e.g. "Artist = :a"
39
+ # `expression_attribute_values`: e.g. { ":a" => "No One You Know" }
40
+ #
41
+ # @param input [Aws::DynamoDB::Types::ScanInput]
42
+ # @return [Aws::DynamoDB::Types::ScanInput]
43
+ def build_filter_clause(input)
44
+ return input if filter_clause&.expression.blank?
45
+ input[:filter_expression] = filter_clause.expression
46
+ if filter_clause.values.present?
47
+ if input[:expression_attribute_values].nil?
48
+ input[:expression_attribute_values] = {}
49
+ end
50
+ input[:expression_attribute_values].
51
+ merge!(filter_clause.values)
52
+ end
53
+ input
54
+ end
55
+
56
+ def build_expression_attribute_names(input)
57
+ if filter_clause&.reserved_words.present?
58
+ expression_attribute.add(filter_clause.reserved_words)
59
+ end
60
+ if expression_attribute.names.present?
61
+ input[:expression_attribute_names] = expression_attribute.names
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -15,6 +15,13 @@ module Dynamodb
15
15
  option :retry_limit, default: 10
16
16
  option :table_name_prefix, default: ''
17
17
  option :index_name_prefix, default: ''
18
+
19
+ # @param value [String] the table name
20
+ # @return [String] the table name
21
+ def build_table_name(value)
22
+ return value unless table_name_prefix?
23
+ "#{table_name_prefix}#{value}"
24
+ end
18
25
  end
19
26
  end
20
27
  end
@@ -3,9 +3,13 @@
3
3
  module Dynamodb
4
4
  module Api
5
5
  module Delete
6
- class Item # :nodoc:
6
+ class Item
7
+ # @param key [Hash] the item key
8
+ # @param table_name [String] the table name
7
9
  def self.delete_item(key, table_name)
8
10
  client = Adapter.client
11
+ table_name = Dynamodb::Api::Config.build_table_name(table_name)
12
+
9
13
  client.delete_item(key: key, table_name: table_name)
10
14
  end
11
15
  end
@@ -4,6 +4,7 @@ module Dynamodb
4
4
  module Api
5
5
  module Delete
6
6
  class Tables # :nodoc:
7
+ # TODO: add rspec
7
8
  def self.delete_tables
8
9
  client = Adapter.client
9
10
  table_names = client.list_tables[:table_names]
@@ -4,21 +4,24 @@ module Dynamodb
4
4
  module Api
5
5
  module Map
6
6
  class Operator # :nodoc:
7
+ # Replace the Dynamodb Operators
8
+ # @param k [String] The Dynamodb Operator
9
+ # @return [String]
7
10
  def self.key(k)
8
11
  k = k.gsub(' ', '')
9
12
  case k
10
- when '='
11
- 'EQ'
12
- when '!='
13
- 'NE'
14
- when '<='
15
- 'LE'
16
- when '<'
17
- 'LT'
18
- when '>='
19
- 'GE'
20
- when '>'
21
- 'GT'
13
+ when 'EQ'
14
+ '='
15
+ when 'NE'
16
+ '!='
17
+ when 'LE'
18
+ '<='
19
+ when 'LT'
20
+ '<'
21
+ when 'GE'
22
+ '>='
23
+ when 'GT'
24
+ '>'
22
25
  else
23
26
  k
24
27
  end
@@ -3,9 +3,13 @@
3
3
  module Dynamodb
4
4
  module Api
5
5
  module Put
6
- class Item # :nodoc:
6
+ class Item
7
+ # @param key [Hash] the item key
8
+ # @param table_name [String] the table name
7
9
  def self.put_item(item, table_name)
8
10
  client = Adapter.client
11
+ table_name = Dynamodb::Api::Config.build_table_name(table_name)
12
+
9
13
  client.put_item(item: item, table_name: table_name)
10
14
  end
11
15
  end
@@ -4,55 +4,53 @@ require 'dynamodb/api/relation'
4
4
 
5
5
  module Dynamodb
6
6
  module Api
7
- class Query # :nodoc:
8
- include Relation
9
-
7
+ class Query < Base # :nodoc:
10
8
  def all
11
- Adapter.client.query(build_query)
12
- end
13
-
14
- private
15
-
16
- def build_query
17
- build_params = base_params.merge(build_filter_clause)
18
- build_params[:scan_index_forward] = order_direct(order_clause)
19
- build_params[:select] = select_name(select_clause)
20
- build_expression_attribute_names(build_params)
21
- build_params[:limit] = limit_clause.number if limit_clause&.number
22
- build_params
9
+ result = Adapter.client.query(build_input)
10
+ @last_evaluated_key = result.last_evaluated_key
11
+ result
23
12
  end
24
13
 
25
- def base_params
26
- {
27
- table_name: from_clause.name,
28
- index_name: index_clause.name,
29
- key_conditions: where_clause.key_conditions,
30
- }
14
+ def next
15
+ return nil if @last_evaluated_key.blank?
16
+ input = build_input
17
+ input[:exclusive_start_key] = @last_evaluated_key
18
+ result = Adapter.client.query(input)
19
+ @last_evaluated_key = result.last_evaluated_key
20
+ return nil if result.count.zero?
21
+ result
31
22
  end
32
23
 
33
- def order_direct(clause)
34
- clause&.direct ? clause.direct : OrderClause.new.direct
35
- end
36
-
37
- def select_name(clause)
38
- clause&.name ? clause.name : SelectClause.new.name
39
- end
24
+ private
40
25
 
41
- def build_filter_clause
42
- return {} if filter_clause&.expression.blank?
43
- {
44
- filter_expression: filter_clause.expression,
45
- expression_attribute_values: filter_clause.values,
46
- }
26
+ # Build options.
27
+ #
28
+ # @return [Aws::DynamoDB::Types::ScanInput]
29
+ def build_input
30
+ input = Aws::DynamoDB::Types::QueryInput.new
31
+ input[:expression_attribute_values] = {}
32
+ input = base_input(input)
33
+ input = build_filter_clause(input)
34
+ input[:scan_index_forward] = order_direct(order_clause)
35
+ input[:select] = select_name(select_clause)
36
+ build_expression_attribute_names(input)
37
+ input[:limit] = limit_clause.number if limit_clause&.number
38
+ input
47
39
  end
48
40
 
49
- def build_expression_attribute_names(params)
50
- if filter_clause&.reserved_words.present?
51
- expression_attribute.add(filter_clause.reserved_words)
52
- end
53
- if expression_attribute.names.present?
54
- params[:expression_attribute_names] = expression_attribute.names
55
- end
41
+ # Build required options.
42
+ # `key_condition_expression`: e.g. "Artist = :a"
43
+ # `expression_attribute_values`: e.g. { ":a" => "No One You Know" }
44
+ #
45
+ # @param input [Aws::DynamoDB::Types::ScanInput]
46
+ # @return [Aws::DynamoDB::Types::ScanInput]
47
+ def base_input(input)
48
+ input[:table_name] = from_clause.name
49
+ input[:index_name] = index_clause.name
50
+ input[:key_condition_expression] = where_clause.key_condition
51
+ input[:expression_attribute_values].
52
+ merge!(where_clause.attribute_values)
53
+ input
56
54
  end
57
55
  end
58
56
  end
@@ -6,11 +6,9 @@ module Dynamodb
6
6
  class FromClause # :nodoc:
7
7
  attr_reader :name
8
8
 
9
+ # @param name [String] the table name
9
10
  def initialize(name)
10
- if Dynamodb::Api::Config.table_name_prefix?
11
- name = Dynamodb::Api::Config.table_name_prefix + name
12
- end
13
- @name = name
11
+ @name = Dynamodb::Api::Config.build_table_name(name)
14
12
  end
15
13
  end
16
14
  end
@@ -24,8 +24,8 @@ module Dynamodb
24
24
  self
25
25
  end
26
26
 
27
- def where(key_conditions)
28
- self.where_clause = Relation::WhereClause.new(key_conditions)
27
+ def where(expression)
28
+ self.where_clause = Relation::WhereClause.new(expression)
29
29
  self
30
30
  end
31
31
 
@@ -4,24 +4,89 @@ module Dynamodb
4
4
  module Api
5
5
  module Relation
6
6
  class WhereClause # :nodoc:
7
- attr_reader :key_conditions
7
+ attr_reader :key_condition
8
+ attr_reader :attribute_values
8
9
 
9
10
  KEY = 0
10
11
  VALUE = 2
11
12
  OPERATOR = 1
13
+ FROM = 0
14
+ TO = 1
12
15
 
13
- def initialize(key_conditions)
14
- @key_conditions = build(key_conditions)
16
+ # @param conditions [Array]
17
+ def initialize(conditions)
18
+ built_conditions = build(conditions)
19
+ @key_condition = built_conditions[:key_conditions]
20
+ @attribute_values = built_conditions[:attribute_values]
15
21
  end
16
22
 
17
23
  private
18
24
 
19
- def build(key_conditions)
20
- conditions = format_conditions(key_conditions)
21
- conditions.each_with_object({}) do |c, h|
22
- h[c[KEY]] = {
23
- attribute_value_list: format_value(c[VALUE]),
24
- comparison_operator: Map::Operator.key(c[OPERATOR]),
25
+ # Build where clause.
26
+ #
27
+ # @param conditions [Array]
28
+ def build(conditions)
29
+ init = { key_conditions: [], attribute_values: {} }
30
+ conditions = format_conditions(conditions)
31
+ built = conditions.each_with_object(init) do |c, h|
32
+ h[:key_conditions] <<
33
+ format_key_condition(c[KEY], c[OPERATOR])
34
+ h[:attribute_values].
35
+ merge!(format_values(c[KEY], c[OPERATOR], c[VALUE]))
36
+ end
37
+ built[:key_conditions] =
38
+ built[:key_conditions].join(' AND ')
39
+ built
40
+ end
41
+
42
+ # Format to the `key_condition_expression`.
43
+ # e.g.
44
+ # `format_key_condition("Artist", "=")` =>
45
+ # `"Artist = :Artist"`
46
+ #
47
+ # `format_key_condition("Artist", "begins_with")` =>
48
+ # `"begins_with(Artist, :Artist)"`
49
+ #
50
+ # `format_key_condition("Year", "between")` =>
51
+ # `"Year between :from_Year and :to_Year"`
52
+ #
53
+ # @param key [String] a attribute name
54
+ # @param operator [String] a operator
55
+ # @return [String] Formatted expression.
56
+ def format_key_condition(key, operator)
57
+ case operator.downcase
58
+ when 'begins_with'
59
+ "#{operator.downcase}(#{key}, :#{key})"
60
+ when 'between'
61
+ "#{key} #{operator.downcase}" \
62
+ " :from_#{key} AND :to_#{key}"
63
+ else
64
+ "#{key} #{Map::Operator.key(operator)} :#{key}"
65
+ end
66
+ end
67
+
68
+ # Format to the `expression_attribute_values`
69
+ # e.g.
70
+ # `format_values("Artist", "=", "blue")` =>
71
+ # `{ ":Artist" => "blue" }`
72
+ #
73
+ # `format_values("Year", "between", [1999, 2020])` =>
74
+ # `{ ":from_Year" => 1999, ":to_Year" => 2020 }`
75
+ #
76
+ # @param key [String] a attribute name
77
+ # @param operator [String] a operator
78
+ # @param values [Object] values
79
+ # @return [Hash<Object>] Formatted expression.
80
+ def format_values(key, operator, values)
81
+ case operator.downcase
82
+ when 'between'
83
+ {
84
+ ":from_#{key}" => values[FROM],
85
+ ":to_#{key}" => values[TO],
86
+ }
87
+ else
88
+ {
89
+ ":#{key}" => values.is_a?(Array) ? values[0] : values,
25
90
  }
26
91
  end
27
92
  end
@@ -30,11 +95,6 @@ module Dynamodb
30
95
  return [conditions] unless conditions[0].is_a?(Array)
31
96
  conditions
32
97
  end
33
-
34
- def format_value(value)
35
- return [value] unless value.is_a?(Array)
36
- value
37
- end
38
98
  end
39
99
  end
40
100
  end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dynamodb/api/relation'
4
+
5
+ module Dynamodb
6
+ module Api
7
+ class Scan < Base # :nodoc:
8
+ def all
9
+ result = Adapter.client.scan(build_input)
10
+ @last_evaluated_key = result.last_evaluated_key
11
+ result
12
+ end
13
+
14
+ def next
15
+ return nil if @last_evaluated_key.blank?
16
+ input = build_input
17
+ input[:exclusive_start_key] = @last_evaluated_key
18
+ result = Adapter.client.scan(input)
19
+ @last_evaluated_key = result.last_evaluated_key
20
+ result
21
+ end
22
+
23
+ private
24
+
25
+ def build_input
26
+ input = Aws::DynamoDB::Types::ScanInput.new
27
+ input = base_input(input)
28
+ input = build_filter_clause(input)
29
+ input[:index_name] = index_clause.name if index_clause&.name
30
+ input[:select] = select_name(select_clause)
31
+ build_expression_attribute_names(input)
32
+ input[:limit] = limit_clause.number if limit_clause&.number
33
+ input
34
+ end
35
+
36
+ def base_input(input)
37
+ input[:table_name] = from_clause.name
38
+ input
39
+ end
40
+ end
41
+ end
42
+ end
@@ -7,7 +7,7 @@ module Dynamodb
7
7
  def update_item(key, cols, table_name)
8
8
  @key = key
9
9
  @cols = cols
10
- @table_name = table_name
10
+ @table_name = Dynamodb::Api::Config.build_table_name(table_name)
11
11
 
12
12
  client = Adapter.client
13
13
  client.update_item(build_update_clause)
@@ -1,5 +1,5 @@
1
1
  module Dynamodb
2
2
  module Api
3
- VERSION = '0.6.2'.freeze
3
+ VERSION = '0.9.1'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dynamodb-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - WalkerSumida
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-12-15 00:00:00.000000000 Z
11
+ date: 2021-06-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk
@@ -30,42 +30,28 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '4'
33
+ version: '5'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '4'
41
- - !ruby/object:Gem::Dependency
42
- name: bundler
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '1.16'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '1.16'
40
+ version: '5'
55
41
  - !ruby/object:Gem::Dependency
56
42
  name: rake
57
43
  requirement: !ruby/object:Gem::Requirement
58
44
  requirements:
59
- - - "~>"
45
+ - - ">="
60
46
  - !ruby/object:Gem::Version
61
- version: '10.0'
47
+ version: 12.3.3
62
48
  type: :development
63
49
  prerelease: false
64
50
  version_requirements: !ruby/object:Gem::Requirement
65
51
  requirements:
66
- - - "~>"
52
+ - - ">="
67
53
  - !ruby/object:Gem::Version
68
- version: '10.0'
54
+ version: 12.3.3
69
55
  - !ruby/object:Gem::Dependency
70
56
  name: rspec
71
57
  requirement: !ruby/object:Gem::Requirement
@@ -129,15 +115,16 @@ executables: []
129
115
  extensions: []
130
116
  extra_rdoc_files: []
131
117
  files:
118
+ - ".github/workflows/build.yml"
132
119
  - ".gitignore"
133
120
  - ".pryrc"
134
121
  - ".rspec"
135
122
  - ".rubocop.yml"
136
123
  - ".rubocop_todo.yml"
137
- - ".travis.yml"
138
124
  - Appraisals
139
125
  - CHANGELOG.md
140
126
  - CODE_OF_CONDUCT.md
127
+ - Dockerfile
141
128
  - Gemfile
142
129
  - LICENSE.txt
143
130
  - README.md
@@ -146,10 +133,13 @@ files:
146
133
  - bin/setup
147
134
  - docker-compose.yml
148
135
  - dynamodb-api.gemspec
149
- - gemfiles/aws_sdk_2.gemfile
150
- - gemfiles/aws_sdk_3.gemfile
136
+ - gemfiles/aws_sdk_2_rails_5.gemfile
137
+ - gemfiles/aws_sdk_2_rails_6.gemfile
138
+ - gemfiles/aws_sdk_3_rails_5.gemfile
139
+ - gemfiles/aws_sdk_3_rails_6.gemfile
151
140
  - lib/dynamodb/api.rb
152
141
  - lib/dynamodb/api/adapter.rb
142
+ - lib/dynamodb/api/base.rb
153
143
  - lib/dynamodb/api/config.rb
154
144
  - lib/dynamodb/api/config/options.rb
155
145
  - lib/dynamodb/api/delete/item.rb
@@ -167,6 +157,7 @@ files:
167
157
  - lib/dynamodb/api/relation/query_methods.rb
168
158
  - lib/dynamodb/api/relation/select_clause.rb
169
159
  - lib/dynamodb/api/relation/where_clause.rb
160
+ - lib/dynamodb/api/scan.rb
170
161
  - lib/dynamodb/api/update/attributes.rb
171
162
  - lib/dynamodb/api/update/base.rb
172
163
  - lib/dynamodb/api/update/item.rb
@@ -175,7 +166,7 @@ homepage: https://github.com/walkersumida/dynamodb-api
175
166
  licenses:
176
167
  - MIT
177
168
  metadata: {}
178
- post_install_message:
169
+ post_install_message:
179
170
  rdoc_options: []
180
171
  require_paths:
181
172
  - lib
@@ -190,9 +181,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
190
181
  - !ruby/object:Gem::Version
191
182
  version: '0'
192
183
  requirements: []
193
- rubyforge_project:
194
- rubygems_version: 2.7.6
195
- signing_key:
184
+ rubygems_version: 3.0.3
185
+ signing_key:
196
186
  specification_version: 4
197
187
  summary: aws dynamodb api
198
188
  test_files: []
data/.travis.yml DELETED
@@ -1,19 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- rvm:
4
- - 2.3
5
- - 2.4
6
- - 2.5
7
- gemfile:
8
- - gemfiles/aws_sdk_2.gemfile
9
- - gemfiles/aws_sdk_3.gemfile
10
-
11
- before_install: gem install bundler -v 1.16.2
12
-
13
- before_script:
14
- - docker-compose up -d
15
-
16
- script: bundle exec rubocop --fail-level=C
17
-
18
- after_script:
19
- - docker-compose down