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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ad75669d3af7d16418b004a3c6ddea50258d8ae7
4
- data.tar.gz: dc77c4becdffc82ff00016ad6a7f84c49be6965a
3
+ metadata.gz: 75fcb74059583a6a1d2db95b90c205df028f4ca4
4
+ data.tar.gz: f3580ea7b8820ddf78398e0eb241b73f6c66f160
5
5
  SHA512:
6
- metadata.gz: fb4f6e4a305f50191357ff2fa7aed0e962961d12f020210833d45ca0b85ecd401835fb41576d37167ee285462a7355013dfd1309cf0eeeda0c821f9384cc7857
7
- data.tar.gz: f434ceacd8d0c426c2ab251ed547c675602599de999e10f9d2666c907742b3989b1d63ec4fbb5d6148831216df2c8339883506ac03818abcc6d55fd91ee7f1f5
6
+ metadata.gz: 2d8c3d3399690a7214c944a67a6960826d429367326266bac3561f0a5095db8a9285aab13cf348bf9665e80c201ae2c5a459cc6b7c9ab2b6e0a71fea82b6cb6e
7
+ data.tar.gz: e206eb74ba5391dfd7ee5ffad4994cdf7e44e12bbb19fb901f132c7792d2543052244b00eb7100f3219749a411efdf880c4390b16f15ea5640e27796752e0139
@@ -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/inflector'
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 expected_errors
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(options = {})
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 not_implemented_error
96
- self.class.not_implemented_error
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
- record = @context.new(options)
34
- record.save!
35
- entity_class(record.attributes)
36
- rescue ::ActiveRecord::RecordInvalid => e
37
- raise Horza::Errors::RecordInvalid.new(e)
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
- record = @context.find(id)
42
- record.assign_attributes(options)
43
- record.save!
44
- record
45
- rescue ::ActiveRecord::RecordNotFound => e
46
- raise Horza::Errors::RecordNotFound.new(e)
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
- record = @context.find(id)
53
- record.destroy!
54
- true
55
- rescue ::ActiveRecord::RecordNotFound => e
56
- raise Horza::Errors::RecordNotFound.new(e)
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
- result = walk_family_tree(@context.find(options[:id]), options)
59
+ run_and_convert_exceptions do
60
+ result = walk_family_tree(@context.find(options[:id]), options)
61
61
 
62
- return nil unless result
62
+ return nil unless result
63
63
 
64
- collection?(result) ? entity_class(result) : entity_class(result.attributes)
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
@@ -35,6 +35,6 @@ module Horza
35
35
  end
36
36
 
37
37
  class Config
38
- attr_accessor :adapter
38
+ attr_accessor :adapter, :development_mode
39
39
  end
40
40
  end
@@ -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.1
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-03 00:00:00.000000000 Z
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