get 0.1.6 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d94cb493af93174c9e0ae92e3496f07d7de70f2f
4
- data.tar.gz: fb442dab1286f24ce10952ac5d744a9704755619
3
+ metadata.gz: b65d91c034544c94bc5f69f130fd281ea846d32d
4
+ data.tar.gz: 3ba99734b8435d50b2fb2372e798b26860dec7db
5
5
  SHA512:
6
- metadata.gz: 706088f656cce4980d28a79ae9cf3a971faf17a12bebc5c52f3003e7e295342c7f719b2ca9c57f07e0465a7df509a201dc8b8a23ba9264722f52c9d1000a422d
7
- data.tar.gz: 20921d8266728bbee9bc6f6695651ca00fb60472e0ade7ee15a841a25446fb742b0714c9a781284f6e771ac054f02c066f5dc1d7017f65312f695ee6b8549187
6
+ metadata.gz: ae40513b32b4063b5bfe7c2d2bcf025e107eeba4aa87013402b298d6601f09815755e1967c0db38c436e92290444820f06034b20a6b6b4b5f6e5541213c136aa
7
+ data.tar.gz: f99002ee16cdd582571be08ea99512dc2eaa6a9e4e9ff661ba9322b5741d75040a27e899eeee37d76201a6c8fd68180e14ea25e08a06d5f15a6e0f117dcf0a26
data/README.md CHANGED
@@ -2,6 +2,92 @@
2
2
 
3
3
  Dynamically generate classes to encapsulate common database queries in Rails.
4
4
 
5
+ ## Usage
6
+
7
+ #### Singular Queries - Return a single record
8
+
9
+ With field being queried in the class name
10
+ ```ruby
11
+ Get::UserById.run(123)
12
+ ```
13
+
14
+ Fail loudly
15
+ ```ruby
16
+ Get::UserById.run!(123)
17
+ ```
18
+
19
+ Slightly more flexible model:
20
+ ```ruby
21
+ Get::UserBy.run(id: 123, employer_id: 88)
22
+ ```
23
+
24
+ #### Plural Queries - Return a collection of records
25
+
26
+ _Note the plurality of 'Users'_
27
+ ```ruby
28
+ Get::UsersByLastName.run('Turner')
29
+ ```
30
+
31
+ With Options
32
+ ```ruby
33
+ Get::UsersByLastName.run('Turner', limit: 10, offset: 20, order: { last_name: :desc })
34
+ ```
35
+
36
+ #### Associations
37
+
38
+ Associations use 'From', and are sugar for the chains we so often write in rails.
39
+
40
+ _You can pass either an entity or an id, the only requirement is that it responds to #id_
41
+
42
+ Parent relationship (user.employer):
43
+ ```ruby
44
+ Get::EmployerFromUser.run(user)
45
+ ```
46
+
47
+ Child relationship (employer.users):
48
+ ```ruby
49
+ Get::UsersFromEmployer.run(employer_id)
50
+ ```
51
+
52
+ Complex relationship (user.employer.sportscars)
53
+ ```ruby
54
+ Get::SportscarsFromUser.run(user, via: :employer)
55
+ ```
56
+
57
+ Eager Loading
58
+ ```ruby
59
+ Get::SportscarsFromUser.run(user, via: :employer, eager_load: true)
60
+ ```
61
+
62
+ Query Associations
63
+ ```ruby
64
+ Get::SportscarsFromUser.run(user, via: :employer, conditions: { make: 'Audi' }, limit: 10, offset: 20)
65
+ ```
66
+
67
+ Keep the plurality of associations in mind. If an Employer has many Users, UsersFromEmployer works,
68
+ but UserFromEmployer will throw `Get::Errors::InvalidAncestry`.
69
+
70
+ ## Options
71
+
72
+ **Base Options**
73
+
74
+ Key | Type | Details
75
+ --- | ---- | -------
76
+ `order` | Hash | { `field` => `:asc`/`:desc` }
77
+ `limit` | Integer | Number of records to return
78
+ `offset` | Integer | Number of records to offset
79
+ `id` | Integer | The id of the root object (associations only)
80
+ `target` | Symbol | The target of the association - ie. employer.users would have a target of :users (associations only)
81
+ `eager_load` | Boolean | Whether to eager_load the association (associations only)
82
+
83
+ **Association Options**
84
+
85
+ Key | Type | Details
86
+ --- | ---- | -------
87
+ `conditions` | Hash | Key value pairs for the query
88
+ `eager_load` | Boolean | Whether to eager_load the association
89
+ `via` | [Symbol] | The associations that need to be traversed in order to reach the desired record(s). These must be in the correct order, ie user.employer.parent.children would be Get::ChildrenFromUser.run(user_id, via: [:employer, :parent]). You can also pass a single symbol instead of an array of length 1.
90
+
5
91
  ## Why is this necessary?
6
92
 
7
93
  #### Problem 1: Encapsulation
@@ -87,56 +173,6 @@ Get identifies four themes in common queries:
87
173
 
88
174
  These themes are not mutually exclusive; **Query** and **Association** can be either **Singular** or **Plural**.
89
175
 
90
- ## Usage
91
-
92
- #### Singular Queries - Return a single record
93
-
94
- With field being queried in the class name
95
- ```ruby
96
- Get::UserById.run(123)
97
- ```
98
-
99
- Fail loudly
100
- ```ruby
101
- Get::UserById.run!(123)
102
- ```
103
-
104
- Slightly more flexible model:
105
- ```ruby
106
- Get::UserBy.run(id: 123, employer_id: 88)
107
- ```
108
-
109
- #### Plural Queries - Return a collection of records
110
-
111
- _Note the plurality of 'Users'_
112
- ```ruby
113
- Get::UsersByLastName.run('Turner')
114
- ```
115
-
116
- #### Associations
117
-
118
- Associations use 'From', and are sugar for the chains we so often write in rails.
119
-
120
- _You can pass either an entity or an id, the only requirement is that it responds to #id_
121
-
122
- Parent relationship (user.employer):
123
- ```ruby
124
- Get::EmployerFromUser.run(user)
125
- ```
126
-
127
- Child relationship (employer.users):
128
- ```ruby
129
- Get::UsersFromEmployer.run(employer_id)
130
- ```
131
-
132
- Complex relationship (user.employer.sportscars)
133
- ```ruby
134
- Get::SportscarsFromUser.run(user, via: :employer)
135
- ```
136
-
137
- Keep the plurality of associations in mind. If an Employer has many Users, UsersFromEmployer works,
138
- but UserFromEmployer will throw `Get::Errors::InvalidAncestry`.
139
-
140
176
  ## Entities
141
177
 
142
178
  Ironically, one of the "features" of Get is its removal of the ability to query associations from the ORM response object.
@@ -234,7 +270,7 @@ Some attributes contain the word 'by', ie. `Customer.invited_by`.
234
270
  Because of the way Get parses classnames, you won't be able to use the attribute-specific format.
235
271
  Use the more general form instead.
236
272
 
237
- ```
273
+ ```ruby
238
274
  Get::CustomerByInvitedBy.run('John') #=> throws Get::Errors::InvalidClassName
239
275
  Get::CustomerBy.run(invited_by: 'John') #=> will work
240
276
  ```
@@ -29,17 +29,18 @@ module Get
29
29
 
30
30
  private
31
31
 
32
- def id
33
- return @model.id if @model.respond_to? :id
34
- @model
35
- end
36
-
37
32
  def query_params
38
- options = @options.except(:via) || {}
39
- { ancestors: ancestor_params }.merge(options)
33
+ { association: ancestor_params }
40
34
  end
41
35
 
42
36
  def ancestor_params
37
+ # Add options to hash only if they exist - empty objects/nil values can wreak havoc
38
+ [:conditions, :limit, :offset, :order, :eager_load].reduce(required_params) do |params, key|
39
+ @options[key] ? params.merge(key => @options[key]) : params
40
+ end
41
+ end
42
+
43
+ def required_params
43
44
  {
44
45
  id: id,
45
46
  via: via,
@@ -47,6 +48,11 @@ module Get
47
48
  }
48
49
  end
49
50
 
51
+ def id
52
+ return @model.id if @model.respond_to? :id
53
+ @model
54
+ end
55
+
50
56
  def via
51
57
  case @options[:via]
52
58
  when Symbol
@@ -22,15 +22,15 @@ module Get
22
22
 
23
23
  @field, @entity, @collection, @store = args[:key], args[:result_entity], args[:collection], args[:store]
24
24
 
25
- def initialize(params)
26
- @params = params
25
+ def initialize(params, options = {})
26
+ @params, @options = params, options
27
27
  super(query_params)
28
28
  end
29
29
 
30
30
  private
31
31
 
32
32
  def query_params
33
- { query_action => conditions }
33
+ { query_action => conditions.merge(@options) }
34
34
  end
35
35
 
36
36
  def query_action
@@ -39,13 +39,8 @@ module Get
39
39
 
40
40
  # find_first
41
41
  def conditions
42
- return @params unless self.class.field
43
- { self.class.field => @params }
44
- end
45
-
46
- def single_params
47
- return {} if self.class.collection
48
- { limit: 1, first: true }
42
+ return { conditions: @params } unless self.class.field
43
+ { conditions: { self.class.field => @params } }
49
44
  end
50
45
  end
51
46
  end
data/lib/get/db.rb CHANGED
@@ -2,10 +2,6 @@ module Get
2
2
  class Db
3
3
  class << self
4
4
  attr_accessor :entity, :query_key, :collection, :store
5
-
6
- def entity_factory
7
- @factory ||= EntityFactory.new(entity, name, collection, query_key)
8
- end
9
5
  end
10
6
 
11
7
  def initialize(actions)
data/spec/get_spec.rb CHANGED
@@ -210,6 +210,41 @@ describe Get do
210
210
  end
211
211
  end
212
212
 
213
+ context 'with options' do
214
+ let(:last_name) { 'Turner' }
215
+ let(:match_count) { 20 }
216
+ let(:miss_count) { 7 }
217
+
218
+ before do
219
+ match_count.times { GetSpec::User.create(last_name: last_name) }
220
+ miss_count.times { GetSpec::User.create }
221
+ end
222
+
223
+ context 'when limit is passed' do
224
+ it 'limits the records' do
225
+ result = Get::UsersBy.run({ last_name: last_name }, limit: 2)
226
+ expect(result.length).to eq 2
227
+ end
228
+ end
229
+
230
+ context 'when offset is passed' do
231
+ it 'offsets the response' do
232
+ result = Get::UsersBy.run({ last_name: last_name }, offset: 5)
233
+ expect(result.length).to eq 15
234
+ end
235
+ end
236
+
237
+ context 'when order is passed' do
238
+ it 'orders the response' do
239
+ result = Get::UsersBy.run({ last_name: last_name }, order: { id: :asc })
240
+ ar_result = GetSpec::User.where(last_name: last_name).order('id asc')
241
+
242
+ expect(result.first.id).to eq ar_result.first.id
243
+ expect(result.last.id).to eq ar_result.last.id
244
+ end
245
+ end
246
+ end
247
+
213
248
  context 'when no records exist' do
214
249
  it 'returns empty collection' do
215
250
  expect(Get::UsersBy.run(last_name: last_name).empty?).to be true
@@ -217,7 +252,7 @@ describe Get do
217
252
  end
218
253
  end
219
254
 
220
- context 'ancestry' do
255
+ context 'associations' do
221
256
  context 'direct relation' do
222
257
  let(:employer) { GetSpec::Employer.create }
223
258
  let!(:user1) { GetSpec::User.create(employer: employer) }
@@ -232,8 +267,9 @@ describe Get do
232
267
  context 'ChildrenFromParent' do
233
268
  it 'returns children' do
234
269
  result = Get::UsersFromEmployer.run(employer)
235
- expect(result.first.to_h).to eq user1.attributes
236
- expect(result.last.to_h).to eq user2.attributes
270
+ ar_result = GetSpec::User.where(employer_id: employer.id).order('id desc')
271
+ expect(result.first.id).to eq ar_result.first.id
272
+ expect(result.last.id).to eq ar_result.last.id
237
273
  end
238
274
  end
239
275
 
@@ -277,6 +313,55 @@ describe Get do
277
313
  expect(result.first.to_h).to eq sportscar.attributes
278
314
  end
279
315
  end
316
+
317
+ context 'with options' do
318
+ let(:employer) { GetSpec::Employer.create }
319
+ let(:match_count) { 20 }
320
+ let(:miss_count) { 7 }
321
+
322
+ before do
323
+ match_count.times { employer.users << GetSpec::User.create(employer: employer, last_name: last_name) }
324
+ miss_count.times { employer.users << GetSpec::User.create(employer: employer) }
325
+ end
326
+
327
+ context 'when conditions are passed' do
328
+ it 'filters response' do
329
+ result = Get::UsersFromEmployer.run(employer.id, conditions: { last_name: last_name })
330
+ expect(result.length).to eq match_count
331
+ end
332
+ end
333
+
334
+ context 'when limit is passed' do
335
+ it 'limits response' do
336
+ result = Get::UsersFromEmployer.run(employer.id, conditions: { last_name: last_name }, limit: 5)
337
+ expect(result.length).to eq 5
338
+ end
339
+ end
340
+
341
+ context 'when offset is passed' do
342
+ it 'offsets response' do
343
+ result = Get::UsersFromEmployer.run(employer.id, conditions: { last_name: last_name }, offset: 16)
344
+ expect(result.length).to eq match_count - 16
345
+ end
346
+ end
347
+
348
+ context 'when order is passed' do
349
+ it 'orders response' do
350
+ result = Get::UsersFromEmployer.run(employer.id, conditions: { last_name: last_name }, order: { id: :asc })
351
+ ar_result = GetSpec::User.where(employer_id: employer.id, last_name: last_name).order('id asc')
352
+
353
+ expect(result.first.id).to eq ar_result.first.id
354
+ expect(result.last.id).to eq ar_result.last.id
355
+ end
356
+ end
357
+
358
+ context 'when eager_load is passed' do
359
+ it 'behaves as expected' do
360
+ result = Get::UsersFromEmployer.run(employer.id, conditions: { last_name: last_name }, eager_load: true)
361
+ expect(result.length).to eq match_count
362
+ end
363
+ end
364
+ end
280
365
  end
281
366
  end
282
367
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: get
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.2.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: horza
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.2.1
19
+ version: 0.3.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.2.1
26
+ version: 0.3.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement