hyperion-api 0.0.1.alpha2 → 0.0.1.alpha3

Sign up to get free protection for your applications and to get access to all the features.
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