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 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