bank 0.1.8

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,94 @@
1
+ require 'attr_protected'
2
+ require 'forwardable'
3
+
4
+ require 'bank/sequel'
5
+ require 'bank/collection_config'
6
+ require 'bank/serialize'
7
+
8
+ module Bank
9
+ RecordNotFound = Class.new(RuntimeError)
10
+ UnknownConversionType = Class.new(RuntimeError)
11
+
12
+ class Collection
13
+ class << self
14
+ extend Forwardable
15
+
16
+ def_delegators :db, *DatasetMethods
17
+
18
+ def config
19
+ @_config ||= CollectionConfig.new
20
+ end
21
+
22
+ def db
23
+ Result.new(config.db, self)
24
+ end
25
+
26
+ def scope(name, blk)
27
+ define_singleton_method(name) { |*args| instance_exec *args, &blk }
28
+ end
29
+
30
+ def find_by(key, value)
31
+ where(key => value).first
32
+ end
33
+
34
+ def save(model)
35
+ pkey = config.primary_key
36
+
37
+ if new?(model)
38
+ model.send(:"#{pkey}=", db.insert(Serialize.pack(config, model)))
39
+ else
40
+ db.where(pkey => model.send(pkey)).
41
+ update(Serialize.pack(config, model))
42
+ end
43
+
44
+ return model
45
+ end
46
+
47
+ def create(attrs)
48
+ save(config.model.new(attrs))
49
+ end
50
+
51
+ def update(*args, &blk)
52
+ model = find(*args)
53
+
54
+ blk.call(model)
55
+ save(model)
56
+ model
57
+ end
58
+
59
+ def find(key)
60
+ result = key.nil? ? nil : where(config.primary_key => key).first
61
+
62
+ raise RecordNotFound,
63
+ "no record found in collection with id `#{key.inspect}'" if result.nil?
64
+
65
+ return result
66
+ end
67
+
68
+ def delete(key)
69
+ db.where(config.primary_key => key).delete
70
+ end
71
+
72
+ def convert(attrs)
73
+ case attrs
74
+ when Array
75
+ attrs.map(&method(:convert))
76
+ when Hash
77
+ config.model.new(Serialize.unpack(config, attrs))
78
+ else
79
+ raise UnknownConversionType, "unable to convert #{attrs.inspect}"
80
+ end
81
+ end
82
+
83
+ def join_as(table, *args, &blk)
84
+ select(*config.model._fields.map { |f| :"#{table}__#{f}"}).join(*args, &blk)
85
+ end
86
+
87
+ private
88
+
89
+ def new?(model)
90
+ model.send(config.primary_key).nil?
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,49 @@
1
+ require 'attr_protected'
2
+ require 'bank/database'
3
+
4
+ module Bank
5
+ class CollectionConfig
6
+ attr_protected :_model_block
7
+ attr_writer :packer, :unpacker
8
+
9
+ def model(&block)
10
+ if block_given?
11
+ self._model_block = block
12
+ else
13
+ @_model ||= _model_block.call
14
+ end
15
+ end
16
+
17
+ def packer
18
+ @packer ||= identity
19
+ end
20
+
21
+ def unpacker
22
+ @unpacker ||= identity
23
+ end
24
+
25
+ def db(&block)
26
+ if block_given?
27
+ @_db_block = block
28
+ @_db = nil
29
+ else
30
+ value = @_db_block.call
31
+ @_db ||= value.is_a?(Symbol) ? Database[value] : value
32
+ end
33
+ end
34
+
35
+ def primary_key(value = nil)
36
+ if value
37
+ @_primary_key = value
38
+ else
39
+ @_primary_key ||= :id
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def identity
46
+ ->(i) { i }
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,23 @@
1
+ require 'attr_protected'
2
+
3
+ require 'bank/result'
4
+
5
+ module Bank
6
+ class Database
7
+ class << self
8
+ attr_protected :db
9
+
10
+ def self.db
11
+ db.dup
12
+ end
13
+
14
+ def use_db(db)
15
+ self.db = db
16
+ end
17
+
18
+ def [](name)
19
+ self.db[name]
20
+ end
21
+ end
22
+ end
23
+ end
data/lib/bank/model.rb ADDED
@@ -0,0 +1,65 @@
1
+ require 'attr_protected'
2
+
3
+ module Bank
4
+ class Model
5
+ class << self
6
+ attr_protected :_fields, :_defaults
7
+
8
+ def fields(*fields)
9
+ attr_accessor *fields
10
+ self._fields = fields
11
+ end
12
+
13
+ def _fields
14
+ @_fields ||= []
15
+ end
16
+
17
+ def defaults(defaults)
18
+ self._defaults = defaults
19
+ end
20
+
21
+ def _defaults
22
+ @_defaults ||= {}
23
+ end
24
+ end
25
+
26
+ def initialize(attrs = {})
27
+ set(attrs)
28
+ _defaults.each { |key, val| set(key, val) if !get(key) }
29
+ end
30
+
31
+ def to_hash
32
+ _fields.reduce({}) do |acc, field|
33
+ acc.merge(field => get(field))
34
+ end
35
+ end
36
+
37
+ def get(attr)
38
+ instance_variable_get(:"@#{attr}")
39
+ end
40
+
41
+ def set(attr, value = nil)
42
+ if attr.is_a?(Hash)
43
+ attr.each { |key, value| set(key, value) }
44
+ else
45
+ public_send(:"#{attr}=", value)
46
+ end
47
+
48
+ return self
49
+ end
50
+
51
+ def ==(other)
52
+ other.is_a?(self.class) && other.to_hash == to_hash
53
+ end
54
+
55
+ private
56
+
57
+ def _fields
58
+ self.class._fields
59
+ end
60
+
61
+ def _defaults
62
+ self.class._defaults
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,61 @@
1
+ require 'attr_protected'
2
+ require 'forwardable'
3
+
4
+ require 'bank/sequel'
5
+
6
+ module Bank
7
+ class Result
8
+ include Enumerable
9
+ extend Forwardable
10
+
11
+ attr_protected :db, :collection
12
+
13
+ def_delegators :db, *[:update, :insert, :delete, :max, :min, :count]
14
+ def_delegators :all, :inspect, :empty?
15
+
16
+ def initialize(db, collection)
17
+ self.db = db
18
+ self.collection = collection
19
+ end
20
+
21
+ def each(&blk)
22
+ raw.each { |result| blk.call(collection.convert(result)) }
23
+ end
24
+
25
+ def raw
26
+ db.all
27
+ end
28
+
29
+ def all
30
+ collection.convert(raw)
31
+ end
32
+
33
+ # db overrides for Enumerable-clashing methods
34
+ def select(*args, &block) new(db.select(*args, &block)) end
35
+ def group_by(*args, &block) new(db.group_by(*args, &block)) end
36
+ def grep(*args, &block) new(db.grep(*args, &block)) end
37
+
38
+ def method_missing(*args, &blk)
39
+ DatasetMethods.include?(args[0]) ? new(db.send(*args, &blk)) : super
40
+ end
41
+
42
+ def respond_to?(method)
43
+ DatasetMethods.include?(method) || super
44
+ end
45
+
46
+ def ==(other)
47
+ self.all == other
48
+ end
49
+ alias_method :eql?, :==
50
+
51
+ def inspect
52
+ all.inspect
53
+ end
54
+
55
+ private
56
+
57
+ def new(db)
58
+ self.class.new(db, collection)
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,17 @@
1
+ module Bank
2
+
3
+ DatasetMethods = [:select, :select_all, :select_append, :select_group,
4
+ :select_more, :join, :left_join, :right_join, :full_join,
5
+ :natural_join, :natural_left_join, :natural_right_join,
6
+ :natural_full_join, :cross_join, :inner_join, :left_outer_join,
7
+ :right_outer_join, :full_outer_join, :join_table, :where, :filter,
8
+ :exclude, :exclude_where, :and, :or, :grep, :invert, :unfiltered,
9
+ :group, :group_by, :group_and_count, :select_group, :ungrouped,
10
+ :having, :exclude_having, :invert, :unfiltered, :order, :order_by,
11
+ :order_append, :order_prepend, :order_more, :reverse, :reverse_order,
12
+ :unordered, :limit, :offset, :unlimited, :union, :intersect, :except,
13
+ :for_update, :lock_style, :with, :with_recursive, :clone, :distinct,
14
+ :naked, :qualify, :server, :with_sql, :count,
15
+ :insert, :update, :delete, :max, :min]
16
+
17
+ end
@@ -0,0 +1,101 @@
1
+ module Bank
2
+ module Serialize
3
+ def self.pack(*args)
4
+ Packer.new(*args).call
5
+ end
6
+
7
+ def self.unpack(*args)
8
+ Unpacker.new(*args).call
9
+ end
10
+
11
+ class Packer
12
+ attr_protected :config, :model
13
+
14
+ def initialize(config, model)
15
+ self.config = config
16
+ self.model = model
17
+ end
18
+
19
+ def call
20
+ attrs = normalize(model.to_hash)
21
+
22
+ config.packer.call(attrs)
23
+ set_timestamps(attrs, model)
24
+
25
+ model.set(Serialize.unpack(config, attrs.dup))
26
+ attrs
27
+ end
28
+
29
+ private
30
+
31
+ def set_timestamps(attrs, model)
32
+ now = Time.now
33
+
34
+ attrs[:updated_at] = now if model.respond_to?(:updated_at=)
35
+ attrs[:created_at] = now if model.respond_to?(:created_at=) &&
36
+ !model.send(config.primary_key)
37
+ end
38
+
39
+ def normalize(attrs)
40
+ attrs = attrs.dup
41
+
42
+ columns.select { |column, opts|
43
+ !attrs[column].nil? && opts[:type] == :integer
44
+ }.each { |column, opts| attrs[column] = attrs[column].to_i }
45
+
46
+ columns.select { |column, opts|
47
+ !attrs[column].nil? && opts[:type] == :boolean
48
+ }.each { |column, opts| attrs[column] = attrs[column] ? 1 : 0 }
49
+
50
+ attrs
51
+ end
52
+
53
+ def columns
54
+ @columns ||= Database.db.schema(config.db)
55
+ end
56
+ end
57
+
58
+ class Unpacker
59
+ attr_protected :config, :attrs
60
+
61
+ def initialize(config, attrs)
62
+ self.config = config
63
+ self.attrs = attrs
64
+ end
65
+
66
+ def call
67
+ columns.select { |column, opts|
68
+ opts[:type] == :datetime && ![nil, 0].include?(attrs[column])
69
+ }.each { |column, opts| attrs[column] = drop_usecs(attrs[column]) }
70
+
71
+ columns.select { |column, opts|
72
+ opts[:type] == :date && ![nil, 0].include?(attrs[column])
73
+ }.each { |column, opts|
74
+ attrs[column] = Date.parse(attrs[column]) if attrs[column].is_a?(String)
75
+ }
76
+
77
+ columns.select { |column, opts|
78
+ !attrs[column].nil? && opts[:type] == :boolean
79
+ }.each { |column, opts| attrs[column] = [1, true].include?(attrs[column]) }
80
+
81
+ config.unpacker.call(attrs)
82
+ attrs
83
+ end
84
+
85
+ def drop_usecs(time)
86
+ if time.is_a?(String)
87
+ Time.at(Time.parse(time).to_i)
88
+ elsif time.is_a?(DateTime)
89
+ Time.at(time.to_time.to_i)
90
+ else
91
+ Time.at(time.to_i)
92
+ end
93
+ end
94
+
95
+ def columns
96
+ @columns ||= Database.db.schema(config.db)
97
+ end
98
+ end
99
+
100
+ end
101
+ end
metadata ADDED
@@ -0,0 +1,140 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bank
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.8
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Brian Pratt
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-04-25 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: sequel
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '4.7'
22
+ - - ! '>='
23
+ - !ruby/object:Gem::Version
24
+ version: 4.7.0
25
+ type: :runtime
26
+ prerelease: false
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: '4.7'
33
+ - - ! '>='
34
+ - !ruby/object:Gem::Version
35
+ version: 4.7.0
36
+ - !ruby/object:Gem::Dependency
37
+ name: attr_protected
38
+ requirement: !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: '1.0'
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: 1.0.0
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
55
+ - - ! '>='
56
+ - !ruby/object:Gem::Version
57
+ version: 1.0.0
58
+ - !ruby/object:Gem::Dependency
59
+ name: rake
60
+ requirement: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: '10.1'
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: 10.1.1
69
+ type: :development
70
+ prerelease: false
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: '10.1'
77
+ - - ! '>='
78
+ - !ruby/object:Gem::Version
79
+ version: 10.1.1
80
+ - !ruby/object:Gem::Dependency
81
+ name: rspec
82
+ requirement: !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ~>
86
+ - !ruby/object:Gem::Version
87
+ version: '2.14'
88
+ - - ! '>='
89
+ - !ruby/object:Gem::Version
90
+ version: 2.14.1
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ~>
97
+ - !ruby/object:Gem::Version
98
+ version: '2.14'
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: 2.14.1
102
+ description: wraps Sequel to provide a non-ORM data-mapping interface
103
+ email: brian@8thlight.com
104
+ executables: []
105
+ extensions: []
106
+ extra_rdoc_files: []
107
+ files:
108
+ - lib/bank/collection.rb
109
+ - lib/bank/collection_config.rb
110
+ - lib/bank/database.rb
111
+ - lib/bank/model.rb
112
+ - lib/bank/result.rb
113
+ - lib/bank/sequel.rb
114
+ - lib/bank/serialize.rb
115
+ homepage: https://github.com/pratt121/bank
116
+ licenses:
117
+ - WTFPL
118
+ post_install_message:
119
+ rdoc_options: []
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ none: false
124
+ requirements:
125
+ - - ! '>='
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ required_rubygems_version: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ requirements: []
135
+ rubyforge_project:
136
+ rubygems_version: 1.8.23.2
137
+ signing_key:
138
+ specification_version: 3
139
+ summary: simple interface for persistence built on Sequel
140
+ test_files: []