get 0.3.0 → 0.3.1

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: e2d1a7584bddd3b60f6946a92d944bd6e4466be5
4
- data.tar.gz: a44d6c9a3ec1da6f30d443926bdbd9aea0fc47d4
3
+ metadata.gz: e87e789020578ba92ef03c7e3a98f9634f85f762
4
+ data.tar.gz: e8181e6da0904a709a7f532d8157310f4d16fc16
5
5
  SHA512:
6
- metadata.gz: 5b658939ecf304357cbde59019710069c58b7983c6530c6c40e638696dcb638c95fb05c69698b9a5c5499c6e3615b8582e87404123e216322797d61ba6e3bb53
7
- data.tar.gz: d5d02338741299749b7da0a3e42b21ccb378769bf2757bb9002f559bd4e6e7e6099496303922aeb9e05f94414ee62cce64d0085fd08e472e18178c254138258c
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
@@ -11,6 +11,8 @@ module Get
11
11
  QueryBuilder
12
12
  when 'From'
13
13
  AncestryBuilder
14
+ when 'JoinedWith'
15
+ JoinBuilder
14
16
  end
15
17
  end
16
18
  end
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
@@ -1,6 +1,7 @@
1
1
  require 'get/builders/base_builder'
2
2
  require 'get/builders/ancestry_builder'
3
3
  require 'get/builders/query_builder'
4
+ require 'get/builders/join_builder'
4
5
  require 'get/builders'
5
6
  require 'get/configuration'
6
7
  require 'get/db'
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.0
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-06-12 00:00:00.000000000 Z
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.3.4
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.3.4
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