horza 0.2.1 → 0.2.2
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.
- checksums.yaml +4 -4
- data/lib/horza.rb +3 -1
- data/lib/horza/adapters/abstract_adapter.rb +7 -54
- data/lib/horza/adapters/active_record.rb +33 -32
- data/lib/horza/adapters/class_methods.rb +25 -0
- data/lib/horza/adapters/instance_methods.rb +87 -0
- data/lib/horza/configuration.rb +1 -1
- data/spec/active_record_spec.rb +22 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 75fcb74059583a6a1d2db95b90c205df028f4ca4
|
4
|
+
data.tar.gz: f3580ea7b8820ddf78398e0eb241b73f6c66f160
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2d8c3d3399690a7214c944a67a6960826d429367326266bac3561f0a5095db8a9285aab13cf348bf9665e80c201ae2c5a459cc6b7c9ab2b6e0a71fea82b6cb6e
|
7
|
+
data.tar.gz: e206eb74ba5391dfd7ee5ffad4994cdf7e44e12bbb19fb901f132c7792d2543052244b00eb7100f3219749a411efdf880c4390b16f15ea5640e27796752e0139
|
data/lib/horza.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'horza/adapters/class_methods'
|
2
|
+
require 'horza/adapters/instance_methods'
|
1
3
|
require 'horza/adapters/abstract_adapter'
|
2
4
|
require 'horza/adapters/active_record'
|
3
5
|
require 'horza/core_extensions/string'
|
@@ -6,7 +8,7 @@ require 'horza/entities/collection'
|
|
6
8
|
require 'horza/entities'
|
7
9
|
require 'horza/configuration'
|
8
10
|
require 'horza/errors'
|
9
|
-
require 'active_support
|
11
|
+
require 'active_support'
|
10
12
|
|
11
13
|
module Horza
|
12
14
|
extend Configuration
|
@@ -1,44 +1,25 @@
|
|
1
1
|
module Horza
|
2
2
|
module Adapters
|
3
3
|
class AbstractAdapter
|
4
|
+
extend ::Horza::Adapters::ClassMethods
|
5
|
+
include ::Horza::Adapters::InstanceMethods
|
6
|
+
|
4
7
|
attr_reader :context
|
5
8
|
|
6
9
|
class << self
|
7
|
-
def
|
8
|
-
[::Horza::Errors::RecordNotFound, ::Horza::Errors::RecordInvalid]
|
9
|
-
end
|
10
|
-
|
11
|
-
def context_for_entity(entity)
|
10
|
+
def expected_errors_map
|
12
11
|
not_implemented_error
|
13
12
|
end
|
14
13
|
|
15
14
|
def entity_context_map
|
16
15
|
not_implemented_error
|
17
16
|
end
|
18
|
-
|
19
|
-
def not_implemented_error
|
20
|
-
raise ::Horza::Errors::MethodNotImplemented, 'You must implement this method in your adapter.'
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def initialize(context)
|
25
|
-
@context = context
|
26
17
|
end
|
27
18
|
|
28
|
-
def get(
|
29
|
-
get!(options)
|
30
|
-
rescue *self.class.expected_errors
|
31
|
-
end
|
32
|
-
|
33
|
-
def get!(options = {})
|
19
|
+
def get!(id)
|
34
20
|
not_implemented_error
|
35
21
|
end
|
36
22
|
|
37
|
-
def find_first(options = {})
|
38
|
-
find_first!(options)
|
39
|
-
rescue *self.class.expected_errors
|
40
|
-
end
|
41
|
-
|
42
23
|
def find_first!(options = {})
|
43
24
|
not_implemented_error
|
44
25
|
end
|
@@ -47,29 +28,14 @@ module Horza
|
|
47
28
|
not_implemented_error
|
48
29
|
end
|
49
30
|
|
50
|
-
def create(options = {})
|
51
|
-
create!(options)
|
52
|
-
rescue *self.class.expected_errors
|
53
|
-
end
|
54
|
-
|
55
31
|
def create!(options = {})
|
56
32
|
not_implemented_error
|
57
33
|
end
|
58
34
|
|
59
|
-
def delete(id)
|
60
|
-
delete!(id)
|
61
|
-
rescue *self.class.expected_errors
|
62
|
-
end
|
63
|
-
|
64
35
|
def delete!(id)
|
65
36
|
not_implemented_error
|
66
37
|
end
|
67
38
|
|
68
|
-
def update(id, options = {})
|
69
|
-
update!(id, options)
|
70
|
-
rescue *self.class.expected_errors
|
71
|
-
end
|
72
|
-
|
73
39
|
def update!(id, options = {})
|
74
40
|
not_implemented_error
|
75
41
|
end
|
@@ -78,27 +44,14 @@ module Horza
|
|
78
44
|
not_implemented_error
|
79
45
|
end
|
80
46
|
|
81
|
-
def eager_load(options = {})
|
82
|
-
not_implemented_error
|
83
|
-
end
|
84
|
-
|
85
47
|
def to_hash
|
86
48
|
not_implemented_error
|
87
49
|
end
|
88
50
|
|
89
|
-
def entity_class(res = @context)
|
90
|
-
collection?(res) ? ::Horza::Entities.collection_entity_for(entity_symbol).new(res) : ::Horza::Entities.single_entity_for(entity_symbol).new(res)
|
91
|
-
end
|
92
|
-
|
93
51
|
private
|
94
52
|
|
95
|
-
def
|
96
|
-
|
97
|
-
end
|
98
|
-
|
99
|
-
def entity_symbol
|
100
|
-
klass = @context.name.split('::').last
|
101
|
-
collection? ? klass.pluralize.symbolize : klass.symbolize
|
53
|
+
def collection?
|
54
|
+
not_implemented_error
|
102
55
|
end
|
103
56
|
end
|
104
57
|
end
|
@@ -4,64 +4,65 @@ module Horza
|
|
4
4
|
INVALID_ANCESTRY_MSG = 'Invalid relation. Ensure that the plurality of your associations is correct.'
|
5
5
|
|
6
6
|
class << self
|
7
|
-
def context_for_entity(entity)
|
8
|
-
entity_context_map[entity]
|
9
|
-
end
|
10
|
-
|
11
7
|
def entity_context_map
|
8
|
+
# Rails doesn't preload classes in development mode, caching doesn't make sense
|
9
|
+
return ::Horza.descendants_map(::ActiveRecord::Base) if ::Horza.configuration.development_mode
|
12
10
|
@map ||= ::Horza.descendants_map(::ActiveRecord::Base)
|
13
11
|
end
|
12
|
+
|
13
|
+
def expected_errors_map
|
14
|
+
{
|
15
|
+
::ActiveRecord::RecordNotFound => Horza::Errors::RecordNotFound,
|
16
|
+
::ActiveRecord::RecordInvalid => Horza::Errors::RecordInvalid
|
17
|
+
}
|
18
|
+
end
|
14
19
|
end
|
15
20
|
|
16
21
|
def get!(id)
|
17
|
-
entity_class(@context.find(id).attributes)
|
18
|
-
rescue ::ActiveRecord::RecordNotFound => e
|
19
|
-
raise Horza::Errors::RecordNotFound.new(e)
|
22
|
+
run_and_convert_exceptions { entity_class(@context.find(id).attributes) }
|
20
23
|
end
|
21
24
|
|
22
25
|
def find_first!(options = {})
|
23
|
-
entity_class(base_query(options).first!.attributes)
|
24
|
-
rescue ::ActiveRecord::RecordNotFound => e
|
25
|
-
raise Horza::Errors::RecordNotFound.new(e)
|
26
|
+
run_and_convert_exceptions { entity_class(base_query(options).first!.attributes) }
|
26
27
|
end
|
27
28
|
|
28
29
|
def find_all(options = {})
|
29
|
-
entity_class(base_query(options))
|
30
|
+
run_and_convert_exceptions { entity_class(base_query(options)) }
|
30
31
|
end
|
31
32
|
|
32
33
|
def create!(options = {})
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
run_and_convert_exceptions do
|
35
|
+
record = @context.new(options)
|
36
|
+
record.save!
|
37
|
+
entity_class(record.attributes)
|
38
|
+
end
|
38
39
|
end
|
39
40
|
|
40
41
|
def update!(id, options = {})
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
rescue ::ActiveRecord::RecordInvalid => e
|
48
|
-
raise Horza::Errors::RecordInvalid.new(e)
|
42
|
+
run_and_convert_exceptions do
|
43
|
+
record = @context.find(id)
|
44
|
+
record.assign_attributes(options)
|
45
|
+
record.save!
|
46
|
+
entity_class(record.attributes)
|
47
|
+
end
|
49
48
|
end
|
50
49
|
|
51
50
|
def delete!(id)
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
51
|
+
run_and_convert_exceptions do
|
52
|
+
record = @context.find(id)
|
53
|
+
record.destroy!
|
54
|
+
true
|
55
|
+
end
|
57
56
|
end
|
58
57
|
|
59
58
|
def ancestors(options = {})
|
60
|
-
|
59
|
+
run_and_convert_exceptions do
|
60
|
+
result = walk_family_tree(@context.find(options[:id]), options)
|
61
61
|
|
62
|
-
|
62
|
+
return nil unless result
|
63
63
|
|
64
|
-
|
64
|
+
collection?(result) ? entity_class(result) : entity_class(result.attributes)
|
65
|
+
end
|
65
66
|
end
|
66
67
|
|
67
68
|
def to_hash
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Horza
|
2
|
+
module Adapters
|
3
|
+
module ClassMethods
|
4
|
+
def expected_horza_errors
|
5
|
+
[Horza::Errors::RecordNotFound, Horza::Errors::RecordInvalid]
|
6
|
+
end
|
7
|
+
|
8
|
+
def expected_errors
|
9
|
+
expected_errors_map.keys
|
10
|
+
end
|
11
|
+
|
12
|
+
def horza_error_from_orm_error(orm_error)
|
13
|
+
expected_errors_map[orm_error]
|
14
|
+
end
|
15
|
+
|
16
|
+
def context_for_entity(entity)
|
17
|
+
entity_context_map[entity]
|
18
|
+
end
|
19
|
+
|
20
|
+
def not_implemented_error
|
21
|
+
raise ::Horza::Errors::MethodNotImplemented, 'You must implement this method in your adapter.'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Horza
|
2
|
+
module Adapters
|
3
|
+
module InstanceMethods
|
4
|
+
|
5
|
+
def initialize(context)
|
6
|
+
@context = context
|
7
|
+
end
|
8
|
+
|
9
|
+
def get(id)
|
10
|
+
run_quietly { get!(id) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def find_first(options = {})
|
14
|
+
run_quietly { find_first!(options) }
|
15
|
+
end
|
16
|
+
|
17
|
+
def create(options = {})
|
18
|
+
run_quietly { create!(options) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def delete(id)
|
22
|
+
run_quietly { delete!(id) }
|
23
|
+
end
|
24
|
+
|
25
|
+
def update(id, options = {})
|
26
|
+
run_quietly { update!(id, options) }
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
def run_quietly(&block)
|
32
|
+
block.call
|
33
|
+
rescue *self.class.expected_horza_errors
|
34
|
+
end
|
35
|
+
|
36
|
+
# Execute the code block and convert ORM exceptions into Horza exceptions
|
37
|
+
def run_and_convert_exceptions(&block)
|
38
|
+
block.call
|
39
|
+
rescue *self.class.expected_errors => e
|
40
|
+
raise self.class.horza_error_from_orm_error(e.class)
|
41
|
+
end
|
42
|
+
|
43
|
+
def entity_class(res = @context)
|
44
|
+
collection?(res) ? ::Horza::Entities.collection_entity_for(entity_symbol).new(res) : ::Horza::Entities.single_entity_for(entity_symbol).new(res)
|
45
|
+
end
|
46
|
+
|
47
|
+
def entity_symbol
|
48
|
+
klass = @context.name.split('::').last
|
49
|
+
collection? ? klass.pluralize.symbolize : klass.symbolize
|
50
|
+
end
|
51
|
+
|
52
|
+
# given an options hash,
|
53
|
+
# with optional :conditions, :order, :limit and :offset keys,
|
54
|
+
# returns conditions, normalized order, limit and offset
|
55
|
+
def extract_conditions!(options = {})
|
56
|
+
order = normalize_order(options.delete(:order))
|
57
|
+
limit = options.delete(:limit)
|
58
|
+
offset = options.delete(:offset)
|
59
|
+
conditions = options.delete(:conditions) || options
|
60
|
+
|
61
|
+
[conditions, order, limit, offset]
|
62
|
+
end
|
63
|
+
|
64
|
+
# given an order argument, returns an array of pairs, with each pair containing the attribute, and :asc or :desc
|
65
|
+
def normalize_order(order)
|
66
|
+
order = Array(order)
|
67
|
+
|
68
|
+
if order.length == 2 && !order[0].is_a?(Array) && [:asc, :desc].include?(order[1])
|
69
|
+
order = [order]
|
70
|
+
else
|
71
|
+
order = order.map {|pair| pair.is_a?(Array) ? pair : [pair, :asc] }
|
72
|
+
end
|
73
|
+
|
74
|
+
order.each do |pair|
|
75
|
+
pair.length == 2 or raise ArgumentError, "each order clause must be a pair (unknown clause #{pair.inspect})"
|
76
|
+
[:asc, :desc].include?(pair[1]) or raise ArgumentError, "order must be specified with :asc or :desc (unknown key #{pair[1].inspect})"
|
77
|
+
end
|
78
|
+
|
79
|
+
order
|
80
|
+
end
|
81
|
+
|
82
|
+
def not_implemented_error
|
83
|
+
self.class.not_implemented_error
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
data/lib/horza/configuration.rb
CHANGED
data/spec/active_record_spec.rb
CHANGED
@@ -59,6 +59,28 @@ describe Horza do
|
|
59
59
|
HorzaSpec::Employer.delete_all
|
60
60
|
end
|
61
61
|
|
62
|
+
context '#context_for_entity' do
|
63
|
+
it 'Returns correct class' do
|
64
|
+
expect(Horza.adapter.context_for_entity(:user)).to eq HorzaSpec::User
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'in development mode' do
|
68
|
+
before do
|
69
|
+
Horza.reset
|
70
|
+
Horza.configure do |config|
|
71
|
+
config.adapter = adapter
|
72
|
+
config.development_mode = true
|
73
|
+
end
|
74
|
+
end
|
75
|
+
after do
|
76
|
+
Horza.reset
|
77
|
+
end
|
78
|
+
it 'Returns correct class' do
|
79
|
+
expect(Horza.adapter.context_for_entity(:user)).to eq HorzaSpec::User
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
62
84
|
describe '#adapter' do
|
63
85
|
let(:user) { HorzaSpec::User.create }
|
64
86
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: horza
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Blake Turner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-06-
|
11
|
+
date: 2015-06-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hashie
|
@@ -106,6 +106,8 @@ files:
|
|
106
106
|
- lib/horza.rb
|
107
107
|
- lib/horza/adapters/abstract_adapter.rb
|
108
108
|
- lib/horza/adapters/active_record.rb
|
109
|
+
- lib/horza/adapters/class_methods.rb
|
110
|
+
- lib/horza/adapters/instance_methods.rb
|
109
111
|
- lib/horza/configuration.rb
|
110
112
|
- lib/horza/core_extensions/string.rb
|
111
113
|
- lib/horza/entities.rb
|