dymos 0.0.2 → 0.0.3

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
  SHA1:
3
- metadata.gz: 408c57bc4b5bc1b6a83e14f53cb1e69071e885b0
4
- data.tar.gz: eaf61ec14a52d888980e478d45aa91180bdd0536
3
+ metadata.gz: 7c0c0a46aa4fd1522baccf359d95557969ef7b84
4
+ data.tar.gz: ce4dddfca46a0a4531633111ff41221821307972
5
5
  SHA512:
6
- metadata.gz: bd4d7dbab18afeba617102abe889732658458aac36b119b5c5f5d7c5b5a0288d44040f27ca437dbfdf079610e3e719280dcdee59f16c3a490cdc374c704382a9
7
- data.tar.gz: b4f0eafab6f9c8346c2d986a189f7038b5cc8f67534289eebb1aa1a1ea45cef7d47b8178529ce8b54ae491195fdc794d17d62ecd3c81240547a4ae31fe883bf0
6
+ metadata.gz: 51158e3ba9bbe24135f76217f825fa11282bfce214f993ed2a92a1b01de54ed0d554137add7b387658dfd287e2dba741dde117a3528fb59012756d17adef4807
7
+ data.tar.gz: 4c654ea7370834f50eff5f83e7562ec77ba68d595a8fa0d26b6cd30898d5c674974f5ff863a45351a58e9d47504dfefef98f8f84709c0dbd7d687fe9aaa33e59
data/.gitignore CHANGED
@@ -13,4 +13,5 @@
13
13
  *.a
14
14
  mkmf.log
15
15
  .idea/
16
- /vendor/bundle
16
+ /vendor/bundle
17
+ .ruby-version
data/.rspec CHANGED
@@ -1,3 +1,2 @@
1
1
  --color
2
- --warnings
3
2
  --require spec_helper
@@ -1,8 +1,9 @@
1
1
  language: ruby
2
2
  cache: bundler
3
- before_script: 'bundle exec fake_dynamo -d .fake_dynamo.db -P .fake_dynamo.pid -D'
4
- script: 'bundle exec rake'
5
- after_script: 'kill `cat .fake_dynamo.pid`'
3
+ before_install:
4
+ - wget http://dynamodb-local.s3-website-us-west-2.amazonaws.com/dynamodb_local_latest
5
+ - tar xfz dynamodb_local_latest
6
+ - java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -inMemory -port 4567 &
6
7
  rvm:
7
8
  - 2.1.0
8
9
  - 2.1.1
data/Rakefile CHANGED
@@ -1,13 +1,7 @@
1
- # -*- encoding: utf-8 -*-
2
- require "bundler/gem_tasks"
3
- require 'rubygems'
4
- require 'rake'
5
- $:.unshift File.join(File.dirname(__FILE__), "lib")
1
+ #!/usr/bin/env rake
2
+ require 'bundler/gem_tasks'
6
3
 
7
- require 'rspec/core'
4
+ # RSpec
8
5
  require 'rspec/core/rake_task'
9
-
10
- task :default => :spec
11
-
12
- desc "Run all specs in spec directory"
13
6
  RSpec::Core::RakeTask.new(:spec)
7
+ task :default => :spec
@@ -1,8 +1,14 @@
1
+ require "dymos/query/attribute"
2
+ require "dymos/query/expect"
3
+ require "dymos/query/builder"
4
+ require "dymos/query/put_item"
5
+ require "dymos/query/update_item"
6
+ require "dymos/query/get_item"
7
+ require "dymos/query/query"
8
+ require "dymos/attribute"
9
+ require "dymos/command"
1
10
  require "dymos/model"
2
11
  require "dymos/version"
3
12
 
4
13
  module Dymos
5
- def self.model
6
- Dymos::Model
7
- end
8
14
  end
@@ -1,5 +1,4 @@
1
1
  module Dymos
2
2
  module Attribute
3
-
4
3
  end
5
4
  end
@@ -0,0 +1,32 @@
1
+ module Dymos
2
+ module Command
3
+
4
+ # @return [PutItem]
5
+ def put
6
+ Dymos::Query::PutItem.new(:put_item, table_name, class_name)
7
+ end
8
+
9
+ # @return [UpdateItem]
10
+ def update
11
+ Dymos::Query::UpdateItem.new(:update_item, table_name, class_name)
12
+ end
13
+
14
+ # @return [GetItem]
15
+ def get
16
+ Dymos::Query::GetItem.new(:get_item, table_name, class_name)
17
+ end
18
+
19
+ # @return [Query]
20
+ def query
21
+ Dymos::Query::Query.new(:query, table_name, class_name)
22
+ end
23
+
24
+ def scan
25
+
26
+ end
27
+
28
+ def describe
29
+
30
+ end
31
+ end
32
+ end
@@ -4,6 +4,7 @@ require 'active_model'
4
4
  module Dymos
5
5
  class Model
6
6
  include ActiveModel::Model
7
+ extend Dymos::Command
7
8
 
8
9
  def initialize(params={})
9
10
  @attributes = {}
@@ -18,6 +19,7 @@ module Dymos
18
19
  end
19
20
 
20
21
  def self.table(name)
22
+ define_singleton_method('table_name') { name }
21
23
  define_method('table_name') { name }
22
24
  end
23
25
 
@@ -89,10 +91,15 @@ module Dymos
89
91
  end
90
92
 
91
93
  def dynamo
92
-
93
94
  @client ||= Aws::DynamoDB::Client.new
94
95
  end
95
96
 
97
+ # @return [String]
98
+ def self.class_name
99
+ self.name
100
+ end
101
+
102
+ # @return [String]
96
103
  def class_name
97
104
  self.class.name
98
105
  end
@@ -0,0 +1,14 @@
1
+ module Dymos
2
+ module Query
3
+ class Attribute
4
+ def initialize(value)
5
+ value =value.to_i if /^[0-9]+$/ =~ value
6
+ @value = value
7
+ end
8
+
9
+ def data
10
+ @value
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,43 @@
1
+ module Dymos
2
+ module Query
3
+ class Builder
4
+ attr_accessor :table_name, :command, :query
5
+
6
+ def initialize(command, table_name=nil, class_name=nil)
7
+ @class_name = class_name
8
+ @command = command
9
+ @table_name = table_name if table_name.present?
10
+ self
11
+ end
12
+
13
+ def query
14
+
15
+ end
16
+
17
+ def execute(client)
18
+ begin
19
+ res = client.send command, query
20
+ rescue Aws::DynamoDB::Errors::ConditionalCheckFailedException
21
+ return false
22
+ end
23
+ if @class_name.present?
24
+ if res.data.respond_to? :items
25
+ res.data[:items].map do |datum|
26
+ obj = Object.const_get(@class_name).new
27
+ obj.attributes = datum
28
+ obj
29
+ end
30
+ elsif res.data.respond_to? :attributes
31
+ return nil if res.attributes.nil?
32
+ obj = Object.const_get(@class_name).new
33
+ obj.attributes = res.attributes
34
+ obj
35
+ end
36
+ else
37
+ res.data
38
+ end
39
+
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,65 @@
1
+ module Dymos
2
+ module Query
3
+ class Expect < Attribute
4
+ def initialize
5
+ end
6
+
7
+ def condition(operator, value)
8
+ if value.present?
9
+ value1, value2 = value.split(" ")
10
+ value1 =value1.to_i if /^[0-9]+$/.match(value1)
11
+ value2 =value2.to_i if /^[0-9]+$/.match(value2)
12
+ @value = value1
13
+ end
14
+
15
+ case operator.to_sym
16
+ when :==, :eq
17
+ @operator = 'EQ'
18
+ when :!=, :nq
19
+ @operator = 'NE'
20
+ when :<=, :le
21
+ @operator = 'LE'
22
+ when :<, :lt
23
+ @operator = 'LT'
24
+ when :>=, :ge
25
+ @operator = 'GE'
26
+ when :>, :gt
27
+ @operator = 'GT'
28
+ when :between
29
+ @operator = 'BETWEEN'
30
+ @value =[value1, value2]
31
+ when :is_null
32
+ @operator = 'NULL'
33
+ when :is_not_null
34
+ @operator = 'NOT_NULL'
35
+ when :contains
36
+ @operator = 'CONTAINS'
37
+ when :not_contains
38
+ @operator = 'NOT_CONTAINS'
39
+ when :begins_with
40
+ @operator = 'BEGINS_WITH'
41
+ else
42
+ raise ArgumentError, '%s is not defined ' % operator
43
+ end
44
+ self
45
+ end
46
+
47
+ def data(is_force_array=false)
48
+ value = super()
49
+ if is_force_array or value.is_a? Array
50
+ data = {
51
+ attribute_value_list: (is_force_array and !(value.is_a? Array)) ? [value] : value,
52
+ comparison_operator: @operator
53
+ }
54
+ else
55
+ data = {}
56
+ data[:value]= value if value.present?
57
+ data[:comparison_operator]= @operator
58
+ end
59
+
60
+ data[:exists] = true if @exists.present?
61
+ data
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,19 @@
1
+ module Dymos
2
+ module Query
3
+ class GetItem < ::Dymos::Query::Builder
4
+
5
+ def key(params)
6
+ @key = params
7
+ self
8
+ end
9
+
10
+ def query
11
+ {
12
+ table_name: @table_name.to_s,
13
+ key: @key,
14
+ consistent_read: true,
15
+ }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,48 @@
1
+ module Dymos
2
+ module Query
3
+ class PutItem < ::Dymos::Query::Builder
4
+
5
+ def item(params)
6
+ @item = params
7
+ self
8
+ end
9
+
10
+ def expected(params)
11
+ @expected = Hash[params.map do |name, expression|
12
+ operator, values = expression.split(' ', 2)
13
+ if values.nil?
14
+ value1 = operator
15
+ [name, ::Dymos::Query::Expect.new.condition(operator, nil).data]
16
+ else
17
+ value1, value2 = values.split(' ')
18
+ if value2.present?
19
+ [name, ::Dymos::Query::Expect.new.condition(operator, values).data]
20
+ else
21
+ [name, ::Dymos::Query::Expect.new.condition(operator, value1).data]
22
+ end
23
+ end
24
+
25
+ end]
26
+ self
27
+ end
28
+
29
+ def query
30
+ data = {
31
+ table_name: @table_name.to_s,
32
+ item: @item,
33
+ return_values: @return_values || 'ALL_OLD',
34
+ # return_consumed_capacity: @return_consumed_capacity || 'TOTAL',
35
+ # return_item_collection_metrics: @return_item_collection_metrics || 'SIZE',
36
+ }
37
+
38
+ if @expected.present?
39
+ data[:expected] = @expected
40
+ if @expected.size > 1
41
+ data[:conditional_operator] = @conditional_operator || 'AND'
42
+ end
43
+ end
44
+ data
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,38 @@
1
+ module Dymos
2
+ module Query
3
+ class Query < ::Dymos::Query::Builder
4
+
5
+ def key_conditions(params)
6
+ @key = Hash[params.map do |name, expression|
7
+ operator, values = expression.split(' ', 2)
8
+ if values.nil?
9
+ [name, ::Dymos::Query::Expect.new.condition(operator, nil).data(true)]
10
+ else
11
+ value1, value2 = values.split(' ')
12
+ if value2.present?
13
+ [name, ::Dymos::Query::Expect.new.condition(operator, values).data(true)]
14
+ else
15
+ [name, ::Dymos::Query::Expect.new.condition(operator, value1).data(true)]
16
+ end
17
+ end
18
+
19
+ end]
20
+ self
21
+ end
22
+
23
+ def index_name(name)
24
+ @index_name =name
25
+ self
26
+ end
27
+
28
+ def query
29
+ {
30
+ table_name: @table_name.to_s,
31
+ index_name: @index_name.to_s,
32
+ key_conditions: @key,
33
+ consistent_read: false
34
+ }
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,72 @@
1
+ module Dymos
2
+ module Query
3
+ class UpdateItem < ::Dymos::Query::Builder
4
+
5
+ # @param [String] name
6
+ # @return [self]
7
+ def key(name)
8
+ @key = name
9
+ self
10
+ end
11
+
12
+ # @param [Hash] param
13
+ # @param [String] action
14
+ # @return [self]
15
+ def attribute_updates(param, action="put")
16
+ @attribute_updates||={}
17
+ param.each { |key, value|
18
+ @attribute_updates[key] = {
19
+ value: value,
20
+ action: action.upcase
21
+ }
22
+ }
23
+ self
24
+ end
25
+
26
+ # @param [Hash] params
27
+ # @return [self]
28
+ def expected(params)
29
+ @expected = Hash[params.map do |name, expression|
30
+ operator, values = expression.split(' ', 2)
31
+ if values.nil?
32
+ [name, ::Dymos::Query::Expect.new.condition(operator, nil).data]
33
+ else
34
+ value1, value2 = values.split(' ')
35
+ if value2.present?
36
+ [name, ::Dymos::Query::Expect.new.condition(operator, values).data]
37
+ else
38
+ [name, ::Dymos::Query::Expect.new.condition(operator, value1).data]
39
+ end
40
+ end
41
+
42
+ end]
43
+ self
44
+ end
45
+
46
+ # @param [String] value
47
+ # @return [self]
48
+ def return_values(value)
49
+ @return_values = value.upcase
50
+ self
51
+ end
52
+
53
+ # @return [Hash]
54
+ def query
55
+ data = {
56
+ table_name: @table_name.to_s,
57
+ key: @key,
58
+ attribute_updates: @attribute_updates,
59
+ return_values: @return_values || 'ALL_NEW',
60
+ }
61
+
62
+ if @expected.present?
63
+ data[:expected] = @expected
64
+ if @expected.size > 1
65
+ data[:conditional_operator] = @conditional_operator || 'AND'
66
+ end
67
+ end
68
+ data
69
+ end
70
+ end
71
+ end
72
+ end
@@ -1,3 +1,3 @@
1
1
  module Dymos
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -66,12 +66,6 @@ describe Dymos::Model do
66
66
 
67
67
  # let(:model) { Dummy.new }
68
68
 
69
- describe Dymos do
70
- it "dymos.model" do
71
- expect(Dymos::model.name).to eq('Dymos::Model')
72
- end
73
- end
74
-
75
69
  describe :new do
76
70
 
77
71
  describe :field do
@@ -0,0 +1,15 @@
1
+ describe Dymos::Query::Attribute do
2
+ describe :new do
3
+ describe "DynamoDBClientで取り扱う値の形式に変換" do
4
+ it "文字列" do
5
+ attribute = Dymos::Query::Attribute.new('10')
6
+ expect(attribute.data).to eq(10)
7
+ end
8
+ it "数値に変換可能な文字列はintになる" do
9
+ attribute = Dymos::Query::Attribute.new('10')
10
+ expect(attribute.data).to eq(10)
11
+ end
12
+ end
13
+ end
14
+ end
15
+
@@ -0,0 +1,65 @@
1
+ describe Dymos::Query::Builder do
2
+ before :all do
3
+ Aws.config[:region] = 'us-west-1'
4
+ Aws.config[:endpoint] = 'http://localhost:4567'
5
+ Aws.config[:access_key_id] = 'XXX'
6
+ Aws.config[:secret_access_key] = 'XXX'
7
+ end
8
+
9
+ describe :list_tables do
10
+ let(:query) { Dymos::Query::Builder.new(:list_tables) }
11
+
12
+ it "command" do
13
+ expect(query.command).to eq(:list_tables)
14
+ end
15
+
16
+ it "execute" do
17
+ client = Aws::DynamoDB::Client.new
18
+ expect(query.execute(client).methods.include? :table_names).to eq(true)
19
+ end
20
+ end
21
+
22
+ describe :put_item do
23
+ before :all do
24
+ client = Aws::DynamoDB::Client.new
25
+ # client.delete_table(table_name: 'test_put_item') if client.list_tables[:table_names].include?('test_put_item')
26
+ # client.create_table(
27
+ # table_name: 'test_put_item',
28
+ # attribute_definitions: [
29
+ # {attribute_name: 'id', attribute_type: 'S'}
30
+ # ],
31
+ # key_schema: [
32
+ # {attribute_name: 'id', key_type: 'HASH'}
33
+ # ],
34
+ # provisioned_throughput: {
35
+ # read_capacity_units: 1,
36
+ # write_capacity_units: 1,
37
+ # })
38
+ # client.put_item(table_name: 'test_put_item', item: {id: 'hoge', name: '太郎'})
39
+ # client.put_item(table_name: 'test_put_item', item: {id: 'fuga', name: '次郎'})
40
+ # client.put_item(table_name: 'test_put_item', item: {id: 'piyo', name: '三郎'})
41
+ end
42
+ let(:client) { Aws::DynamoDB::Client.new }
43
+ let(:query) { Dymos::Query::Builder.new(:put_item, "test_put_item") }
44
+
45
+ it 'put' do
46
+ # User.put.item(id:"hoge",name:"太郎").expected(id:'hoge')
47
+ # query.query = {
48
+ # table_name: query.table_name,
49
+ # item: {
50
+ # id: "hoge",
51
+ # name: "太郎2",
52
+ # },
53
+ # expected: {
54
+ # id: Dymos::Query::Expect.new(:s).condition(:==, 'hoge').data,
55
+ # name: Dymos::Query::Expect.new(:s).condition(:==, '太郎2').data,
56
+ # },
57
+ # return_values: "ALL_OLD",
58
+ # }
59
+ # result = query.execute client
60
+ # expect(result).to eq('hoge')
61
+ end
62
+
63
+ end
64
+ end
65
+
@@ -0,0 +1,5 @@
1
+ describe Dymos::Query::Expect do
2
+ describe :new do
3
+ end
4
+ end
5
+
@@ -0,0 +1,55 @@
1
+ describe Dymos::Query::GetItem do
2
+ before :all do
3
+ Aws.config[:region] = 'us-west-1'
4
+ Aws.config[:endpoint] = 'http://localhost:4567'
5
+ Aws.config[:access_key_id] = 'XXX'
6
+ Aws.config[:secret_access_key] = 'XXX'
7
+
8
+ client = Aws::DynamoDB::Client.new
9
+ client.delete_table(table_name: 'test_get_item') if client.list_tables[:table_names].include?('test_get_item')
10
+ client.create_table(
11
+ table_name: 'test_get_item',
12
+ attribute_definitions: [
13
+ {attribute_name: 'id', attribute_type: 'S'},
14
+ {attribute_name: 'category_id', attribute_type: 'N'},
15
+ ],
16
+ key_schema: [
17
+ {attribute_name: 'id', key_type: 'HASH'},
18
+ {attribute_name: 'category_id', key_type: 'RANGE'}
19
+ ],
20
+ provisioned_throughput: {
21
+ read_capacity_units: 1,
22
+ write_capacity_units: 1,
23
+ })
24
+ client.put_item(table_name: 'test_get_item', item: {id: 'hoge', category_id: 0, name: '太郎'})
25
+ client.put_item(table_name: 'test_get_item', item: {id: 'hoge', category_id: 1})
26
+
27
+ class TestItem < Dymos::Model
28
+ table :test_get_item
29
+ field :id, :string
30
+ end
31
+ end
32
+
33
+ let(:client) { Aws::DynamoDB::Client.new }
34
+ describe :put_item do
35
+ describe "クエリ生成" do
36
+ it "追加のみ" do
37
+ query = TestItem.get.key(id: 'hoge', category_id: 1)
38
+ expect(query.query).to eq({
39
+ table_name: "test_get_item",
40
+ key: {id: "hoge", category_id: 1},
41
+ consistent_read: true,
42
+ })
43
+ # p client.scan(table_name: "test_get_item")
44
+ # res = query.execute client
45
+ # p res
46
+
47
+
48
+ # expect(res).to eq({})
49
+ # p client.scan(table_name:"test_get_item")
50
+ end
51
+
52
+ end
53
+ end
54
+ end
55
+
@@ -0,0 +1,316 @@
1
+ describe Dymos::Query::PutItem do
2
+ before :all do
3
+ Aws.config[:region] = 'us-west-1'
4
+ Aws.config[:endpoint] = 'http://localhost:4567'
5
+ Aws.config[:access_key_id] = 'XXX'
6
+ Aws.config[:secret_access_key] = 'XXX'
7
+
8
+ client = Aws::DynamoDB::Client.new
9
+ client.delete_table(table_name: 'test_put_item') if client.list_tables[:table_names].include?('test_put_item')
10
+ client.create_table(
11
+ table_name: 'test_put_item',
12
+ attribute_definitions: [
13
+ {attribute_name: 'id', attribute_type: 'S'},
14
+ ],
15
+ key_schema: [
16
+ {attribute_name: 'id', key_type: 'HASH'}
17
+ ],
18
+ provisioned_throughput: {
19
+ read_capacity_units: 1,
20
+ write_capacity_units: 1,
21
+ })
22
+ client.put_item(table_name: 'test_put_item', item: {id: 'hoge', name: '太郎'})
23
+ client.put_item(table_name: 'test_put_item', item: {id: 'fuga', category_id: 1})
24
+
25
+ class TestItem < Dymos::Model
26
+ table :test_put_item
27
+ field :id, :string
28
+ end
29
+ end
30
+
31
+ let(:client) { Aws::DynamoDB::Client.new }
32
+ describe :put_item do
33
+ describe "クエリ生成" do
34
+ it "追加のみ" do
35
+ query = TestItem.put.item(id: "foo", name: "John")
36
+ expect(query.query).to eq({
37
+ table_name: "test_put_item",
38
+ item: {id: "foo", name: "John"},
39
+ return_values: "ALL_OLD",
40
+ })
41
+ end
42
+
43
+ end
44
+ it "条件なしput_item実行 追加時はattributesがnilになる" do
45
+ query = TestItem.put.item(id: "foo", name: "John")
46
+ result = query.execute client
47
+ expect(result).to eq(nil)
48
+ end
49
+
50
+ # it "条件ありput_item" do
51
+ # query = TestPutItem.put.item(id: "hoge", name: "次郎").expected(name: "== 太郎")
52
+ # expect(query.query).to eq({
53
+ # table_name: "test_put_item",
54
+ # item: {id: "hoge", name: "次郎"},
55
+ # :expected => {:name => {:value => "太郎", :comparison_operator => "EQ"}},
56
+ # return_values: "ALL_OLD",
57
+ # })
58
+ #
59
+ # query = TestPutItem.put.item(id: "hoge", name: "次郎").expected(category_id: "== 1")
60
+ # expect(query.query).to eq({
61
+ # table_name: "test_put_item",
62
+ # item: {id: "hoge", name: "次郎"},
63
+ # :expected => {:category_id => {:value => 1, :comparison_operator => "EQ"}},
64
+ # return_values: "ALL_OLD",
65
+ # })
66
+ #
67
+ # query = TestPutItem.put.item(id: "hoge", name: "次郎").expected(category_id: "between 0 2")
68
+ # expect(query.query).to eq({
69
+ # table_name: "test_put_item",
70
+ # item: {id: "hoge", name: "次郎"},
71
+ # :expected => {:category_id => {:attribute_value_list => [0, 2], :comparison_operator => "BETWEEN"}},
72
+ # return_values: "ALL_OLD",
73
+ # })
74
+ # end
75
+
76
+ # it "条件ありput_item実行 成功すると古いデータを返す" do
77
+ # query = TestPutItem.put.item(id: "hoge", name: "次郎").expected(name: "== 太郎")
78
+ # result = query.execute client
79
+ # expect(result.attributes).to eq({id: "hoge", name: "太郎"})
80
+ # end
81
+
82
+ describe "条件指定" do
83
+ it "undefined operator" do
84
+ expect{TestItem.put.item(id: "fuga", category_id: 1).expected(category_id: "= 1")}.to raise_error(ArgumentError)
85
+ end
86
+
87
+ describe :== do
88
+ let(:query) { TestItem.put.item(id: "fuga", category_id: 1).expected(category_id: "== 1") }
89
+ it :query do
90
+ expect(query.query).to eq(table_name: "test_put_item",
91
+ item: {id: "fuga", category_id: 1},
92
+ expected: {:category_id => {:value => 1, :comparison_operator => "EQ"}},
93
+ return_values: "ALL_OLD")
94
+ end
95
+ it :execute do
96
+ result = query.execute client
97
+ expect(result.attributes).to eq({id: "fuga", category_id: 1})
98
+ end
99
+ it :error do
100
+ query = TestItem.put.item(id: "fuga", category_id: 1).expected(category_id: "== 2")
101
+ expect(query.execute(client)).to eq(false)
102
+ end
103
+ end
104
+
105
+ describe :!= do
106
+ let(:query) { TestItem.put.item(id: "fuga", category_id: 1).expected(category_id: "!= 0") }
107
+ it :query do
108
+ expect(query.query).to eq(table_name: "test_put_item",
109
+ item: {id: "fuga", category_id: 1},
110
+ expected: {:category_id => {:value => 0, :comparison_operator => "NE"}},
111
+ return_values: "ALL_OLD")
112
+ end
113
+ it :execute do
114
+ result = query.execute client
115
+ expect(result.attributes).to eq({id: "fuga", category_id: 1})
116
+ end
117
+ it :error do
118
+ query = TestItem.put.item(id: "fuga", category_id: 1).expected(category_id: "== 2")
119
+ expect(query.execute(client)).to eq(false)
120
+ end
121
+ end
122
+
123
+ describe :> do
124
+ let(:query) { TestItem.put.item(id: "fuga", category_id: 1).expected(category_id: "> 0") }
125
+ it :query do
126
+ expect(query.query).to eq(table_name: "test_put_item",
127
+ item: {id: "fuga", category_id: 1},
128
+ expected: {:category_id => {:value => 0, :comparison_operator => "GT"}},
129
+ return_values: "ALL_OLD")
130
+ end
131
+ it :execute do
132
+ result = query.execute client
133
+ expect(result.attributes).to eq({id: "fuga", category_id: 1})
134
+ end
135
+ it :error do
136
+ query = TestItem.put.item(id: "fuga", category_id: 1).expected(category_id: "> 2")
137
+ expect(query.execute(client)).to eq(false)
138
+ end
139
+ end
140
+
141
+ describe :>= do
142
+ let(:query) { TestItem.put.item(id: "fuga", category_id: 1).expected(category_id: ">= 1") }
143
+ it :query do
144
+ expect(query.query).to eq(table_name: "test_put_item",
145
+ item: {id: "fuga", category_id: 1},
146
+ expected: {:category_id => {:value => 1, :comparison_operator => "GE"}},
147
+ return_values: "ALL_OLD")
148
+ end
149
+ it :execute do
150
+ result = query.execute client
151
+ expect(result.attributes).to eq({id: "fuga", category_id: 1})
152
+ end
153
+ it :error do
154
+ query = TestItem.put.item(id: "fuga", category_id: 1).expected(category_id: "> 2")
155
+ expect(query.execute(client)).to eq(false)
156
+ end
157
+ end
158
+
159
+ describe :< do
160
+ let(:query) { TestItem.put.item(id: "fuga", category_id: 1).expected(category_id: "< 2") }
161
+ it :query do
162
+ expect(query.query).to eq(table_name: "test_put_item",
163
+ item: {id: "fuga", category_id: 1},
164
+ expected: {:category_id => {:value => 2, :comparison_operator => "LT"}},
165
+ return_values: "ALL_OLD")
166
+ end
167
+ it :execute do
168
+ result = query.execute client
169
+ expect(result.attributes).to eq({id: "fuga", category_id: 1})
170
+ end
171
+ it :error do
172
+ query = TestItem.put.item(id: "fuga", category_id: 1).expected(category_id: "< 0")
173
+ expect(query.execute(client)).to eq(false)
174
+ end
175
+ end
176
+
177
+ describe :<= do
178
+ let(:query) { TestItem.put.item(id: "fuga", category_id: 1).expected(category_id: "<= 1") }
179
+ it :query do
180
+ expect(query.query).to eq(table_name: "test_put_item",
181
+ item: {id: "fuga", category_id: 1},
182
+ expected: {:category_id => {:value => 1, :comparison_operator => "LE"}},
183
+ return_values: "ALL_OLD")
184
+ end
185
+ it :execute do
186
+ result = query.execute client
187
+ expect(result.attributes).to eq({id: "fuga", category_id: 1})
188
+ end
189
+ it :error do
190
+ query = TestItem.put.item(id: "fuga", category_id: 1).expected(category_id: "<= 0")
191
+ expect(query.execute(client)).to eq(false)
192
+ end
193
+ end
194
+
195
+ describe :between do
196
+ let(:query) { TestItem.put.item(id: "fuga", category_id: 1).expected(category_id: "between 1 2") }
197
+ it :query do
198
+ expect(query.query).to eq(table_name: "test_put_item",
199
+ item: {id: "fuga", category_id: 1},
200
+ expected: {:category_id => {:attribute_value_list => [1, 2], :comparison_operator => "BETWEEN"}},
201
+ return_values: "ALL_OLD")
202
+ end
203
+ it :execute do
204
+ result = query.execute client
205
+ expect(result.attributes).to eq({id: "fuga", category_id: 1})
206
+ end
207
+ it :error do
208
+ query = TestItem.put.item(id: "fuga", category_id: 1).expected(category_id: "between 2 3")
209
+ expect(query.execute(client)).to eq(false)
210
+ end
211
+ end
212
+
213
+ describe :contain do
214
+ let(:query) { TestItem.put.item(id: "fuga", category_id: 1).expected(id: "contains uga") }
215
+ it :query do
216
+ expect(query.query).to eq(table_name: "test_put_item",
217
+ item: {id: "fuga", category_id: 1},
218
+ expected: {:id => {:value => "uga", :comparison_operator => "CONTAINS"}},
219
+ return_values: "ALL_OLD")
220
+ end
221
+ it :execute do
222
+ result = query.execute client
223
+ expect(result.attributes).to eq({id: "fuga", category_id: 1})
224
+ end
225
+ it :error do
226
+ query = TestItem.put.item(id: "fuga", category_id: 1).expected(id: "contains ppp")
227
+ expect(query.execute(client)).to eq(false)
228
+ end
229
+ end
230
+
231
+ describe :not_contain do
232
+ let(:query) { TestItem.put.item(id: "fuga", category_id: 1).expected(id: "not_contains ppp") }
233
+ it :query do
234
+ expect(query.query).to eq(table_name: "test_put_item",
235
+ item: {id: "fuga", category_id: 1},
236
+ expected: {:id => {:value => "ppp", :comparison_operator => "NOT_CONTAINS"}},
237
+ return_values: "ALL_OLD")
238
+ end
239
+ it :execute do
240
+ result = query.execute client
241
+ expect(result.attributes).to eq({id: "fuga", category_id: 1})
242
+ end
243
+ it :error do
244
+ query = TestItem.put.item(id: "fuga", category_id: 1).expected(id: "not_contains uga")
245
+ expect(query.execute(client)).to eq(false)
246
+ end
247
+ end
248
+
249
+ describe :begins_with do
250
+ let(:query) { TestItem.put.item(id: "fuga", category_id: 1).expected(id: "begins_with fug") }
251
+ it :query do
252
+ expect(query.query).to eq(table_name: "test_put_item",
253
+ item: {id: "fuga", category_id: 1},
254
+ expected: {:id => {:value => "fug", :comparison_operator => "BEGINS_WITH"}},
255
+ return_values: "ALL_OLD")
256
+ end
257
+ it :execute do
258
+ result = query.execute client
259
+ expect(result.attributes).to eq({id: "fuga", category_id: 1})
260
+ end
261
+ it :error do
262
+ query = TestItem.put.item(id: "fuga", category_id: 1).expected(id: "begins_with uga")
263
+ expect(query.execute(client)).to eq(false)
264
+ end
265
+ end
266
+
267
+ describe :is_null do
268
+ let(:query) { TestItem.put.item(id: "fuga", category_id: 1).expected(bar: "is_null") }
269
+ it :query do
270
+ expect(query.query).to eq(table_name: "test_put_item",
271
+ item: {id: "fuga", category_id: 1},
272
+ expected: {:bar => {:comparison_operator => "NULL"}},
273
+ return_values: "ALL_OLD")
274
+ end
275
+ it :execute do
276
+ result = query.execute client
277
+ expect(result.attributes).to eq({id: "fuga", category_id: 1})
278
+ end
279
+ it :error do
280
+ query = TestItem.put.item(id: "fuga", category_id: 1).expected(id: "is_null")
281
+ expect(query.execute(client)).to eq(false)
282
+ end
283
+ end
284
+
285
+ describe :is_not_null do
286
+ let(:query) { TestItem.put.item(id: "fuga", category_id: 1).expected(id: "is_not_null") }
287
+ it :query do
288
+ expect(query.query).to eq(table_name: "test_put_item",
289
+ item: {id: "fuga", category_id: 1},
290
+ expected: {:id => {:comparison_operator => "NOT_NULL"}},
291
+ return_values: "ALL_OLD")
292
+ end
293
+ it :execute do
294
+ result = query.execute client
295
+ expect(result.attributes).to eq({id: "fuga", category_id: 1})
296
+ end
297
+ it :error do
298
+ query = TestItem.put.item(id: "fuga", category_id: 1).expected(bar: "is_not_null")
299
+ expect(query.execute(client)).to eq(false)
300
+ end
301
+ end
302
+ end
303
+ #
304
+ # it :< do
305
+ # query = TestPutItem.put.item(id: "fuga", category_id: 1).expected(category_id: "< 2")
306
+ # result = query.execute client
307
+ # expect(result.attributes).to eq({id: "fuga", category_id: 1})
308
+ # end
309
+ # it :between do
310
+ # query = TestPutItem.put.item(id: "fuga", category_id: 1).expected(category_id: "between 1 2")
311
+ # result = query.execute client
312
+ # expect(result.attributes).to eq({id: "fuga", category_id: 1})
313
+ # end
314
+ end
315
+ end
316
+
@@ -0,0 +1,90 @@
1
+ describe Dymos::Query::Query do
2
+ before :all do
3
+ Aws.config[:region] = 'us-west-1'
4
+ Aws.config[:endpoint] = 'http://localhost:4567'
5
+ Aws.config[:access_key_id] = 'XXX'
6
+ Aws.config[:secret_access_key] = 'XXX'
7
+
8
+ client = Aws::DynamoDB::Client.new
9
+ client.delete_table(table_name: 'test_query_item') if client.list_tables[:table_names].include?('test_query_item')
10
+ client.create_table(
11
+ table_name: 'test_query_item',
12
+ attribute_definitions: [
13
+ {attribute_name: 'id', attribute_type: 'S'},
14
+ {attribute_name: 'category_id', attribute_type: 'N'},
15
+ {attribute_name: 'other_id', attribute_type: 'N'},
16
+ ],
17
+ key_schema: [
18
+ {attribute_name: 'id', key_type: 'HASH'},
19
+ {attribute_name: 'category_id', key_type: 'RANGE'}
20
+ ],
21
+ global_secondary_indexes: [
22
+ {
23
+ index_name: "index_other_id",
24
+ key_schema: [
25
+ {attribute_name: "id", key_type: "HASH"},
26
+ {attribute_name: "other_id", key_type: "RANGE"},
27
+ ],
28
+ projection: {
29
+ projection_type: "ALL",
30
+ },
31
+ provisioned_throughput: {
32
+ read_capacity_units: 1,
33
+ write_capacity_units: 1,
34
+ },
35
+ },
36
+ ],
37
+ provisioned_throughput: {
38
+ read_capacity_units: 1,
39
+ write_capacity_units: 1,
40
+ })
41
+ client.put_item(table_name: 'test_query_item', item: {id: 'hoge', category_id: 0, other_id: 1})
42
+ client.put_item(table_name: 'test_query_item', item: {id: 'hoge', category_id: 1, other_id: 2})
43
+ client.put_item(table_name: 'test_query_item', item: {id: 'hoge', category_id: 2, other_id: 3})
44
+ client.put_item(table_name: 'test_query_item', item: {id: 'hoge', category_id: 3, other_id: 4})
45
+ client.put_item(table_name: 'test_query_item', item: {id: 'hoge', category_id: 4, other_id: 5})
46
+ client.put_item(table_name: 'test_query_item', item: {id: 'hoge', category_id: 5, other_id: 6})
47
+
48
+ class TestItem < Dymos::Model
49
+ table :test_query_item
50
+ field :id, :string
51
+ end
52
+ end
53
+
54
+ let(:client) { Aws::DynamoDB::Client.new }
55
+ describe :put_item do
56
+ describe "クエリ生成" do
57
+ describe "グローバルセカンダリインデックスを利用した検索" do
58
+ let(:query) {
59
+ TestItem.query.index_name(:index_other_id).key_conditions(
60
+ id: "== hoge",
61
+ other_id: "between 1 3"
62
+ )
63
+ }
64
+ it :query do
65
+ expect(query.query).to eq(
66
+ table_name: 'test_query_item',
67
+ index_name: 'index_other_id',
68
+ key_conditions: {
69
+ id: {
70
+ attribute_value_list: ["hoge"],
71
+ comparison_operator: "EQ"
72
+ },
73
+ other_id: {
74
+ attribute_value_list: [1, 3],
75
+ comparison_operator: "BETWEEN"
76
+ }},
77
+ consistent_read: false,
78
+ )
79
+ end
80
+ it :execute do
81
+ res = query.execute client
82
+ expect(res.size).to eq(3)
83
+ end
84
+
85
+
86
+ end
87
+ end
88
+ end
89
+ end
90
+
@@ -0,0 +1,119 @@
1
+ describe Dymos::Query::UpdateItem do
2
+ before :all do
3
+ Aws.config[:region] = 'us-west-1'
4
+ Aws.config[:endpoint] = 'http://localhost:4567'
5
+ Aws.config[:access_key_id] = 'XXX'
6
+ Aws.config[:secret_access_key] = 'XXX'
7
+
8
+ client = Aws::DynamoDB::Client.new
9
+ client.delete_table(table_name: 'test_update_item') if client.list_tables[:table_names].include?('test_update_item')
10
+ client.create_table(
11
+ table_name: 'test_update_item',
12
+ attribute_definitions: [
13
+ {attribute_name: 'id', attribute_type: 'S'},
14
+ ],
15
+ key_schema: [
16
+ {attribute_name: 'id', key_type: 'HASH'}
17
+ ],
18
+ provisioned_throughput: {
19
+ read_capacity_units: 1,
20
+ write_capacity_units: 1,
21
+ })
22
+ client.put_item(table_name: 'test_update_item', item: {id: 'hoge', name: '太郎'})
23
+ client.put_item(table_name: 'test_update_item', item: {id: 'fuga', count: 0})
24
+ client.put_item(table_name: 'test_update_item', item: {id: 'poyo', name: '可奈'})
25
+ client.put_item(table_name: 'test_update_item', item: {id: 'piyo', name: '杏奈', count: 10})
26
+
27
+ class TestItem < Dymos::Model
28
+ table :test_update_item
29
+ field :id, :string
30
+ field :name, :string
31
+ field :count, :string
32
+ end
33
+ end
34
+
35
+ let(:client) { Aws::DynamoDB::Client.new }
36
+ describe :put_item do
37
+ describe "クエリ生成" do
38
+ describe "新しいアイテムを追加" do
39
+ let(:query) { TestItem.update.key(id: "foo").attribute_updates({name: "Sam"}, 'PUT') }
40
+ it :query do
41
+ expect(query.query).to eq({
42
+ table_name: "test_update_item",
43
+ key: {id: "foo"},
44
+ attribute_updates: {name: {value: "Sam", action: "PUT"}},
45
+ return_values: "ALL_NEW",
46
+ })
47
+ end
48
+ it "成功すると新しいアイテムを返す" do
49
+ res = query.execute client
50
+ expect(res.id).to eq("foo")
51
+ end
52
+ end
53
+
54
+ describe "既存のアイテムを更新" do
55
+ describe "return_values :ALL_OLD" do
56
+ it "更新した場合は更新前のアイテムを返す" do
57
+ query = TestItem.update.key(id: "hoge").attribute_updates({name: "次郎"}, 'PUT').return_values(:ALL_OLD)
58
+ res = query.execute client
59
+ expect(res.name).to eq("太郎")
60
+ end
61
+ it "追加した場合はnilを返す" do
62
+ query = TestItem.update.key(id: "bar").attribute_updates({name: "Sam"}, 'PUT').return_values(:ALL_OLD)
63
+ res = query.execute client
64
+ expect(res).to eq(nil)
65
+ end
66
+ end
67
+ it "アイテムに加算する" do
68
+ query = TestItem.update.key(id: "fuga").attribute_updates({count: 1}, 'add')
69
+ res = query.execute client
70
+ expect(res.count).to eq(1)
71
+ end
72
+
73
+ describe "条件付き更新" do
74
+ describe :== do
75
+ let(:query) { TestItem.update.key(id: "poyo").attribute_updates({name: "志保"}, 'PUT').expected(name: "== 可奈") }
76
+
77
+ it :query do
78
+ expect(query.query).to eq({
79
+ table_name: "test_update_item",
80
+ key: {id: "poyo"},
81
+ attribute_updates: {name: {value: "志保", action: "PUT"}},
82
+ expected: ({name: {value: "可奈", comparison_operator: "EQ"}}),
83
+ return_values: "ALL_NEW",
84
+ })
85
+ end
86
+ it "成功すると新しいアイテムを返す" do
87
+ res = query.execute client
88
+ expect(res.name).to eq("志保")
89
+ end
90
+ end
91
+ describe "複数条件" do
92
+ let(:query) { TestItem.update.key(id: "piyo").attribute_updates({name: "百合子"}, 'PUT')
93
+ .expected(count: "between 9 12", name: "== 杏奈", hoge:"is_null")}
94
+
95
+ it :query do
96
+ expect(query.query).to eq({
97
+ table_name: "test_update_item",
98
+ key: {id: "piyo"},
99
+ attribute_updates: {name: {value: "百合子", action: "PUT"}},
100
+ expected: ({
101
+ name: {value: "杏奈", comparison_operator: "EQ"},
102
+ count: {attribute_value_list: [9, 12], comparison_operator: "BETWEEN"},
103
+ hoge: {comparison_operator: "NULL"},
104
+ }),
105
+ return_values: "ALL_NEW",
106
+ conditional_operator: "AND"
107
+ })
108
+ end
109
+ it "成功すると新しいアイテムを返す" do
110
+ res = query.execute client
111
+ expect(res.name).to eq("百合子")
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+
@@ -1,81 +1,7 @@
1
1
  require 'coveralls'
2
2
  Coveralls.wear!
3
- # This file was generated by the `rspec --init` command. Conventionally, all
4
- # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
5
- # The generated `.rspec` file contains `--require spec_helper` which will cause this
6
- # file to always be loaded, without a need to explicitly require it in any files.
7
- #
8
- # Given that it is always loaded, you are encouraged to keep this file as
9
- # light-weight as possible. Requiring heavyweight dependencies from this file
10
- # will add to the boot time of your test suite on EVERY test run, even for an
11
- # individual file that may not need all of that loaded. Instead, make a
12
- # separate helper file that requires this one and then use it only in the specs
13
- # that actually need it.
14
- #
15
- # The `.rspec` file also contains a few flags that are not defaults but that
16
- # users commonly want.
17
- #
18
- # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
19
- Dir[File.join(File.dirname(__FILE__), "..", "lib", "**/*.rb")].each{|f| require f }
20
3
 
4
+ require 'rubygems'
5
+ require 'bundler/setup'
21
6
 
22
- RSpec.configure do |config|
23
- # The settings below are suggested to provide a good initial experience
24
- # with RSpec, but feel free to customize to your heart's content.
25
- # These two settings work together to allow you to limit a spec run
26
- # to individual examples or groups you care about by tagging them with
27
- # `:focus` metadata. When nothing is tagged with `:focus`, all examples
28
- # get run.
29
- config.filter_run :focus
30
- config.run_all_when_everything_filtered = true
31
-
32
- # Many RSpec users commonly either run the entire suite or an individual
33
- # file, and it's useful to allow more verbose output when running an
34
- # individual spec file.
35
- if config.files_to_run.one?
36
- # Use the documentation formatter for detailed output,
37
- # unless a formatter has already been configured
38
- # (e.g. via a command-line flag).
39
- config.default_formatter = 'doc'
40
- end
41
-
42
- # Print the 10 slowest examples and example groups at the
43
- # end of the spec run, to help surface which specs are running
44
- # particularly slow.
45
- config.profile_examples = 10
46
-
47
- # Run specs in random order to surface order dependencies. If you find an
48
- # order dependency and want to debug it, you can fix the order by providing
49
- # the seed, which is printed after each run.
50
- # --seed 1234
51
- config.order = :random
52
-
53
- # Seed global randomization in this process using the `--seed` CLI option.
54
- # Setting this allows you to use `--seed` to deterministically reproduce
55
- # test failures related to randomization by passing the same `--seed` value
56
- # as the one that triggered the failure.
57
- Kernel.srand config.seed
58
-
59
- # rspec-expectations config goes here. You can use an alternate
60
- # assertion/expectation library such as wrong or the stdlib/minitest
61
- # assertions if you prefer.
62
- config.expect_with :rspec do |expectations|
63
- # Enable only the newer, non-monkey-patching expect syntax.
64
- # For more details, see:
65
- # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
66
- expectations.syntax = :expect
67
- end
68
-
69
- # rspec-mocks config goes here. You can use an alternate test double
70
- # library (such as bogus or mocha) by changing the `mock_with` option here.
71
- config.mock_with :rspec do |mocks|
72
- # Enable only the newer, non-monkey-patching expect syntax.
73
- # For more details, see:
74
- # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
75
- mocks.syntax = :expect
76
-
77
- # Prevents you from mocking or stubbing a method that does not exist on
78
- # a real object. This is generally recommended.
79
- mocks.verify_partial_doubles = true
80
- end
81
- end
7
+ require 'dymos'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dymos
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - hoshina85
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-21 00:00:00.000000000 Z
11
+ date: 2014-09-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -125,9 +125,24 @@ files:
125
125
  - dymos.gemspec
126
126
  - lib/dymos.rb
127
127
  - lib/dymos/attribute.rb
128
+ - lib/dymos/command.rb
128
129
  - lib/dymos/model.rb
130
+ - lib/dymos/query/attribute.rb
131
+ - lib/dymos/query/builder.rb
132
+ - lib/dymos/query/expect.rb
133
+ - lib/dymos/query/get_item.rb
134
+ - lib/dymos/query/put_item.rb
135
+ - lib/dymos/query/query.rb
136
+ - lib/dymos/query/update_item.rb
129
137
  - lib/dymos/version.rb
130
138
  - spec/lib/dymos/model_spec.rb
139
+ - spec/lib/dymos/query/attribute_spec.rb
140
+ - spec/lib/dymos/query/builder_spec.rb
141
+ - spec/lib/dymos/query/expect_spec.rb
142
+ - spec/lib/dymos/query/get_item_spec.rb
143
+ - spec/lib/dymos/query/put_item_spec.rb
144
+ - spec/lib/dymos/query/query_spec.rb
145
+ - spec/lib/dymos/query/update_item_spec.rb
131
146
  - spec/spec_helper.rb
132
147
  homepage: ''
133
148
  licenses:
@@ -155,4 +170,11 @@ specification_version: 4
155
170
  summary: aws-sdk-core-ruby dynamodb client wrapper
156
171
  test_files:
157
172
  - spec/lib/dymos/model_spec.rb
173
+ - spec/lib/dymos/query/attribute_spec.rb
174
+ - spec/lib/dymos/query/builder_spec.rb
175
+ - spec/lib/dymos/query/expect_spec.rb
176
+ - spec/lib/dymos/query/get_item_spec.rb
177
+ - spec/lib/dymos/query/put_item_spec.rb
178
+ - spec/lib/dymos/query/query_spec.rb
179
+ - spec/lib/dymos/query/update_item_spec.rb
158
180
  - spec/spec_helper.rb