hyperion-api 0.0.1.alpha2 → 0.0.1.alpha3

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.
data/lib/hyperion/api.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'hyperion/query'
2
2
  require 'hyperion/filter'
3
3
  require 'hyperion/sort'
4
+ require 'hyperion/util'
4
5
 
5
6
  module Hyperion
6
7
  class API
@@ -19,6 +20,23 @@ module Hyperion
19
20
  Thread.current[:datastore] || raise('No Datastore installed')
20
21
  end
21
22
 
23
+ # Assigns the datastore within the given block
24
+ def with_datastore(name, opts={})
25
+ self.datastore = new_datastore(name, opts)
26
+ yield
27
+ self.datastore = nil
28
+ end
29
+
30
+ def new_datastore(name, opts={})
31
+ begin
32
+ require "hyperion/#{name}"
33
+ rescue LoadError
34
+ raise "Can't find datastore implementation: #{name}"
35
+ end
36
+ ds_klass = Hyperion.const_get(Util.class_name(name.to_s))
37
+ ds_klass.new(opts)
38
+ end
39
+
22
40
  # Saves a record. Any additional parameters will get merged onto the record before it is saved.
23
41
 
24
42
  # Hyperion::API.save({:kind => :foo})
@@ -0,0 +1,111 @@
1
+ require 'hyperion/api'
2
+
3
+ module Hyperion
4
+ class Memory
5
+
6
+ def initialize(opts={})
7
+ @id_counter = 0
8
+ @store = {}
9
+ end
10
+
11
+ def save(records)
12
+ records.map do |record|
13
+ key = API.new?(record) ? generate_key : record[:key]
14
+ record[:key] = key
15
+ store[key] = record
16
+ record
17
+ end
18
+ end
19
+
20
+ def find_by_key(key)
21
+ store[key]
22
+ end
23
+
24
+ def find(query)
25
+ records = store.values
26
+ records = filter_kind(query.kind, records)
27
+ records = apply_filters(query.filters, records)
28
+ records = apply_sorts(query.sorts, records)
29
+ records = apply_offset(query.offset, records)
30
+ records = apply_limit(query.limit, records)
31
+ records
32
+ end
33
+
34
+ def delete_by_key(key)
35
+ store.delete(key)
36
+ nil
37
+ end
38
+
39
+ def delete(query)
40
+ records = find(query)
41
+ store.delete_if do |key, record|
42
+ records.include?(record)
43
+ end
44
+ nil
45
+ end
46
+
47
+ def count(query)
48
+ find(query).length
49
+ end
50
+
51
+ private
52
+
53
+ attr_reader :store
54
+
55
+ def filter_kind(kind, records)
56
+ records.select do |record|
57
+ record[:kind] == kind
58
+ end
59
+ end
60
+
61
+ def apply_filters(filters, records)
62
+ records.select do |record|
63
+ filters.all? do |filter|
64
+ value = record[filter.field]
65
+ case filter.operator
66
+ when '<'; value < filter.value
67
+ when '<='; value <= filter.value
68
+ when '>'; value > filter.value
69
+ when '>='; value >= filter.value
70
+ when '='; value == filter.value
71
+ when '!='; value != filter.value
72
+ when 'contains?'; filter.value.include?(value)
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ def apply_sorts(sorts, records)
79
+ records.sort { |record1, record2| compare_records record1, record2, sorts }
80
+ end
81
+
82
+ def compare_records(record1, record2, sorts)
83
+ sorts.each do |sort|
84
+ result = compare_record record1, record2, sort
85
+ return result if result
86
+ end
87
+ 0
88
+ end
89
+
90
+ def compare_record(record1, record2, sort)
91
+ field1, field2 = record1[sort.field], record2[sort.field]
92
+ field1 == field2 ? nil :
93
+ field1 < field2 && sort.ascending? ? -1 :
94
+ field1 > field2 && sort.descending? ? -1 : 1
95
+ end
96
+
97
+ def generate_key
98
+ @id_counter += 1
99
+ end
100
+
101
+ def apply_offset(offset, records)
102
+ return records unless offset
103
+ records.drop offset
104
+ end
105
+
106
+ def apply_limit(limit, records)
107
+ return records unless limit
108
+ records.take(limit)
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,19 @@
1
+ module Hyperion
2
+ class Util
3
+
4
+ class << self
5
+
6
+ def camel_case(str)
7
+ str.gsub(/[_| |\-][A-Za-z]/) { |a| a[1..-1].upcase }
8
+ end
9
+
10
+ def class_name(str)
11
+ cameled = camel_case(str)
12
+ cameled[0] = cameled[0].capitalize
13
+ cameled
14
+ end
15
+
16
+ end
17
+
18
+ end
19
+ end
@@ -14,6 +14,16 @@ describe Hyperion::API do
14
14
  end
15
15
  end
16
16
 
17
+ context 'factory' do
18
+ it 'bombs on unknown implementations' do
19
+ expect {api.new_datastore(:unknown)}.to raise_error("Can't find datastore implementation: unknown")
20
+ end
21
+
22
+ it 'creates a memory datastore' do
23
+ api.new_datastore(:memory).class.should == Hyperion::Memory
24
+ end
25
+ end
26
+
17
27
  context 'new?' do
18
28
  it 'false if a record exists' do
19
29
  api.new?({:key => 1}).should be_false
@@ -27,9 +37,14 @@ describe Hyperion::API do
27
37
  context 'with fake datastore' do
28
38
  attr_reader :fake_ds
29
39
 
30
- before :each do
31
- @fake_ds = FakeDatastore.new
32
- api.datastore = @fake_ds
40
+ def fake_ds
41
+ Thread.current[:datastore]
42
+ end
43
+
44
+ around :each do |example|
45
+ api.with_datastore(:fake_ds) do
46
+ example.run
47
+ end
33
48
  end
34
49
 
35
50
  context 'save' do
@@ -1,43 +1,44 @@
1
- class FakeDatastore
1
+ module Hyperion
2
+ class FakeDs
3
+
4
+ attr_accessor :saved_records, :queries, :key_queries, :returns
5
+
6
+ def initialize(opts={})
7
+ @saved_records = []
8
+ @returns = []
9
+ @queries = []
10
+ @key_queries = []
11
+ end
12
+
13
+ def save(records)
14
+ @saved_records += records
15
+ returns.shift || []
16
+ end
17
+
18
+ def find_by_key(key)
19
+ @key_queries << key
20
+ returns.shift || nil
21
+ end
22
+
23
+ def find(query)
24
+ @queries << query
25
+ returns.shift || []
26
+ end
27
+
28
+ def delete_by_key(key)
29
+ @key_queries << key
30
+ nil
31
+ end
32
+
33
+ def delete(query)
34
+ @queries << query
35
+ returns.shift || nil
36
+ end
37
+
38
+ def count(query)
39
+ @queries << query
40
+ returns.shift || 0
41
+ end
2
42
 
3
- attr_accessor :saved_records, :queries, :key_queries, :returns
4
-
5
- def initialize
6
- @saved_records = []
7
- @returns = []
8
- @queries = []
9
- @key_queries = []
10
- end
11
-
12
- def save(records)
13
- @saved_records += records
14
- returns.shift || []
15
- end
16
-
17
- def find_by_key(key)
18
- @key_queries << key
19
- returns.shift || nil
20
- end
21
-
22
- def find(query)
23
- @queries << query
24
- returns.shift || []
25
43
  end
26
-
27
- def delete_by_key(key)
28
- @key_queries << key
29
- nil
30
- end
31
-
32
- def delete(query)
33
- @queries << query
34
- returns.shift || nil
35
- end
36
-
37
- def count(query)
38
- @queries << query
39
- returns.shift || 0
40
- end
41
-
42
44
  end
43
-
@@ -0,0 +1,13 @@
1
+ require 'hyperion/memory'
2
+ require 'hyperion/dev/ds_spec'
3
+
4
+ describe Hyperion::Memory do
5
+
6
+ around :each do |example|
7
+ Hyperion::API.with_datastore(:memory) do
8
+ example.run
9
+ end
10
+ end
11
+
12
+ it_behaves_like 'Datastore'
13
+ end
@@ -0,0 +1,30 @@
1
+ require 'hyperion/util'
2
+
3
+ describe Hyperion::Util do
4
+
5
+ def util
6
+ Hyperion::Util
7
+ end
8
+
9
+ it 'camel cases words' do
10
+ util.camel_case('fake_ds').should == 'fakeDs'
11
+ util.camel_case('defaultSceneName').should == 'defaultSceneName'
12
+ util.camel_case('set defaultSceneName').should == 'setDefaultSceneName'
13
+ util.camel_case('class_name').should == 'className'
14
+ util.camel_case('once_upon_a_time').should == 'onceUponATime'
15
+ util.camel_case('with spaces').should == 'withSpaces'
16
+ util.camel_case('with-dash').should == 'withDash'
17
+ util.camel_case('starting Capital').should == 'startingCapital'
18
+ end
19
+
20
+ it 'converts to class name' do
21
+ util.class_name('fake_ds').should == 'FakeDs'
22
+ util.class_name('defaultSceneName').should == 'DefaultSceneName'
23
+ util.class_name('set defaultSceneName').should == 'SetDefaultSceneName'
24
+ util.class_name('class_name').should == 'ClassName'
25
+ util.class_name('once_upon_a_time').should == 'OnceUponATime'
26
+ util.class_name('with spaces').should == 'WithSpaces'
27
+ util.class_name('with-dash').should == 'WithDash'
28
+ util.class_name('starting Capital').should == 'StartingCapital'
29
+ end
30
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hyperion-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.alpha2
4
+ version: 0.0.1.alpha3
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -46,20 +46,23 @@ dependencies:
46
46
  description: A Generic Persistence API for Ruby
47
47
  email:
48
48
  - myles@8thlight.com
49
+ - skim@8thlight.com
49
50
  executables: []
50
51
  extensions: []
51
52
  extra_rdoc_files: []
52
53
  files:
53
- - lib/hyperion/dev/memory.rb
54
54
  - lib/hyperion/dev/ds_spec.rb
55
+ - lib/hyperion/util.rb
55
56
  - lib/hyperion/filter.rb
56
57
  - lib/hyperion/api.rb
57
58
  - lib/hyperion/key.rb
59
+ - lib/hyperion/memory.rb
58
60
  - lib/hyperion/sort.rb
59
61
  - lib/hyperion/query.rb
60
- - spec/hyperion/dev/memory_spec.rb
62
+ - spec/hyperion/util_spec.rb
61
63
  - spec/hyperion/key_spec.rb
62
64
  - spec/hyperion/shared_examples.rb
65
+ - spec/hyperion/memory_spec.rb
63
66
  - spec/hyperion/api_spec.rb
64
67
  - spec/hyperion/fake_ds.rb
65
68
  homepage: https://github.com/mylesmegyesi/hyperion-ruby
@@ -88,8 +91,9 @@ signing_key:
88
91
  specification_version: 3
89
92
  summary: A Generic Persistence API for Ruby
90
93
  test_files:
91
- - spec/hyperion/dev/memory_spec.rb
94
+ - spec/hyperion/util_spec.rb
92
95
  - spec/hyperion/key_spec.rb
93
96
  - spec/hyperion/shared_examples.rb
97
+ - spec/hyperion/memory_spec.rb
94
98
  - spec/hyperion/api_spec.rb
95
99
  - spec/hyperion/fake_ds.rb
@@ -1,113 +0,0 @@
1
- require 'hyperion/api'
2
-
3
- module Hyperion
4
- module Dev
5
- class Memory
6
-
7
- def initialize
8
- @id_counter = 0
9
- @store = {}
10
- end
11
-
12
- def save(records)
13
- records.map do |record|
14
- key = API.new?(record) ? generate_key : record[:key]
15
- record[:key] = key
16
- store[key] = record
17
- record
18
- end
19
- end
20
-
21
- def find_by_key(key)
22
- store[key]
23
- end
24
-
25
- def find(query)
26
- records = store.values
27
- records = filter_kind(query.kind, records)
28
- records = apply_filters(query.filters, records)
29
- records = apply_sorts(query.sorts, records)
30
- records = apply_offset(query.offset, records)
31
- records = apply_limit(query.limit, records)
32
- records
33
- end
34
-
35
- def delete_by_key(key)
36
- store.delete(key)
37
- nil
38
- end
39
-
40
- def delete(query)
41
- records = find(query)
42
- store.delete_if do |key, record|
43
- records.include?(record)
44
- end
45
- nil
46
- end
47
-
48
- def count(query)
49
- find(query).length
50
- end
51
-
52
- private
53
-
54
- attr_reader :store
55
-
56
- def filter_kind(kind, records)
57
- records.select do |record|
58
- record[:kind] == kind
59
- end
60
- end
61
-
62
- def apply_filters(filters, records)
63
- records.select do |record|
64
- filters.all? do |filter|
65
- value = record[filter.field]
66
- case filter.operator
67
- when '<'; value < filter.value
68
- when '<='; value <= filter.value
69
- when '>'; value > filter.value
70
- when '>='; value >= filter.value
71
- when '='; value == filter.value
72
- when '!='; value != filter.value
73
- when 'contains?'; filter.value.include?(value)
74
- end
75
- end
76
- end
77
- end
78
-
79
- def apply_sorts(sorts, records)
80
- records.sort { |record1, record2| compare_records record1, record2, sorts }
81
- end
82
-
83
- def compare_records(record1, record2, sorts)
84
- sorts.each do |sort|
85
- result = compare_record record1, record2, sort
86
- return result if result
87
- end
88
- 0
89
- end
90
-
91
- def compare_record(record1, record2, sort)
92
- field1, field2 = record1[sort.field], record2[sort.field]
93
- field1 == field2 ? nil :
94
- field1 < field2 && sort.ascending? ? -1 :
95
- field1 > field2 && sort.descending? ? -1 : 1
96
- end
97
-
98
- def generate_key
99
- @id_counter += 1
100
- end
101
-
102
- def apply_offset(offset, records)
103
- return records unless offset
104
- records.drop offset
105
- end
106
-
107
- def apply_limit(limit, records)
108
- return records unless limit
109
- records.take(limit)
110
- end
111
- end
112
- end
113
- end
@@ -1,11 +0,0 @@
1
- require 'hyperion/dev/memory'
2
- require 'hyperion/dev/ds_spec'
3
-
4
- describe Hyperion::Dev::Memory do
5
-
6
- before :each do
7
- Hyperion::API.datastore = Hyperion::Dev::Memory.new
8
- end
9
-
10
- it_behaves_like 'Datastore'
11
- end