horza 0.2.2 → 0.3.0

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: 75fcb74059583a6a1d2db95b90c205df028f4ca4
4
- data.tar.gz: f3580ea7b8820ddf78398e0eb241b73f6c66f160
3
+ metadata.gz: 2e84ae0d471c92bf87ccaa0894984e2eb1b874b3
4
+ data.tar.gz: 82a91f1e8c57dfcef55e900824509357d28bd955
5
5
  SHA512:
6
- metadata.gz: 2d8c3d3399690a7214c944a67a6960826d429367326266bac3561f0a5095db8a9285aab13cf348bf9665e80c201ae2c5a459cc6b7c9ab2b6e0a71fea82b6cb6e
7
- data.tar.gz: e206eb74ba5391dfd7ee5ffad4994cdf7e44e12bbb19fb901f132c7792d2543052244b00eb7100f3219749a411efdf880c4390b16f15ea5640e27796752e0139
6
+ metadata.gz: 4a9b216d669260c8bb880c5ee0bb97501a736709841cbffc05b34028f0e0b5f250b5eab7ef7205abdeb0c57d1df1c66b328313a6d899fd86e32f52b35a6660cb
7
+ data.tar.gz: 06458d7480062e516133d9e0f557ec299c1cda2a936d040cf1f096a51cfe694a934138bd3f2912dd0fbad2aeae5b4242b22ec6a1f2233890aab4981246e929ba
data/README.md CHANGED
@@ -16,22 +16,59 @@ end
16
16
  **Get Adapter for your ORM Object**
17
17
  ```ruby
18
18
  # ActiveRecord Example
19
- # Don't worry, We don't actually call things horza_users in our codebase, this is just for emphasis
20
- horza_user = Horza.adapt(User)
19
+ user = Horza.adapt(User)
21
20
 
22
21
  # Examples
23
- horza_user.get(id) # Find by id - Return nil on fail
24
- horza_user.get!(id) # Find by id - Error on fail
25
- horza_user.find_first(params) # Find 1 user - Orders by id desc by default - Return nil on fail
26
- horza_user.find_first!(params) # Find 1 user - Orders by id desc by default - Error nil on fail
27
- horza_user.find_all(params) # Find all users that match parameters
28
- horza_user.create(params) # Create record - return nil on fail
29
- horza_user.create!(params) # Create record - raise error on fail
30
- horza_user.update(params) # Update record - return nil on fail
31
- horza_user.update!(params) # Update record - raise error on fail
32
- horza_user.delete(params) # Delete record - return nil on fail
33
- horza_user.delete!(params) # Delete record - raise error on fail
34
- horza_user.ancestors(target: :employer, via: []) # Traverse relations
22
+ user.get(id) # Find by id - Return nil on fail
23
+ user.get!(id) # Find by id - Error on fail
24
+ user.find_first(options) # Find 1 user - Orders by id desc by default - Return nil on fail
25
+ user.find_first!(options) # Find 1 user - Orders by id desc by default - Error nil on fail
26
+ user.find_all(options) # Find all users that match parameters
27
+ user.create(options) # Create record - return nil on fail
28
+ user.create!(options) # Create record - raise error on fail
29
+ user.update(options) # Update record - return nil on fail
30
+ user.update!(options) # Update record - raise error on fail
31
+ user.delete(options) # Delete record - return nil on fail
32
+ user.delete!(options) # Delete record - raise error on fail
33
+ user.association(target: :employer, via: []) # Traverse association
34
+ ```
35
+
36
+ ## Options
37
+
38
+ **Base Options**
39
+
40
+ Key | Type | Details
41
+ ___ | ____ | _______
42
+ `conditions` | Hash | Key value pairs for the query
43
+ `order` | Hash | { `field` => `:asc`/`:desc` }
44
+ `limit` | Integer | Number of records to return
45
+ `offset` | Integer | Number of records to offset
46
+ `id` | Integer | The id of the root object (associations only)
47
+ `target` | Symbol | The target of the association - ie. employer.users would have a target of :users (associations only)
48
+ `eager_load` | Boolean | Whether to eager_load the association (associations only)
49
+
50
+ **Association Options**
51
+
52
+ Key | Type | Details
53
+ ___ | ____ | _______
54
+ `id` | Integer | The id of the root object
55
+ `target` | Symbol | The target of the association - ie. employer.users would have a target of :users
56
+ `eager_load` | Boolean | Whether to eager_load the association
57
+
58
+ ```ruby
59
+ conditions = { last_name: 'Turner' }
60
+
61
+ # Ordering
62
+ user.find_all(conditions: conditions, order: { last_name: :desc })
63
+
64
+ # Limiting
65
+ user.find_all(conditions: conditions, limit: 20)
66
+
67
+ # Offset
68
+ user.find_all(conditions: conditions, offset: 50)
69
+
70
+ # Eager loading associations
71
+ user.association(target: :sports_cars, via: [:employer], conditions: { make: 'Audi' }, eager_load: true)
35
72
  ```
36
73
 
37
74
  ## Outputs
@@ -42,7 +79,7 @@ Collection entities behave like arrays.
42
79
 
43
80
  ```ruby
44
81
  # Singular Entity
45
- result = horza_user.find_first(first_name: 'Blake')
82
+ result = user.find_first(first_name: 'Blake')
46
83
 
47
84
  result # => {"id"=>1, "first_name"=>"Blake", "last_name"=>"Turner", "employer_id"=>1}
48
85
  result.class.name # => "Horza::Entities::Single"
@@ -51,7 +88,7 @@ result.id # => 1
51
88
  result.id? # => true
52
89
 
53
90
  # Collection Entity
54
- result = horza_user.find_all(last_name: 'Turner')
91
+ result = user.find_all(last_name: 'Turner')
55
92
 
56
93
  result.class.name # => "Horza::Entities::Collection"
57
94
  result.length # => 1
@@ -3,6 +3,7 @@ module Horza
3
3
  class AbstractAdapter
4
4
  extend ::Horza::Adapters::ClassMethods
5
5
  include ::Horza::Adapters::InstanceMethods
6
+ extend ActiveSupport::DescendantsTracker
6
7
 
7
8
  attr_reader :context
8
9
 
@@ -40,7 +41,7 @@ module Horza
40
41
  not_implemented_error
41
42
  end
42
43
 
43
- def ancestors(options = {})
44
+ def association(options = {})
44
45
  not_implemented_error
45
46
  end
46
47
 
@@ -23,11 +23,11 @@ module Horza
23
23
  end
24
24
 
25
25
  def find_first!(options = {})
26
- run_and_convert_exceptions { entity_class(base_query(options).first!.attributes) }
26
+ run_and_convert_exceptions { entity_class(query(options).first!.attributes) }
27
27
  end
28
28
 
29
29
  def find_all(options = {})
30
- run_and_convert_exceptions { entity_class(base_query(options)) }
30
+ run_and_convert_exceptions { entity_class(query(options)) }
31
31
  end
32
32
 
33
33
  def create!(options = {})
@@ -55,13 +55,18 @@ module Horza
55
55
  end
56
56
  end
57
57
 
58
- def ancestors(options = {})
58
+ def association(options = {})
59
59
  run_and_convert_exceptions do
60
- result = walk_family_tree(@context.find(options[:id]), options)
60
+ options = Options.new(options)
61
61
 
62
+ base = @context
63
+ base = base.includes(options.eager_args) if options.eager_load?
64
+ base = base.find(options.id)
65
+
66
+ result = walk_family_tree(base, options)
62
67
  return nil unless result
63
68
 
64
- collection?(result) ? entity_class(result) : entity_class(result.attributes)
69
+ collection?(result) ? entity_class(query(options, result)) : entity_class(result.attributes)
65
70
  end
66
71
  end
67
72
 
@@ -73,8 +78,15 @@ module Horza
73
78
 
74
79
  private
75
80
 
76
- def base_query(options)
77
- @context.where(options).order('ID DESC')
81
+ def query(options, base = @context)
82
+ options = options.is_a?(Options) ? options : Options.new(options)
83
+
84
+ result = base
85
+ result = base.where(options.conditions) if options.conditions
86
+ result = result.order(base.arel_table[options.order_field].send(options.order_direction))
87
+ result = result.limit(options.limit) if options.limit
88
+ result = result.offset(options.offset) if options.offset
89
+ result
78
90
  end
79
91
 
80
92
  def collection?(subject = @context)
@@ -82,8 +94,9 @@ module Horza
82
94
  end
83
95
 
84
96
  def walk_family_tree(object, options)
85
- via = options[:via] || []
86
- via.push(options[:target]).reduce(object) do |object, relation|
97
+ via = options.via || []
98
+
99
+ via.push(options.target).reduce(object) do |object, relation|
87
100
  raise ::Horza::Errors::InvalidAncestry.new(INVALID_ANCESTRY_MSG) unless object.respond_to? relation
88
101
  object.send(relation)
89
102
  end
@@ -0,0 +1,45 @@
1
+ module Horza
2
+ module Adapters
3
+ class Options
4
+ META_METHODS = [:conditions, :limit, :offset, :order, :target, :id, :via]
5
+
6
+ def initialize(options)
7
+ @options = options
8
+ end
9
+
10
+ def method_missing(method)
11
+ super unless META_METHODS.include? method
12
+ @options[method]
13
+ end
14
+
15
+ def order_field
16
+ return :id unless order.present?
17
+ @options[:order].keys.first
18
+ end
19
+
20
+ def order_direction
21
+ return :desc unless order.present?
22
+
23
+ raise ::Horza::Errors::InvalidOption.new('Order must be :asc or :desc') unless [:asc, :desc].include?(@options[:order][order_field])
24
+ order[order_field]
25
+ end
26
+
27
+ def eager_load?
28
+ !!@options[:eager_load]
29
+ end
30
+
31
+ def eager_args
32
+ raise ::Horza::Errors::InvalidOption.new('You must pass eager_load: true and defined a target') unless eager_load? && target
33
+ return target unless via
34
+
35
+ via.reverse.reduce({}) do |hash, table|
36
+ if hash.empty?
37
+ hash.merge(table => target)
38
+ else
39
+ { table => hash }
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -21,16 +21,7 @@ module Horza
21
21
  end
22
22
 
23
23
  def adapter_map
24
- @adapter_map ||= generate_map
25
- end
26
-
27
- private
28
-
29
- def generate_map
30
- ::Horza::Adapters::AbstractAdapter.descendants.reduce({}) do |hash, (klass)|
31
- return hash unless klass.name
32
- hash.merge(klass.name.split('::').last.underscore.to_sym => klass)
33
- end
24
+ @adapter_map ||= ::Horza.descendants_map(::Horza::Adapters::AbstractAdapter)
34
25
  end
35
26
  end
36
27
 
@@ -12,6 +12,14 @@ module Horza
12
12
  def symbolize
13
13
  underscore.to_sym
14
14
  end
15
+
16
+ def underscore
17
+ gsub(/::/, '/')
18
+ .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
19
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
20
+ .tr('-', '_')
21
+ .downcase
22
+ end
15
23
  end
16
24
  end
17
25
  end
data/lib/horza/errors.rb CHANGED
@@ -20,5 +20,8 @@ module Horza
20
20
 
21
21
  class RecordNotFound < StandardError
22
22
  end
23
+
24
+ class InvalidOption < StandardError
25
+ end
23
26
  end
24
27
  end
data/lib/horza.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'horza/adapters/class_methods'
2
2
  require 'horza/adapters/instance_methods'
3
+ require 'horza/adapters/options'
3
4
  require 'horza/adapters/abstract_adapter'
4
5
  require 'horza/adapters/active_record'
5
6
  require 'horza/core_extensions/string'
@@ -8,7 +9,7 @@ require 'horza/entities/collection'
8
9
  require 'horza/entities'
9
10
  require 'horza/configuration'
10
11
  require 'horza/errors'
11
- require 'active_support'
12
+ require 'active_support/inflections'
12
13
 
13
14
  module Horza
14
15
  extend Configuration
@@ -17,5 +18,9 @@ module Horza
17
18
  def descendants_map(klass)
18
19
  klass.descendants.reduce({}) { |hash, (klass)| hash.merge(klass.name.split('::').last.underscore.to_sym => klass) }
19
20
  end
21
+
22
+ def adapt(klass)
23
+ adapter.new(klass)
24
+ end
20
25
  end
21
26
  end
@@ -47,10 +47,10 @@ end
47
47
  describe Horza do
48
48
  let(:last_name) { 'Turner' }
49
49
  let(:adapter) { :active_record }
50
- let(:user_adapter) { Horza.adapter.new(HorzaSpec::User) }
51
- let(:customer_adapter) { Horza.adapter.new(HorzaSpec::Customer) }
52
- let(:employer_adapter) { Horza.adapter.new(HorzaSpec::Employer) }
53
- let(:sports_car_adapter) { Horza.adapter.new(HorzaSpec::SportsCar) }
50
+ let(:user_adapter) { Horza.adapt(HorzaSpec::User) }
51
+ let(:customer_adapter) { Horza.adapt(HorzaSpec::Customer) }
52
+ let(:employer_adapter) { Horza.adapt(HorzaSpec::Employer) }
53
+ let(:sports_car_adapter) { Horza.adapt(HorzaSpec::SportsCar) }
54
54
 
55
55
  # Reset base config with each iteration
56
56
  before { Horza.configure { |config| config.adapter = adapter } }
@@ -81,7 +81,17 @@ describe Horza do
81
81
  end
82
82
  end
83
83
 
84
- describe '#adapter' do
84
+ describe '#adapt' do
85
+ subject { Horza.adapt(HorzaSpec::User) }
86
+ it 'returns the adaptor class' do
87
+ expect(subject.is_a? Horza::Adapters::ActiveRecord).to be true
88
+ end
89
+ it 'sets the model as context' do
90
+ expect(subject.context).to eq HorzaSpec::User
91
+ end
92
+ end
93
+
94
+ describe 'Queries' do
85
95
  let(:user) { HorzaSpec::User.create }
86
96
 
87
97
  describe '#get!' do
@@ -119,17 +129,17 @@ describe Horza do
119
129
  2.times { HorzaSpec::User.create(last_name: 'OTHER') }
120
130
  end
121
131
  it 'returns single Entity' do
122
- expect(user_adapter.find_first(last_name: last_name).is_a? Horza::Entities::Single).to be true
132
+ expect(user_adapter.find_first(conditions: { last_name: last_name }).is_a? Horza::Entities::Single).to be true
123
133
  end
124
134
 
125
135
  it 'returns user' do
126
- expect(user_adapter.find_first!(last_name: last_name).to_h).to eq HorzaSpec::User.where(last_name: last_name).order('id DESC').first.attributes
136
+ expect(user_adapter.find_first!(conditions: { last_name: last_name }).to_h).to eq HorzaSpec::User.where(last_name: last_name).order('id DESC').first.attributes
127
137
  end
128
138
  end
129
139
 
130
140
  context 'when user does not exist' do
131
141
  it 'throws error' do
132
- expect { user_adapter.find_first!(last_name: last_name) }.to raise_error Horza::Errors::RecordNotFound
142
+ expect { user_adapter.find_first!(conditions: { last_name: last_name }) }.to raise_error Horza::Errors::RecordNotFound
133
143
  end
134
144
  end
135
145
  end
@@ -137,25 +147,45 @@ describe Horza do
137
147
  describe '#find_first' do
138
148
  context 'when user does not exist' do
139
149
  it 'returns nil' do
140
- expect(user_adapter.find_first(last_name: last_name)).to be nil
150
+ expect(user_adapter.find_first(conditions: { last_name: last_name })).to be nil
141
151
  end
142
152
  end
143
153
  end
144
154
 
145
155
  describe '#find_all' do
156
+ let(:conditions) { { last_name: last_name } }
157
+ let(:options) { { conditions: conditions } }
158
+
146
159
  context 'when users exist' do
147
160
  before do
148
- 3.times { HorzaSpec::User.create(last_name: last_name) }
161
+ 3.times { HorzaSpec::User.create(conditions) }
149
162
  2.times { HorzaSpec::User.create(last_name: 'OTHER') }
150
163
  end
151
164
  it 'returns user' do
152
- expect(user_adapter.find_all(last_name: last_name).length).to eq 3
165
+ expect(user_adapter.find_all(options).length).to eq 3
166
+ end
167
+
168
+ context 'with limit' do
169
+ it 'limits response' do
170
+ expect(user_adapter.find_all(options.merge(limit: 2)).length).to eq 2
171
+ end
172
+ end
173
+
174
+ context 'with offset' do
175
+ let(:total) { 20 }
176
+ let(:offset) { 7 }
177
+ before do
178
+ total.times { HorzaSpec::User.create(last_name: 'Smith') }
179
+ end
180
+ it 'offsets response' do
181
+ expect(user_adapter.find_all(conditions: { last_name: 'Smith' }, offset: offset).length).to eq total - offset
182
+ end
153
183
  end
154
184
  end
155
185
 
156
186
  context 'when user does not exist' do
157
187
  it 'throws error' do
158
- expect(user_adapter.find_all(last_name: last_name).empty?).to be true
188
+ expect(user_adapter.find_all(options).empty?).to be true
159
189
  end
160
190
  end
161
191
  end
@@ -262,7 +292,7 @@ describe Horza do
262
292
  end
263
293
  end
264
294
 
265
- context '#ancestors' do
295
+ context '#association' do
266
296
  context 'direct relation' do
267
297
  let(:employer) { HorzaSpec::Employer.create }
268
298
  let!(:user1) { HorzaSpec::User.create(employer: employer) }
@@ -270,36 +300,85 @@ describe Horza do
270
300
 
271
301
  context 'parent' do
272
302
  it 'returns parent' do
273
- expect(user_adapter.ancestors(id: user1.id, target: :employer).to_h).to eq employer.attributes
303
+ expect(user_adapter.association(id: user1.id, target: :employer).to_h).to eq employer.attributes
274
304
  end
275
305
  end
276
306
 
277
307
  context 'children' do
278
308
  it 'returns children' do
279
- result = employer_adapter.ancestors(id: employer.id, target: :users)
309
+ result = employer_adapter.association(id: employer.id, target: :users)
280
310
  expect(result.length).to eq 2
281
311
  expect(result.first.is_a? Horza::Entities::Single).to be true
282
- expect(result.first.to_hash).to eq HorzaSpec::User.order('id DESC').last.attributes
312
+ expect(result.first.to_hash).to eq HorzaSpec::User.order('id DESC').first.attributes
283
313
  end
284
314
  end
285
315
 
286
316
  context 'invalid ancestry' do
287
317
  it 'throws error' do
288
- expect { employer_adapter.ancestors(id: employer.id, target: :user) }.to raise_error Horza::Errors::InvalidAncestry
318
+ expect { employer_adapter.association(id: employer.id, target: :user) }.to raise_error Horza::Errors::InvalidAncestry
289
319
  end
290
320
  end
291
321
 
292
322
  context 'valid ancestry with no saved childred' do
293
323
  let(:employer2) { HorzaSpec::Employer.create }
294
324
  it 'returns empty collection error' do
295
- expect(employer_adapter.ancestors(id: employer2.id, target: :users).empty?).to be true
325
+ expect(employer_adapter.association(id: employer2.id, target: :users).empty?).to be true
296
326
  end
297
327
  end
298
328
 
299
329
  context 'valid ancestry with no saved parent' do
300
330
  let(:user2) { HorzaSpec::User.create }
301
331
  it 'returns nil' do
302
- expect(user_adapter.ancestors(id: user2.id, target: :employer)).to be nil
332
+ expect(user_adapter.association(id: user2.id, target: :employer)).to be nil
333
+ end
334
+ end
335
+
336
+ context 'with options' do
337
+ let(:turner_total) { 25 }
338
+ let(:other_total) { 20 }
339
+ let(:conditions) { { last_name: 'Turner' } }
340
+
341
+ before do
342
+ turner_total.times { employer.users << HorzaSpec::User.create(conditions.merge(employer: employer)) }
343
+ other_total.times { employer.users << HorzaSpec::User.create(employer: employer) }
344
+ end
345
+
346
+ context 'limit' do
347
+ it 'limits response' do
348
+ expect(employer_adapter.association(id: employer.id, target: :users, limit: 10).length).to eq 10
349
+ end
350
+ end
351
+
352
+ context 'conditions' do
353
+ it 'only returns matches' do
354
+ expect(employer_adapter.association(id: employer.id, target: :users, conditions: conditions).length).to eq turner_total
355
+ end
356
+ end
357
+
358
+ context 'offset' do
359
+ it 'offsets response' do
360
+ expect(employer_adapter.association(id: employer.id, target: :users, conditions: conditions, offset: 10).length).to eq turner_total - 10
361
+ end
362
+ end
363
+
364
+ context 'order' do
365
+ it 'orders response' do
366
+ horza_response = employer_adapter.association(id: employer.id, target: :users, conditions: conditions, order: { id: :asc })
367
+ ar_response = HorzaSpec::User.where(conditions).order('id asc')
368
+ expect(horza_response.first.id).to eq ar_response.first.id
369
+ expect(horza_response.last.id).to eq ar_response.last.id
370
+ end
371
+ end
372
+
373
+ context 'eager_load' do
374
+ context 'simple' do
375
+ it 'works as expected' do
376
+ horza_response = employer_adapter.association(id: employer.id, target: :users, conditions: conditions, order: { id: :asc }, eager_load: true)
377
+ ar_response = HorzaSpec::User.where(conditions).order('id asc')
378
+ expect(horza_response.first.id).to eq ar_response.first.id
379
+ expect(horza_response.last.id).to eq ar_response.last.id
380
+ end
381
+ end
303
382
  end
304
383
  end
305
384
  end
@@ -314,7 +393,14 @@ describe Horza do
314
393
  end
315
394
 
316
395
  it 'returns the correct ancestor' do
317
- expect(user_adapter.ancestors(id: user.id, target: :sports_cars, via: [:employer]).first).to eq sportscar.attributes
396
+ expect(user_adapter.association(id: user.id, target: :sports_cars, via: [:employer]).first).to eq sportscar.attributes
397
+ end
398
+
399
+ context 'with eager loading' do
400
+ it 'works as expected' do
401
+ horza_response = user_adapter.association(id: user.id, target: :sports_cars, via: [:employer], order: { id: :asc }, eager_load: true)
402
+ expect(horza_response.first.id).to eq sportscar.id
403
+ end
318
404
  end
319
405
  end
320
406
  end
data/spec/horza_spec.rb CHANGED
@@ -11,7 +11,10 @@ describe Horza do
11
11
  end
12
12
 
13
13
  context 'when adapter is configured' do
14
- before { Horza.configure { |config| config.adapter = :active_record } }
14
+ before do
15
+ Horza.reset
16
+ Horza.configure { |config| config.adapter = :active_record }
17
+ end
15
18
  after { Horza.reset }
16
19
  it 'returns appropriate class' do
17
20
  expect(Horza.adapter).to eq Horza::Adapters::ActiveRecord
@@ -19,3 +22,138 @@ describe Horza do
19
22
  end
20
23
  end
21
24
  end
25
+
26
+ describe Horza::Adapters::Options do
27
+ subject { Horza::Adapters::Options.new(options) }
28
+
29
+ context 'when all options are defined' do
30
+ let(:options) do
31
+ {
32
+ conditions: { last_name: 'Turner' },
33
+ order: { last_name: :asc },
34
+ limit: 20,
35
+ offset: 10,
36
+ target: :sports_cars,
37
+ via: [:employer],
38
+ eager_load: true
39
+ }
40
+ end
41
+
42
+ Horza::Adapters::Options::META_METHODS.each do |method|
43
+ context "##{method}" do
44
+ it 'returns conditions' do
45
+ expect(subject.send(method)).to eq options[method]
46
+ end
47
+ end
48
+ end
49
+
50
+ context '#order_field' do
51
+ context 'when order is passed' do
52
+ it 'returns key of options hash' do
53
+ expect(subject.order_field).to eq(:last_name)
54
+ end
55
+ end
56
+
57
+ context 'when order is not passed' do
58
+ let(:options) { { conditions: { last_name: 'Turner' } } }
59
+ it 'defaults to id' do
60
+ expect(subject.order_field).to eq(:id)
61
+ end
62
+ end
63
+ end
64
+
65
+ context '#order_direction' do
66
+ context 'when order is passed' do
67
+ it 'returns key of options hash' do
68
+ expect(subject.order_direction).to eq(:asc)
69
+ end
70
+ end
71
+
72
+ context 'when order is not passed' do
73
+ let(:options) { { conditions: { last_name: 'Turner' } } }
74
+ it 'defaults to desc' do
75
+ expect(subject.order_direction).to eq(:desc)
76
+ end
77
+ end
78
+ end
79
+
80
+ context '#eager_load?' do
81
+ context 'when eager_load is true' do
82
+ it 'returns true' do
83
+ expect(subject.eager_load?).to be true
84
+ end
85
+ end
86
+
87
+ context 'when eager_load is not set' do
88
+ let(:options) { { conditions: { last_name: 'Turner' } } }
89
+ it 'returns false' do
90
+ expect(subject.eager_load?).to be false
91
+ end
92
+ end
93
+ end
94
+
95
+ context '#eager_args' do
96
+ context 'when eager_load is false' do
97
+ let(:options) { { conditions: { last_name: 'Turner' } } }
98
+ it 'raises error' do
99
+ expect { subject.eager_args }.to raise_error Horza::Errors::InvalidOption
100
+ end
101
+ end
102
+
103
+ context 'simple relation' do
104
+ let(:options) do
105
+ {
106
+ id: 999,
107
+ target: :users,
108
+ eager_load: true
109
+ }
110
+ end
111
+ it 'returns target' do
112
+ expect(subject.eager_args).to eq :users
113
+ end
114
+ end
115
+
116
+ context '1 via' do
117
+ let(:options) do
118
+ {
119
+ id: 999,
120
+ target: :sports_cars,
121
+ via: [:employer],
122
+ eager_load: true
123
+ }
124
+ end
125
+ it 'returns target as value, via as key' do
126
+ expect(subject.eager_args).to eq(employer: :sports_cars)
127
+ end
128
+ end
129
+
130
+ context '2 vias' do
131
+ let(:options) do
132
+ {
133
+ id: 999,
134
+ target: :sports_cars,
135
+ via: [:user, :employer],
136
+ eager_load: true
137
+ }
138
+ end
139
+ it 'returns target as value, final as key, nested in first via' do
140
+ expect(subject.eager_args).to eq(user: { employer: :sports_cars })
141
+ end
142
+ end
143
+
144
+ context '3 vias' do
145
+ let(:options) do
146
+ {
147
+ id: 999,
148
+ target: :sports_cars,
149
+ via: [:app, :user, :employer],
150
+ eager_load: true
151
+ }
152
+ end
153
+ it 'returns target as value, final as key, nested in first via' do
154
+ expect(subject.eager_args).to eq(app: { user: { employer: :sports_cars } })
155
+ end
156
+ end
157
+ end
158
+ end
159
+ end
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.2
4
+ version: 0.3.0
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-05 00:00:00.000000000 Z
11
+ date: 2015-06-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hashie
@@ -108,6 +108,7 @@ files:
108
108
  - lib/horza/adapters/active_record.rb
109
109
  - lib/horza/adapters/class_methods.rb
110
110
  - lib/horza/adapters/instance_methods.rb
111
+ - lib/horza/adapters/options.rb
111
112
  - lib/horza/configuration.rb
112
113
  - lib/horza/core_extensions/string.rb
113
114
  - lib/horza/entities.rb