dynameek 0.0.1a

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,58 @@
1
+ module Dynameek
2
+ module DynamoDb
3
+ def convert_from_dynamodb(type, value)
4
+ case type
5
+ when :integer
6
+ value.to_i
7
+ when :float
8
+ value.to_f
9
+ when :string
10
+ value.to_s
11
+ when :datetime
12
+ Time.at(value).to_datetime
13
+ else
14
+ value
15
+ end
16
+ end
17
+ def convert_to_dynamodb(type, value)
18
+ case type
19
+ when :datetime
20
+ value.to_time.to_f
21
+ else
22
+ value
23
+ end
24
+ end
25
+
26
+ def exists?
27
+ table.exists?
28
+ end
29
+
30
+ def build!
31
+ return if dynamo_db.tables[table_name].exists?
32
+ new_table = dynamo_db.tables.create(table_name, @@read_write[0], @@read_write[1],
33
+ :hash_key => { @@hash_key.field => @@hash_key.type },
34
+ :range_key => { @@range.field => @@range.type == :datetime ? :number : @@range.type }
35
+ )
36
+ puts "Creating table, this may take a few minutes"
37
+ while new_table.status == :creating
38
+ sleep 1
39
+ end
40
+ end
41
+
42
+ @@table = nil
43
+ @@dynamo_db = nil
44
+
45
+ def dynamo_db
46
+ @@dynamo_db = AWS::DynamoDB.new if @@dynamo_db.nil?
47
+ @@dynamo_db
48
+ end
49
+
50
+ def table
51
+ build!
52
+ @@table = dynamo_db.tables[table_name] if @@table.nil?
53
+ @@table.load_schema if !@@table.schema_loaded?
54
+ @@table
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,92 @@
1
+ class Dynameek::Model
2
+ extend Dynameek::DynamoDb
3
+ extend Dynameek::ModelStructure
4
+ extend Dynameek::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.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])
23
+ end
24
+ # p items.methods - Object.new.methods
25
+ return nil if(items.entries.size == 0)
26
+ item_to_instance(items.first)
27
+
28
+ end
29
+
30
+
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])
38
+ end
39
+ instance
40
+ end
41
+
42
+
43
+
44
+ def self.create(attrib)
45
+ instance = self.new
46
+ attrib.each do |key, val|
47
+ instance.send "#{key.to_s}=", val
48
+ end
49
+ instance.save
50
+ end
51
+
52
+ @@before_save_callbacks = Set.new
53
+ def self.before_save method
54
+ @@before_save_callbacks.add(method.to_sym)
55
+ end
56
+
57
+ def save
58
+ attribs = self.class.fields.reduce({}) do |memo, (field, type)|
59
+ #Always call the read method in case it has been overwritten
60
+ #Note that this is required for the multicolumn key
61
+ val = self.send field
62
+ val = self.class.convert_to_dynamodb(type, val)
63
+ memo[field] = val
64
+ memo
65
+ end
66
+ @@before_save_callbacks.each{|method| self.send method}
67
+ self.class.table.batch_write(
68
+ :put => [
69
+ attribs
70
+ ]
71
+ )
72
+ self
73
+ end
74
+
75
+
76
+ def self.table_name
77
+ self.to_s
78
+ end
79
+
80
+ private
81
+
82
+ def read_attribute(fieldname)
83
+ @attributes[fieldname]
84
+ end
85
+
86
+ def write_attribute(fieldname, value)
87
+ @attributes = {} if(!@attributes)
88
+ @attributes[fieldname] = value
89
+ end
90
+
91
+
92
+ end
@@ -0,0 +1,106 @@
1
+ module Dynameek
2
+ module ModelStructure
3
+
4
+ @@fields = {}
5
+ @@hash_key = OpenStruct.new
6
+ @@hash_key.field = nil
7
+ @@hash_key.type = nil
8
+
9
+ @@range = OpenStruct.new
10
+ @@range.field = nil
11
+ @@range.type = nil
12
+
13
+ @@read_write = [10, 5]
14
+
15
+ @@multi_column_hash_key_fields = []
16
+ @@multi_column_join = "|"
17
+
18
+
19
+ def field fieldname, type
20
+ fieldname = fieldname.to_sym
21
+ type = type.to_sym
22
+ @@fields[fieldname] = type
23
+ define_method(fieldname.to_s) { read_attribute(fieldname) }
24
+ define_method("#{fieldname.to_s}?") { !read_attribute(fieldname).nil? }
25
+ define_method("#{fieldname.to_s}=") {|value| write_attribute(fieldname, value) }
26
+ end
27
+
28
+
29
+
30
+ def hash_key fieldname
31
+ fieldname = fieldname.to_sym
32
+ check_field(fieldname)
33
+ @@hash_key.field = fieldname
34
+ @@hash_key.type = @@fields[fieldname]
35
+ define_method(:hash_key) { read_attribute(fieldname) }
36
+ end
37
+
38
+ def multi_column_join
39
+ @@multi_column_join
40
+ end
41
+ def multi_column_join=(join)
42
+ @@multi_column_join = join
43
+ end
44
+ def multi_column_hash_key?
45
+ !@@multi_column_hash_key_fields.empty?
46
+ end
47
+
48
+
49
+
50
+ def multi_column_hash_key fieldnames
51
+ fields = fieldnames.map(&:to_sym)
52
+ fields.each{|f| check_field(f)}
53
+ @@multi_column_hash_key_fields = fields
54
+ fieldname = fieldnames.map(&:to_s).join("_").to_s
55
+ @@fields[fieldname] = :string
56
+ define_method(:hash_key) do
57
+ @@multi_column_hash_key_fields.reduce([]) do |memo, field|
58
+ memo << attributes[field]
59
+ memo
60
+ end.join(@@multi_column_join)
61
+ end
62
+ alias_method fieldname, :hash_key
63
+ @@hash_key.field = fieldname
64
+ @@hash_key.type = :string
65
+ end
66
+
67
+ def hash_key_field
68
+ @@hash_key
69
+ end
70
+
71
+
72
+ def range fieldname
73
+ fieldname = fieldname.to_sym
74
+ check_field(fieldname)
75
+ @@range.field = fieldname
76
+ @@range.type = @@fields[fieldname]
77
+ end
78
+
79
+
80
+ def read_write read, write
81
+ @@read_write = [read, write]
82
+ end
83
+
84
+ def read_units
85
+ @@read_write[0]
86
+ end
87
+ def write_units
88
+ @@read_write[1]
89
+ end
90
+
91
+ def fields
92
+ @@fields
93
+ end
94
+
95
+ def range_field
96
+ @@range.field.nil? ? nil : @@range
97
+ end
98
+
99
+ def check_field(fieldname)
100
+ raise Exception("#{fieldname} is not a recognised field") if @@fields[fieldname].nil?
101
+ end
102
+
103
+ end
104
+ end
105
+
106
+
@@ -0,0 +1,77 @@
1
+ module Dynameek
2
+ module Query
3
+ #Similar to dynamoids approach but lighter (hopefully)
4
+
5
+ class QueryChain
6
+
7
+ def initialize(model)
8
+ @model = model
9
+ @hash_key = nil
10
+ @range = {eq: nil, within: nil, gte: nil, gt: nil, lte: nil, lt: nil, begins_with: nil}
11
+ end
12
+
13
+ def query(hash_key)
14
+ @hash_key = hash_key
15
+ self
16
+ end
17
+
18
+ def where(value, op=:eq)
19
+ raise Exception("Op #{op.to_s} not recognised") if(!@range.keys.include?(op))
20
+ @range[op] = value
21
+ self
22
+ end
23
+
24
+ def all
25
+ run
26
+ end
27
+
28
+ def each
29
+ all.each
30
+ end
31
+
32
+ def each_with_index
33
+ all.each_with_index
34
+ end
35
+
36
+ RANGE_QUERY_MAP =
37
+ {
38
+ eq: :range_value,
39
+ within: :range_value,
40
+ gte: :range_gte,
41
+ gt: :range_greater_than,
42
+ lte: :range_lte,
43
+ lt: :range_less_than,
44
+ begins_with: :range_begins_with
45
+ }
46
+
47
+ private
48
+
49
+ def run
50
+ hash_key = @hash_key
51
+ hash_key = hash_key.join(@model.multi_column_join) if(hash_key.is_a?(Array))
52
+
53
+ query_hash = {:hash_value => hash_key}
54
+
55
+ query_hash = @range.reduce(query_hash) do |hsh, (key, val)|
56
+ if(!val.nil?)
57
+ hsh[RANGE_QUERY_MAP[key]] = @model.convert_to_dynamodb(@model.range_field.type, val)
58
+ end
59
+ hsh
60
+ end
61
+ @model.table.items.query(query_hash).map{|item| @model.item_to_instance(item)}
62
+
63
+ end
64
+
65
+
66
+ end
67
+
68
+ [:query, :where, :all, :each, :each_with_index].each do |method|
69
+ define_method(method) do |*args|
70
+ qc = QueryChain.new(self)
71
+ args = [] if !args
72
+ qc.send method, *args
73
+ end
74
+ end
75
+
76
+ end
77
+ end
data/lib/dynameek.rb ADDED
@@ -0,0 +1,7 @@
1
+ module Dynameek
2
+ end
3
+
4
+ require File.join(File.dirname(__FILE__), *%w[dynameek dynamo_db])
5
+ require File.join(File.dirname(__FILE__), *%w[dynameek query])
6
+ require File.join(File.dirname(__FILE__), *%w[dynameek model_structure])
7
+ require File.join(File.dirname(__FILE__), *%w[dynameek model])
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dynameek
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: 5
5
+ version: 0.0.1a
6
+ platform: ruby
7
+ authors:
8
+ - Max Dupenois
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2013-03-20 00:00:00 Z
14
+ dependencies: []
15
+
16
+ description: A very lightweight model for DynamoDB tables in, certainly not in a finished state
17
+ email: max.dupenois@forward.co.uk
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - lib/dynameek/dynamo_db.rb
26
+ - lib/dynameek/model.rb
27
+ - lib/dynameek/model_structure.rb
28
+ - lib/dynameek/query.rb
29
+ - lib/dynameek.rb
30
+ homepage: http://github.com/maxdupenois/dynameek
31
+ licenses: []
32
+
33
+ post_install_message:
34
+ rdoc_options: []
35
+
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ">"
48
+ - !ruby/object:Gem::Version
49
+ version: 1.3.1
50
+ requirements: []
51
+
52
+ rubyforge_project:
53
+ rubygems_version: 1.8.24
54
+ signing_key:
55
+ specification_version: 3
56
+ summary: Dynameek
57
+ test_files: []
58
+