dynameek 0.1.1a → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in foo.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,50 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ dynameek (0.2.1)
5
+ aws-sdk
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activesupport (3.2.13)
11
+ i18n (= 0.6.1)
12
+ multi_json (~> 1.0)
13
+ aws-sdk (1.8.5)
14
+ json (~> 1.4)
15
+ nokogiri (>= 1.4.4)
16
+ uuidtools (~> 2.1)
17
+ diff-lcs (1.2.1)
18
+ fake_dynamo (0.1.1)
19
+ activesupport
20
+ json
21
+ sinatra
22
+ i18n (0.6.1)
23
+ json (1.7.7)
24
+ multi_json (1.7.1)
25
+ nokogiri (1.5.8)
26
+ rack (1.5.2)
27
+ rack-protection (1.5.0)
28
+ rack
29
+ rspec (2.13.0)
30
+ rspec-core (~> 2.13.0)
31
+ rspec-expectations (~> 2.13.0)
32
+ rspec-mocks (~> 2.13.0)
33
+ rspec-core (2.13.1)
34
+ rspec-expectations (2.13.0)
35
+ diff-lcs (>= 1.1.3, < 2.0)
36
+ rspec-mocks (2.13.0)
37
+ sinatra (1.4.1)
38
+ rack (~> 1.5, >= 1.5.2)
39
+ rack-protection (~> 1.4)
40
+ tilt (~> 1.3, >= 1.3.4)
41
+ tilt (1.3.6)
42
+ uuidtools (2.1.3)
43
+
44
+ PLATFORMS
45
+ ruby
46
+
47
+ DEPENDENCIES
48
+ dynameek!
49
+ fake_dynamo
50
+ rspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Max Dupenois
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # Dynameek
2
+ A very lightweight ORMish model thing for amazon's dynamo db, after initialising the aws-sdk with something like:
3
+
4
+ amazon_config_path = File.join(File.dirname(__FILE__), *%w[.. config amazon.config.yml])
5
+ amazon_config = YAML.load(File.read(amazon_config_path))
6
+ AWS.config(amazon_config[ENVIRONMENT])
7
+
8
+ ##Models
9
+
10
+ You can create table models with this kind of syntax:
11
+
12
+ class Conversion < Dynameek::Model
13
+
14
+ field :client_id, :integer
15
+ field :channel_id, :string
16
+ field :goal_name, :string
17
+ field :time, :datetime
18
+
19
+ multi_column_hash_key [:client_id, :channel_id]
20
+ range :time
21
+
22
+ end
23
+
24
+ Creation of the models is as you'd expect
25
+
26
+ con = Conversion.create(:client_id => 1, :channel_id => "google", :goal_name=> "Some Goal", :time => DateTime.now)
27
+
28
+ The models can be edited like normal (_no update\_attributes yet though_)
29
+
30
+ con.goal_name="hello"
31
+ con.save
32
+
33
+ These models can be queried by find and query, although this is still undergoing some refactoring at the moment it currently looks something like this:
34
+
35
+ Conversion.find([1, "google"], DateTime.new([Some existing datetime]))
36
+
37
+ Conversion.query(["1", "google"]).where(DateTime.now, :lt).where(DateTime.now - 10, :gte).all
38
+
39
+ NB. The where clauses are only for referencing the range part of the composite hash key, there is currently no way to search by
40
+ hash contents as that felt like it was against the point of a document store.
41
+
42
+ ### Disclaimery Bit
43
+
44
+ Delete is not currently supported because I don't need it. The gem is dynameek (unsurprisingly) but I wouldn't use it yet, far better
45
+ to clone down the project and modify it for your own use.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/dynameek.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'dynameek/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "dynameek"
8
+ gem.version = Dynameek::VERSION
9
+ gem.authors = ["Max Dupenois"]
10
+ gem.email = ["max.dupenois@forward.co.uk"]
11
+ gem.description = %q{A very lightweight model for DynamoDB tables in, certainly not in a finished state}
12
+ gem.summary = %q{Dynameek - A dynamodb model}
13
+ gem.homepage = "http://github.com/maxdupenois/dynameek"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency("aws-sdk")
21
+ gem.add_development_dependency("rspec")
22
+ gem.add_development_dependency("fake_dynamo")
23
+ end
@@ -30,10 +30,11 @@ module Dynameek
30
30
 
31
31
  def build!
32
32
  return if dynamo_db.tables[table_name].exists?
33
- new_table = dynamo_db.tables.create(table_name, @@read_write[0], @@read_write[1],
34
- :hash_key => { hash_key_field.field => hash_key_field.type },
35
- :range_key => { range_field.field => range_field.type == :datetime ? :number : range_field.type }
36
- )
33
+ opts = {:hash_key => { hash_key_info.field => [:datetime, :integer, :float].include?(hash_key_info.type) ? :number : hash_key_info.type }}
34
+ if range?
35
+ opts[:range_key] = { range_info.field => [:datetime, :integer, :float].include?(range_info.type) ? :number : range_info.type }
36
+ end
37
+ new_table = dynamo_db.tables.create(table_name, read_units, write_units, opts)
37
38
  puts "Creating table, this may take a few minutes"
38
39
  while new_table.status == :creating
39
40
  sleep 1
@@ -17,21 +17,29 @@ module Dynameek
17
17
  end
18
18
 
19
19
  def where(value, op=:eq)
20
- raise Exception("Op #{op.to_s} not recognised") if(!@range.keys.include?(op))
20
+ raise Exception.new("Op #{op.to_s} not recognised") if(!@range.keys.include?(op))
21
21
  @range[op] = value
22
22
  self
23
23
  end
24
24
 
25
+ def delete
26
+ each(&:delete)
27
+ end
28
+
25
29
  def all
26
30
  run
27
31
  end
28
32
 
29
33
  def each
30
- all.each
34
+ all.each do |item|
35
+ yield(item)
36
+ end
31
37
  end
32
38
 
33
39
  def each_with_index
34
- all.each_with_index
40
+ all.each_with_index do |item, index|
41
+ yield(item, index)
42
+ end
35
43
  end
36
44
 
37
45
  RANGE_QUERY_MAP =
@@ -51,22 +59,29 @@ module Dynameek
51
59
  hash_key = @hash_key
52
60
  hash_key = hash_key.join(@model.multi_column_join) if(hash_key.is_a?(Array))
53
61
 
54
- query_hash = {:hash_value => hash_key}
62
+ query_hash = {:hash_value => hash_key, :select => :all}
55
63
 
56
64
  query_hash = @range.reduce(query_hash) do |hsh, (key, val)|
57
65
  if(!val.nil?)
58
- hsh[RANGE_QUERY_MAP[key]] = @model.convert_to_dynamodb(@model.range_field.type, val)
66
+ hsh[RANGE_QUERY_MAP[key]] = @model.convert_to_dynamodb(@model.range_info.type, val)
59
67
  end
60
68
  hsh
61
69
  end
62
- @model.table.items.query(query_hash).map{|item| @model.item_to_instance(item)}
70
+ # p query_hash
71
+ # "CONTENTS"
72
+ # @model.table.items.each{|item| p item.inspect}
73
+ # p "_________"
74
+ @model.table.items.query(query_hash).map{|item|
75
+ # p item.inspect
76
+ @model.item_to_instance(item)
77
+ }
63
78
 
64
79
  end
65
80
 
66
81
 
67
82
  end
68
83
 
69
- [:query, :where, :all, :each, :each_with_index].each do |method|
84
+ [:query, :where, :all, :each, :each_with_index, :delete].each do |method|
70
85
  define_method(method) do |*args|
71
86
  qc = QueryChain.new(self)
72
87
  args = [] if !args
@@ -1,26 +1,70 @@
1
1
  module Dynameek
2
2
  module Model
3
3
  module Structure
4
-
5
- @fields = {}
6
- @hash_key = OpenStruct.new
7
- @hash_key.field = nil
8
- @hash_key.type = nil
9
-
10
- @range = OpenStruct.new
11
- @range.field = nil
12
- @range.type = nil
13
-
14
- @read_write = [10, 5]
4
+
15
5
 
16
- @multi_column_hash_key_fields = []
17
- @multi_column_join = "|"
18
-
6
+ def fields
7
+ @fields ||= {}
8
+ end
9
+
10
+ def hash_key_info
11
+ if(@hash_key.nil?)
12
+ @hash_key = OpenStruct.new
13
+ @hash_key.field = nil
14
+ @hash_key.type = nil
15
+ end
16
+ @hash_key
17
+ end
18
+
19
+ def range_info
20
+ if(@range.nil?)
21
+ @range = OpenStruct.new
22
+ @range.field = nil
23
+ @range.type = nil
24
+ end
25
+ @range
26
+ end
27
+
28
+ def range?
29
+ !range_info.field.nil?
30
+ end
31
+
32
+ def read_units
33
+ @read_write ||= [10, 5]
34
+ @read_write[0]
35
+ end
36
+
37
+ def write_units
38
+ @read_write ||= [10, 5]
39
+ @read_write[1]
40
+ end
41
+
42
+ def read_write(vals)
43
+ @read_write = vals
44
+ end
45
+
46
+ def multi_column_hash_key_fields
47
+ @multi_column_hash_key_fields ||= []
48
+ end
49
+
50
+
51
+
52
+ def multi_column_join
53
+ @multi_column_join ||= "|"
54
+ end
55
+
56
+ def multi_column_join=(join)
57
+ @multi_column_join =join
58
+ end
59
+
60
+ def multi_column_hash_key?
61
+ !multi_column_hash_key_fields.empty?
62
+ end
19
63
 
20
64
  def field fieldname, type
21
65
  fieldname = fieldname.to_sym
22
66
  type = type.to_sym
23
- @fields[fieldname] = type
67
+ fields[fieldname] = type
24
68
  define_method(fieldname.to_s) { read_attribute(fieldname) }
25
69
  define_method("#{fieldname.to_s}?") { !read_attribute(fieldname).nil? }
26
70
  define_method("#{fieldname.to_s}=") {|value| write_attribute(fieldname, value) }
@@ -31,74 +75,48 @@ module Dynameek
31
75
  def hash_key fieldname
32
76
  fieldname = fieldname.to_sym
33
77
  check_field(fieldname)
34
- @hash_key.field = fieldname
35
- @hash_key.type = @fields[fieldname]
78
+ hash_key_info.field = fieldname
79
+ hash_key_info.type = fields[fieldname]
36
80
  define_method(:hash_key) { read_attribute(fieldname) }
37
81
  end
38
82
 
39
- def multi_column_join
40
- @multi_column_join
41
- end
42
- def multi_column_join=(join)
43
- @multi_column_join = join
44
- end
45
- def multi_column_hash_key?
46
- !@multi_column_hash_key_fields.empty?
47
- end
83
+
48
84
 
49
85
 
50
86
 
51
87
  def multi_column_hash_key fieldnames
52
- fields = fieldnames.map(&:to_sym)
53
- fields.each{|f| check_field(f)}
54
- @multi_column_hash_key_fields = fields
55
- fieldname = fieldnames.map(&:to_s).join("_").to_s
56
- @fields[fieldname] = :string
88
+ fieldnames = fieldnames.map(&:to_sym)
89
+ fieldnames.each{|f| check_field(f)}
90
+ fieldnames.each {|f| multi_column_hash_key_fields << f}
91
+ fieldname = fieldnames.map(&:to_s).join("_").to_sym
92
+ fields[fieldname] = :string
57
93
  define_method(:hash_key) do
58
- @multi_column_hash_key_fields.reduce([]) do |memo, field|
94
+ self.class.multi_column_hash_key_fields.reduce([]) do |memo, field|
59
95
  memo << attributes[field]
60
96
  memo
61
- end.join(@multi_column_join)
97
+ end.join(self.class.multi_column_join)
62
98
  end
63
99
  alias_method fieldname, :hash_key
64
- @hash_key.field = fieldname
65
- @hash_key.type = :string
100
+ hash_key_info.field = fieldname
101
+ hash_key_info.type = :string
66
102
  end
67
103
 
68
- def hash_key_field
69
- @hash_key
70
- end
71
104
 
72
105
 
73
106
  def range fieldname
74
107
  fieldname = fieldname.to_sym
75
108
  check_field(fieldname)
76
- @range.field = fieldname
77
- @range.type = @fields[fieldname]
109
+ range_info.field = fieldname
110
+ range_info.type = fields[fieldname]
78
111
  end
79
112
 
80
113
 
81
- def read_write read, write
82
- @read_write = [read, write]
83
- end
84
114
 
85
- def read_units
86
- @read_write[0]
87
- end
88
- def write_units
89
- @read_write[1]
90
- end
91
-
92
- def fields
93
- @fields
94
- end
95
-
96
- def range_field
97
- @range.field.nil? ? nil : @range
98
- end
115
+
116
+
99
117
 
100
118
  def check_field(fieldname)
101
- raise Exception("#{fieldname} is not a recognised field") if @fields[fieldname].nil?
119
+ raise ("#{fieldname} is not a recognised field") if fields[fieldname].nil?
102
120
  end
103
121
 
104
122
  end
@@ -1,95 +1,132 @@
1
- class Dynameek::Model
2
- extend Dynameek::Model::DynamoDb
3
- extend Dynameek::Model::Structure
4
- extend Dynameek::Model::Query
5
-
6
-
7
-
8
-
9
- attr_accessor :attributes
10
-
11
-
12
-
13
- def self.find(hash_key, range_val=nil)
14
- raise Exception("This has a composite hash with a range, the range val is required") if(range_val.nil? && !range_field.field.nil?)
15
- #multicolumn
16
- hash_key = hash_key.join(multi_column_join) if(hash_key.is_a?(Array))
17
-
18
- items = if !range_val.nil?
19
- range_val = convert_to_dynamodb(range_field.type, range_val)
20
- table.batch_get(:all, [[hash_key, range_val]])
21
- else
22
- table.batch_get(:all, [hash_key])
1
+ module Dynameek
2
+ module Model
3
+ def self.included(base)
4
+ base.extend ClassMethods
23
5
  end
24
- # p items.methods - Object.new.methods
25
- return nil if(items.entries.size == 0)
26
- item_to_instance(items.first)
27
6
 
28
- end
29
-
7
+ def save
8
+ attribs = self.class.fields.reduce({}) do |memo, (field, type)|
9
+ #Always call the read method in case it has been overwritten
10
+ #Note that this is required for the multicolumn key
11
+ val = self.send field
12
+ val = self.class.convert_to_dynamodb(type, val)
13
+ memo[field] = val
14
+ memo
15
+ end
16
+ self.class.before_save_callbacks.each{|method| self.send method}
17
+ self.class.table.batch_write(
18
+ :put => [
19
+ attribs
20
+ ]
21
+ )
22
+ self
23
+ end
24
+
25
+
26
+
27
+ def attributes
28
+ @attributes ||= {}
29
+ end
30
+
31
+ def read_attribute(fieldname)
32
+ attributes[fieldname]
33
+ end
30
34
 
31
-
32
- def self.item_to_instance(item)
33
- item = item.attributes if item.is_a?(AWS::DynamoDB::Item)
34
- instance = self.new
35
- fields.each do |field, type|
36
- next if multi_column_hash_key? && field == hash_key_field.field
37
- instance.send "#{field.to_s}=", convert_from_dynamodb(type, item[field.to_s])
35
+ def write_attribute(fieldname, value)
36
+ attributes[fieldname] = value
37
+ end
38
+
39
+ def delete
40
+ if self.class.range?
41
+ range_val = self.class.convert_to_dynamodb(self.class.range_info.type, self.send(self.class.range_info.field))
42
+ #Rounding errors can be irritating here so if we have the actual item we'll use it's range_val, nope that makes things worse
43
+ # range_val = dynamo_item.range_value if !dynamo_item.nil?
44
+ # p "TRYING TO DELETE #{[[hash_key, range_val]]}.inspect"
45
+ # p "FINDING THAT THING: #{self.class.find(hash_key, self.send(self.class.range_info.field)).inspect}"
46
+ # p "VIA BATCH GET #{self.class.table.batch_get(:all, [[hash_key, range_val]]).entries.inspect}"
47
+ self.class.table.batch_delete([[hash_key, range_val]])
48
+ else
49
+ self.class.table.batch_delete([hash_key])
50
+ end
51
+ end
52
+
53
+ def dynamo_item
54
+ @dynamo_item ||= nil
38
55
  end
39
- instance
40
- end
41
-
42
56
 
43
-
44
- def self.create(attrib)
45
- instance = self.new
46
- attrib.each do |key, val|
47
- instance.send "#{key.to_s}=", val
57
+ def dynamo_item=(item)
58
+ @dynamo_item = item
48
59
  end
49
- instance.save
50
- end
51
60
 
52
- def self.before_save_callbacks
53
- @before_save_callbacks ||= Set.new
54
- end
61
+ module ClassMethods
62
+ include Dynameek::Model::DynamoDb
63
+ include Dynameek::Model::Structure
64
+ include Dynameek::Model::Query
65
+
55
66
 
56
- def self.before_save method
57
- before_save_callbacks << method.to_sym
58
- end
59
67
 
60
- def save
61
- attribs = self.class.fields.reduce({}) do |memo, (field, type)|
62
- #Always call the read method in case it has been overwritten
63
- #Note that this is required for the multicolumn key
64
- val = self.send field
65
- val = self.class.convert_to_dynamodb(type, val)
66
- memo[field] = val
67
- memo
68
- end
69
- self.class.before_save_callbacks.each{|method| self.send method}
70
- self.class.table.batch_write(
71
- :put => [
72
- attribs
73
- ]
74
- )
75
- self
76
- end
68
+
69
+ def find(hash_key, range_val=nil)
70
+ raise Exception("This has a composite hash with a range, the range val is required") if(range_val.nil? && range?)
71
+ #multicolumn
72
+ hash_key = hash_key.join(multi_column_join) if(hash_key.is_a?(Array))
77
73
 
74
+ items = if range?
75
+ range_val = convert_to_dynamodb(range_info.type, range_val)
76
+ table.batch_get(:all, [[hash_key, range_val]])
77
+ else
78
+ table.batch_get(:all, [hash_key])
79
+ end
80
+ # p items.methods - Object.new.methods
81
+ return nil if(items.entries.size == 0)
82
+ item_to_instance(items.first)
83
+
84
+ end
78
85
 
79
- def self.table_name
80
- self.to_s
81
- end
86
+ def delete_table
87
+ table.delete
88
+ end
89
+
82
90
 
83
- private
91
+ def item_to_instance(item)
92
+ item_hsh = (item.is_a?(AWS::DynamoDB::Item) || item.is_a?(AWS::DynamoDB::ItemData) ? item.attributes.to_hash : item)
93
+ instance = self.new
94
+ fields.each do |field, type|
95
+ next if multi_column_hash_key? && field == hash_key_info.field
96
+ instance.send "#{field.to_s}=", convert_from_dynamodb(type, item_hsh[field.to_s])
97
+ end
98
+ if item.is_a?(AWS::DynamoDB::Item) || item.is_a?(AWS::DynamoDB::ItemData)
99
+ instance.dynamo_item = item.is_a?(AWS::DynamoDB::ItemData) ? item.item : item
100
+ end
101
+ instance
102
+ end
103
+
104
+
105
+
106
+ def create(attrib)
107
+ instance = self.new
108
+ attrib.each do |key, val|
109
+ instance.send "#{key.to_s}=", val
110
+ end
111
+ instance.save
112
+ end
113
+
114
+ def before_save_callbacks
115
+ @before_save_callbacks ||= Set.new
116
+ end
117
+
118
+ def before_save method
119
+ before_save_callbacks << method.to_sym
120
+ end
84
121
 
85
- def read_attribute(fieldname)
86
- @attributes[fieldname]
87
- end
88
122
 
89
- def write_attribute(fieldname, value)
90
- @attributes = {} if(!@attributes)
91
- @attributes[fieldname] = value
92
- end
123
+
124
+ def table_name
125
+ self.to_s
126
+ end
127
+
93
128
 
94
129
 
130
+ end
131
+ end
95
132
  end
@@ -0,0 +1,3 @@
1
+ module Dynameek
2
+ VERSION = "0.2.1"
3
+ end
data/lib/dynameek.rb CHANGED
@@ -1,3 +1,6 @@
1
+ require File.join(File.dirname(__FILE__), *%w[dynameek version])
2
+ require 'ostruct'
3
+
1
4
  module Dynameek
2
5
  end
3
6
 
@@ -0,0 +1,13 @@
1
+ class Conversion
2
+ include Dynameek::Model
3
+
4
+ field :client_id, :integer
5
+ field :channel_id, :string
6
+ field :goal_name, :string
7
+ field :time, :datetime
8
+
9
+ multi_column_hash_key [:client_id, :channel_id]
10
+ range :time
11
+
12
+
13
+ end
@@ -0,0 +1,13 @@
1
+ class Simple
2
+ include Dynameek::Model
3
+
4
+
5
+ field :my_id, :integer
6
+ field :some_value, :string
7
+
8
+
9
+ hash_key :my_id
10
+
11
+
12
+
13
+ end
@@ -0,0 +1,58 @@
1
+ require File.join(File.dirname(__FILE__), *%w[spec_helper])
2
+
3
+ describe Conversion do
4
+ before(:all) do
5
+ Conversion.delete_table
6
+ end
7
+ before(:each) do
8
+ Conversion.query([1, "google"]).delete
9
+ end
10
+
11
+ it "should allow you to create a new conversion" do
12
+ con = nil
13
+ lambda{
14
+ con = Conversion.create(:client_id => 1, :channel_id => "google", :goal_name=> "new conversion", :time => DateTime.now)
15
+ }.should_not raise_error
16
+ con.hash_key.should == "1|google"
17
+ end
18
+
19
+
20
+ it "should allow you to find a conversion" do
21
+ now = DateTime.now
22
+ Conversion.create(:client_id => 1, :channel_id => "google", :goal_name=> "find conversion", :time => now)
23
+ con = Conversion.find([1, "google"], now)
24
+ con.should_not be_nil
25
+ con.hash_key.should == "1|google"
26
+ end
27
+
28
+
29
+ it "should allow you to delete a range" do
30
+ now = DateTime.now
31
+ Conversion.create(:client_id => 1, :channel_id => "google", :goal_name=> "delete conversion", :time => now)
32
+ Conversion.query([1, "google"]).all.size.should == 1
33
+ Conversion.query([1, "google"]).delete
34
+ Conversion.query([1, "google"]).all.size.should == 0
35
+ end
36
+
37
+ it "should allow you to find a query a conversion" do
38
+ now = DateTime.now
39
+ Conversion.create(:client_id => 1, :channel_id => "google", :goal_name=> "Some Goal", :time => now)
40
+ cons = Conversion.query([1, "google"]).all
41
+ cons.size.should == 1
42
+ end
43
+
44
+ it "should allow you to find a query a conversion within a range" do
45
+ now = DateTime.now
46
+ Conversion.create(:client_id => 1, :channel_id => "google", :goal_name=> "Some Goal", :time => now - 3)
47
+ Conversion.create(:client_id => 1, :channel_id => "google", :goal_name=> "Some Goal", :time => now - 2)
48
+ Conversion.create(:client_id => 1, :channel_id => "google", :goal_name=> "Some Goal", :time => now - 1)
49
+ cons = Conversion.query([1, "google"]).where(now, :lt).all
50
+ cons.size.should == 3
51
+ cons = Conversion.query([1, "google"]).where(now - 4, :gt).all
52
+ cons.size.should == 3
53
+ # cons = Conversion.query([1, "google"]).where(now - 2, :gte).where(now, :lt).all
54
+ # cons.size.should == 2 Not supported on fake_dynamo, seems to work fine on prod
55
+ end
56
+
57
+
58
+ end
@@ -0,0 +1,26 @@
1
+ require File.join(File.dirname(__FILE__), *%w[spec_helper])
2
+
3
+ describe Simple do
4
+ before(:all) do
5
+ Simple.delete_table
6
+ end
7
+ before(:each) do
8
+ simple = Simple.find(1)
9
+ simple.delete if(!simple.nil?)
10
+ end
11
+ it "should allow you to create a new simple" do
12
+ con = nil
13
+ lambda{
14
+ con = Simple.create(:my_id => 1, :some_value => "hello")
15
+ }.should_not raise_error
16
+ con.hash_key.should == 1
17
+ con.some_value.should == "hello"
18
+ end
19
+ it "should allow you to find a created simple" do
20
+ Simple.create(:my_id => 1, :some_value => "hello")
21
+ con = Simple.find(1)
22
+ con.hash_key.should == 1
23
+ con.some_value.should == "hello"
24
+ end
25
+
26
+ end
@@ -0,0 +1,13 @@
1
+ require 'rspec'
2
+ require 'aws-sdk'
3
+
4
+ require File.join(File.dirname(__FILE__), *%w[.. .. lib dynameek])
5
+
6
+ AWS.config(:use_ssl => false,
7
+ :dynamo_db_endpoint => 'localhost',
8
+ :dynamo_db_port => 4567,
9
+ :access_key_id => "xxx",
10
+ :secret_access_key => "xxx")
11
+
12
+ require File.join(File.dirname(__FILE__), *%w[.. models conversion])
13
+ require File.join(File.dirname(__FILE__), *%w[.. models simple])
metadata CHANGED
@@ -1,8 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dynameek
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: 5
5
- version: 0.1.1a
4
+ prerelease:
5
+ version: 0.2.1
6
6
  platform: ruby
7
7
  authors:
8
8
  - Max Dupenois
@@ -11,10 +11,43 @@ bindir: bin
11
11
  cert_chain: []
12
12
 
13
13
  date: 2013-03-20 00:00:00 Z
14
- dependencies: []
15
-
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: aws-sdk
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ type: :runtime
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: rspec
28
+ prerelease: false
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: "0"
35
+ type: :development
36
+ version_requirements: *id002
37
+ - !ruby/object:Gem::Dependency
38
+ name: fake_dynamo
39
+ prerelease: false
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ type: :development
47
+ version_requirements: *id003
16
48
  description: A very lightweight model for DynamoDB tables in, certainly not in a finished state
17
- email: max.dupenois@forward.co.uk
49
+ email:
50
+ - max.dupenois@forward.co.uk
18
51
  executables: []
19
52
 
20
53
  extensions: []
@@ -22,11 +55,23 @@ extensions: []
22
55
  extra_rdoc_files: []
23
56
 
24
57
  files:
58
+ - Gemfile
59
+ - Gemfile.lock
60
+ - LICENSE.txt
61
+ - README.md
62
+ - Rakefile
63
+ - dynameek.gemspec
64
+ - lib/dynameek.rb
65
+ - lib/dynameek/model.rb
25
66
  - lib/dynameek/model/dynamo_db.rb
26
67
  - lib/dynameek/model/query.rb
27
68
  - lib/dynameek/model/structure.rb
28
- - lib/dynameek/model.rb
29
- - lib/dynameek.rb
69
+ - lib/dynameek/version.rb
70
+ - test/models/conversion.rb
71
+ - test/models/simple.rb
72
+ - test/spec/conversion_spec.rb
73
+ - test/spec/simple_spec.rb
74
+ - test/spec/spec_helper.rb
30
75
  homepage: http://github.com/maxdupenois/dynameek
31
76
  licenses: []
32
77
 
@@ -44,15 +89,19 @@ required_ruby_version: !ruby/object:Gem::Requirement
44
89
  required_rubygems_version: !ruby/object:Gem::Requirement
45
90
  none: false
46
91
  requirements:
47
- - - ">"
92
+ - - ">="
48
93
  - !ruby/object:Gem::Version
49
- version: 1.3.1
94
+ version: "0"
50
95
  requirements: []
51
96
 
52
97
  rubyforge_project:
53
98
  rubygems_version: 1.8.24
54
99
  signing_key:
55
100
  specification_version: 3
56
- summary: Dynameek
57
- test_files: []
58
-
101
+ summary: Dynameek - A dynamodb model
102
+ test_files:
103
+ - test/models/conversion.rb
104
+ - test/models/simple.rb
105
+ - test/spec/conversion_spec.rb
106
+ - test/spec/simple_spec.rb
107
+ - test/spec/spec_helper.rb