get 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +61 -0
- data/lib/get/builders/join_builder.rb +38 -0
- data/lib/get/builders.rb +2 -0
- data/lib/get/parser.rb +1 -1
- data/lib/get.rb +1 -0
- data/spec/get_spec.rb +70 -0
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e87e789020578ba92ef03c7e3a98f9634f85f762
|
4
|
+
data.tar.gz: e8181e6da0904a709a7f532d8157310f4d16fc16
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a68bd91a8407162804dc0d6cdeaa702cee0782f798cbc58ca1a2e086a37c3f38e83e5237a5812a3729a5d20610a15b396e4a568b9e4900e56c198fa162419b0
|
7
|
+
data.tar.gz: 08371505e8ac657c5c88fb7f02ffdf986e5a1d824b6ca239c3ab52257a0d8443dff9ee534482fa27a6fcf271aa54032d3b2982a99a12000787a2d2e4b237ead7
|
data/README.md
CHANGED
@@ -67,6 +67,59 @@ Get::SportscarsFromUser.run(user, via: :employer, conditions: { make: 'Audi' },
|
|
67
67
|
Keep the plurality of associations in mind. If an Employer has many Users, UsersFromEmployer works,
|
68
68
|
but UserFromEmployer will throw `Get::Errors::InvalidAncestry`.
|
69
69
|
|
70
|
+
## Joins
|
71
|
+
|
72
|
+
Associations use 'JoinedWith', and make the dark world of joins much more palatable.
|
73
|
+
Joins will always return a Horza::Collection.
|
74
|
+
|
75
|
+
*It is recommended to pass a fields hash when using Get joins.
|
76
|
+
If you do not, your database implementation will decide which values are placed in fields with common names, like :id.*
|
77
|
+
|
78
|
+
Join on related ids, select multiple fields
|
79
|
+
```ruby
|
80
|
+
join_params = {
|
81
|
+
on: { employer_id: :id }, # base_table(users).employer_id = join_table(employers).id
|
82
|
+
fields: {
|
83
|
+
users: [:first_name, :last_name],
|
84
|
+
employers: [:address],
|
85
|
+
}
|
86
|
+
}
|
87
|
+
UsersJoinedWithEmployers.run(join_params)
|
88
|
+
```
|
89
|
+
|
90
|
+
Join on related ids, select multiple fields - with conditions, limit, and offset
|
91
|
+
```ruby
|
92
|
+
join_params = {
|
93
|
+
on: { employer_id: :id }, # base_table(users).employer_id = join_table(employers).id
|
94
|
+
fields: {
|
95
|
+
users: [:first_name, :last_name],
|
96
|
+
employers: [:address],
|
97
|
+
},
|
98
|
+
conditions: {
|
99
|
+
users: { last_name: 'Turner' },
|
100
|
+
employers: { company_name: 'Corporation ltd.' }
|
101
|
+
},
|
102
|
+
limit: 10,
|
103
|
+
offset: 5
|
104
|
+
}
|
105
|
+
UsersJoinedWithEmployers.run(join_params)
|
106
|
+
```
|
107
|
+
|
108
|
+
Join on multiple requirements, alias field names
|
109
|
+
```ruby
|
110
|
+
join_params = {
|
111
|
+
on: [
|
112
|
+
{ employer_id: :id }, # base_table(users).employer_id = join_table(employers).id
|
113
|
+
{ email: :email }, # base_table(users).email = join_table(employers).email
|
114
|
+
]
|
115
|
+
fields: {
|
116
|
+
users: [:id, { first_name: :my_alias_for_first_name }],
|
117
|
+
employers: [:email, { id: :my_alias_for_employer_id }]
|
118
|
+
}
|
119
|
+
}
|
120
|
+
UsersJoinedWithEmployers.run(join_params)
|
121
|
+
```
|
122
|
+
|
70
123
|
## Options
|
71
124
|
|
72
125
|
**Base Options**
|
@@ -88,6 +141,14 @@ Key | Type | Details
|
|
88
141
|
`eager_load` | Boolean | Whether to eager_load the association
|
89
142
|
`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
143
|
|
144
|
+
**Join Options**
|
145
|
+
|
146
|
+
Key | Type | Details
|
147
|
+
--- | ---- | -------
|
148
|
+
`on` | Hash or Array of Hashes | Key value pairs representing base_table field => join_table field
|
149
|
+
`fields` | Hash | Keys are the table names, values are array of field names or hashes defining the field's alias for the join. See examples above.
|
150
|
+
`conditions` | Hash | Keys are the table names, values are Key value pairs for the query. See examples above.
|
151
|
+
|
91
152
|
## Why is this necessary?
|
92
153
|
|
93
154
|
#### Problem 1: Encapsulation
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Get
|
2
|
+
module Builders
|
3
|
+
class JoinBuilder < BaseBuilder
|
4
|
+
private
|
5
|
+
|
6
|
+
def class_args
|
7
|
+
{
|
8
|
+
base_table: @result_entity.symbolize,
|
9
|
+
join_table: @key,
|
10
|
+
store: Get.adapter.context_for_entity(@result_entity.singularize.symbolize)
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
def template_class(args)
|
15
|
+
Class.new(::Get::Db) do
|
16
|
+
include Get
|
17
|
+
|
18
|
+
class << self
|
19
|
+
attr_reader :base_table, :join_table
|
20
|
+
end
|
21
|
+
|
22
|
+
@base_table, @join_table, @store = args[:base_table], args[:join_table], args[:store]
|
23
|
+
|
24
|
+
def initialize(options)
|
25
|
+
@options = options.merge(with: self.class.join_table)
|
26
|
+
super(query_params)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def query_params
|
32
|
+
{ join: @options }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/get/builders.rb
CHANGED
data/lib/get/parser.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Get
|
2
2
|
class Parser
|
3
|
-
CLASS_REGEX = /^(.*)(By|From)(.*)/
|
3
|
+
CLASS_REGEX = /^(.*)(By|From|JoinedWith)(.*)/
|
4
4
|
CLASS_NAME_BY_ERROR = 'You have multiple instances of "By" in your class. Please use open-ended form ie. Get::UserBy.run(params)'
|
5
5
|
attr_accessor :class_name, :result_entity, :method
|
6
6
|
|
data/lib/get.rb
CHANGED
data/spec/get_spec.rb
CHANGED
@@ -379,6 +379,69 @@ describe Get do
|
|
379
379
|
end
|
380
380
|
end
|
381
381
|
end
|
382
|
+
|
383
|
+
context 'joins' do
|
384
|
+
let(:employer) { GetSpec::Employer.create }
|
385
|
+
let(:employer2) { GetSpec::Employer.create }
|
386
|
+
let(:match_count) { 20 }
|
387
|
+
let(:miss_count) { 7 }
|
388
|
+
|
389
|
+
before do
|
390
|
+
match_count.times { employer2.users << GetSpec::User.create(employer: employer2) }
|
391
|
+
miss_count.times { employer.users << GetSpec::User.create(employer: employer) }
|
392
|
+
end
|
393
|
+
|
394
|
+
context 'when no conditions are passed' do
|
395
|
+
let(:join_params) do
|
396
|
+
{
|
397
|
+
on: { employer_id: :id } # field for adapted model => field for join model
|
398
|
+
}
|
399
|
+
end
|
400
|
+
|
401
|
+
it 'returns match_count + miss_count joines records' do
|
402
|
+
result = Get::UsersJoinedWithEmployers.run(join_params)
|
403
|
+
expect(result.length).to eq match_count + miss_count
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
context 'when conditions are passed' do
|
408
|
+
let(:join_params) do
|
409
|
+
{
|
410
|
+
on: { employer_id: :id }, # field for adapted model => field for join model
|
411
|
+
conditions: {
|
412
|
+
employers: { id: employer2.id }
|
413
|
+
}
|
414
|
+
}
|
415
|
+
end
|
416
|
+
|
417
|
+
it 'returns match_count joined records' do
|
418
|
+
result = Get::UsersJoinedWithEmployers.run(join_params)
|
419
|
+
expect(result.length).to eq match_count
|
420
|
+
end
|
421
|
+
end
|
422
|
+
|
423
|
+
context 'when conditions and fields are passed' do
|
424
|
+
let(:join_params) do
|
425
|
+
{
|
426
|
+
on: { employer_id: :id }, # field for adapted model => field for join model
|
427
|
+
conditions: {
|
428
|
+
employers: { id: employer2.id }
|
429
|
+
},
|
430
|
+
fields: {
|
431
|
+
users: [:id],
|
432
|
+
employers: [{id: :my_employer_id}]
|
433
|
+
}
|
434
|
+
}
|
435
|
+
end
|
436
|
+
|
437
|
+
it 'returns match_count joined records' do
|
438
|
+
result = Get::UsersJoinedWithEmployers.run(join_params)
|
439
|
+
expect(result.length).to eq match_count
|
440
|
+
expect(result.first.my_employer_id).to eq employer2.id
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
444
|
+
end
|
382
445
|
end
|
383
446
|
end
|
384
447
|
|
@@ -427,6 +490,7 @@ end
|
|
427
490
|
describe Get::Parser do
|
428
491
|
let(:ancestry_name) { 'UserFromEmployer' }
|
429
492
|
let(:query_name) { 'UserFromEmployer' }
|
493
|
+
let(:join_name) { 'UsersJoinedWithEmployers' }
|
430
494
|
|
431
495
|
subject { Get::Parser }
|
432
496
|
before { Get.configure { |config| config.adapter = :active_record } }
|
@@ -445,6 +509,12 @@ describe Get::Parser do
|
|
445
509
|
end
|
446
510
|
end
|
447
511
|
|
512
|
+
context 'when name is of join type' do
|
513
|
+
it 'returns true' do
|
514
|
+
expect(subject.new(join_name).match?).to be true
|
515
|
+
end
|
516
|
+
end
|
517
|
+
|
448
518
|
context 'when name is of no type' do
|
449
519
|
it 'returns false' do
|
450
520
|
expect(subject.new('Blablabla').match?).to be false
|
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.3.
|
4
|
+
version: 0.3.1
|
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-
|
11
|
+
date: 2015-07-21 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.
|
19
|
+
version: 0.4.0
|
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.
|
26
|
+
version: 0.4.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -120,6 +120,7 @@ files:
|
|
120
120
|
- lib/get/builders.rb
|
121
121
|
- lib/get/builders/ancestry_builder.rb
|
122
122
|
- lib/get/builders/base_builder.rb
|
123
|
+
- lib/get/builders/join_builder.rb
|
123
124
|
- lib/get/builders/query_builder.rb
|
124
125
|
- lib/get/configuration.rb
|
125
126
|
- lib/get/db.rb
|