joiner 0.3.3 → 0.3.4
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 +4 -4
- data/README.md +1 -1
- data/joiner.gemspec +1 -1
- data/lib/joiner.rb +2 -0
- data/lib/joiner/joins.rb +28 -74
- data/spec/acceptance/joiner_spec.rb +11 -0
- metadata +2 -4
- data/spec/joiner/joins_spec.rb +0 -83
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7249d05e24afee39fbb2547085068230f6b1d62b
|
4
|
+
data.tar.gz: 941f72f5d80c3a6c0b8b88684f7a35b77e7461ee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0fd9651d510164f7e5843589678ba62d3f214c67dca6309e4711f71cd8b4200b3e105cd780fdfab14d3a4240d4354fcd95b6568b101d710757da1d093e96600a
|
7
|
+
data.tar.gz: ff41eaace4916f013c03e7407a65709543251908daab4f3203f723282a9c38c50a35b9767a9b074bb6f7f336bb1042cf30542d8ee179cd08ca868a23228b66fe
|
data/README.md
CHANGED
@@ -9,7 +9,7 @@ If this gem is used by anyone other than myself/Thinking Sphinx, I'll be surpris
|
|
9
9
|
It's a gem - so you can either install it yourself, or add it to the appropriate Gemfile or gemspec.
|
10
10
|
|
11
11
|
```term
|
12
|
-
gem install joiner --version 0.3.
|
12
|
+
gem install joiner --version 0.3.4
|
13
13
|
```
|
14
14
|
|
15
15
|
## Usage
|
data/joiner.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
Gem::Specification.new do |spec|
|
3
3
|
spec.name = 'joiner'
|
4
|
-
spec.version = '0.3.
|
4
|
+
spec.version = '0.3.4'
|
5
5
|
spec.authors = ['Pat Allan']
|
6
6
|
spec.email = ['pat@freelancing-gods.com']
|
7
7
|
spec.summary = %q{Builds ActiveRecord joins from association paths}
|
data/lib/joiner.rb
CHANGED
data/lib/joiner/joins.rb
CHANGED
@@ -1,103 +1,57 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'active_support/ordered_hash'
|
3
|
+
|
1
4
|
class Joiner::Joins
|
2
|
-
JoinDependency
|
5
|
+
JoinDependency = ActiveRecord::Associations::JoinDependency
|
6
|
+
JoinAssociation = JoinDependency::JoinAssociation
|
3
7
|
|
4
|
-
attr_reader
|
5
|
-
|
8
|
+
attr_reader :model
|
9
|
+
attr_accessor :join_association_class
|
6
10
|
|
7
11
|
def initialize(model)
|
8
12
|
@model = model
|
9
|
-
@
|
10
|
-
@joins_cache = ActiveSupport::OrderedHash.new
|
13
|
+
@joins_cache = Set.new
|
11
14
|
end
|
12
15
|
|
13
16
|
def add_join_to(path)
|
14
|
-
|
17
|
+
return if path.empty?
|
18
|
+
|
19
|
+
joins_cache.add path_as_hash(path)
|
15
20
|
end
|
16
21
|
|
17
22
|
def alias_for(path)
|
18
23
|
return model.table_name if path.empty?
|
19
|
-
add_join_to(path).aliased_table_name
|
20
|
-
end
|
21
24
|
|
22
|
-
|
23
|
-
|
25
|
+
add_join_to path
|
26
|
+
join_association_for(path).tables.first.name
|
24
27
|
end
|
25
28
|
|
26
29
|
def join_values
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
private
|
30
|
+
switch_join_dependency join_association_class
|
31
|
+
result = JoinDependency.new model, joins_cache.to_a, []
|
32
|
+
switch_join_dependency JoinAssociation
|
31
33
|
|
32
|
-
|
33
|
-
if join = find_join(path)
|
34
|
-
return join
|
35
|
-
end
|
36
|
-
|
37
|
-
base_node, short_path = relative_path(path)
|
38
|
-
|
39
|
-
join = build_join_association(short_path, base_node.base_klass)
|
40
|
-
base_node.children << join
|
41
|
-
construct_tables! base_node, join
|
42
|
-
|
43
|
-
find_join(path)
|
34
|
+
result
|
44
35
|
end
|
45
36
|
|
46
|
-
|
47
|
-
return nil if path.empty?
|
48
|
-
|
49
|
-
step = path.first
|
50
|
-
reflection = find_reflection(step, base_class)
|
51
|
-
reflection.check_validity!
|
52
|
-
|
53
|
-
join_association_class.new reflection,
|
54
|
-
[build_join_association(path[1..-1], reflection.klass)].compact
|
55
|
-
end
|
56
|
-
|
57
|
-
def find_join(path, base = nil)
|
58
|
-
base ||= @base.join_root
|
59
|
-
|
60
|
-
return base if path.empty?
|
61
|
-
|
62
|
-
if next_step = base.children.detect{ |c| c.reflection.name == path.first }
|
63
|
-
find_join path[1..-1], next_step
|
64
|
-
end
|
65
|
-
end
|
37
|
+
private
|
66
38
|
|
67
|
-
|
68
|
-
short_path = []
|
69
|
-
test_path = path.dup
|
39
|
+
attr_reader :joins_cache
|
70
40
|
|
71
|
-
|
72
|
-
|
73
|
-
node
|
74
|
-
return [node, short_path] if node
|
41
|
+
def join_association_for(path)
|
42
|
+
path.inject(join_values.join_root) do |node, piece|
|
43
|
+
node.children.detect { |child| child.reflection.name == piece }
|
75
44
|
end
|
76
|
-
|
77
|
-
[@base.join_root, path]
|
78
45
|
end
|
79
46
|
|
80
|
-
def
|
81
|
-
|
47
|
+
def path_as_hash(path)
|
48
|
+
path[0..-2].reverse.inject(path.last) { |key, item| {item => key} }
|
82
49
|
end
|
83
50
|
|
84
|
-
def
|
85
|
-
|
86
|
-
@base.alias_tracker.aliased_table_for(
|
87
|
-
reflection.table_name,
|
88
|
-
table_alias_for(reflection, parent, reflection != node.reflection)
|
89
|
-
)
|
90
|
-
}
|
91
|
-
end
|
92
|
-
|
93
|
-
def construct_tables!(parent, node)
|
94
|
-
node.tables = table_aliases_for(parent, node)
|
95
|
-
node.children.each { |child| construct_tables! node, child }
|
96
|
-
end
|
51
|
+
def switch_join_dependency(klass)
|
52
|
+
return unless join_association_class
|
97
53
|
|
98
|
-
|
99
|
-
|
100
|
-
name << "_join" if join
|
101
|
-
name
|
54
|
+
JoinDependency.send :remove_const, :JoinAssociation
|
55
|
+
JoinDependency.const_set :JoinAssociation, klass
|
102
56
|
end
|
103
57
|
end
|
@@ -63,4 +63,15 @@ describe 'Joiner' do
|
|
63
63
|
expect(joiner.alias_for([:comments])).to eq('comments')
|
64
64
|
expect(joiner.alias_for([:user, :comments])).to eq('comments_users')
|
65
65
|
end
|
66
|
+
|
67
|
+
it 'handles simple and deep chains' do
|
68
|
+
joiner = Joiner::Joins.new Article
|
69
|
+
joiner.add_join_to [:comments]
|
70
|
+
joiner.add_join_to [:comments, :user, :articles]
|
71
|
+
|
72
|
+
expect(joiner.alias_for([:comments])).to eq('comments')
|
73
|
+
expect(joiner.alias_for([:comments, :user, :articles])).to eq(
|
74
|
+
'articles_users'
|
75
|
+
)
|
76
|
+
end
|
66
77
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: joiner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pat Allan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-11-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -105,7 +105,6 @@ files:
|
|
105
105
|
- spec/internal/config/database.yml
|
106
106
|
- spec/internal/db/schema.rb
|
107
107
|
- spec/internal/log/.gitignore
|
108
|
-
- spec/joiner/joins_spec.rb
|
109
108
|
- spec/spec_helper.rb
|
110
109
|
homepage: https://github.com/pat/joiner
|
111
110
|
licenses:
|
@@ -140,5 +139,4 @@ test_files:
|
|
140
139
|
- spec/internal/config/database.yml
|
141
140
|
- spec/internal/db/schema.rb
|
142
141
|
- spec/internal/log/.gitignore
|
143
|
-
- spec/joiner/joins_spec.rb
|
144
142
|
- spec/spec_helper.rb
|
data/spec/joiner/joins_spec.rb
DELETED
@@ -1,83 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Joiner::Joins do
|
4
|
-
JoinDependency = ::ActiveRecord::Associations::JoinDependency
|
5
|
-
|
6
|
-
subject { Joiner::Joins.new Article }
|
7
|
-
|
8
|
-
describe '#add_join_to' do
|
9
|
-
it "adds just one join for a stack with a single association" do
|
10
|
-
JoinDependency::JoinAssociation.should_receive(:new).
|
11
|
-
with(Article.reflections[:user], []).once.and_call_original
|
12
|
-
|
13
|
-
subject.add_join_to([:user])
|
14
|
-
end
|
15
|
-
|
16
|
-
it "does not duplicate joins when given the same stack twice" do
|
17
|
-
JoinDependency::JoinAssociation.should_receive(:new).once.and_call_original
|
18
|
-
|
19
|
-
subject.add_join_to([:user])
|
20
|
-
subject.add_join_to([:user])
|
21
|
-
end
|
22
|
-
|
23
|
-
context 'when joins are nested' do
|
24
|
-
it "adds two joins for a stack with two associations" do
|
25
|
-
JoinDependency::JoinAssociation.should_receive(:new).
|
26
|
-
with(Article.reflections[:user], kind_of(Array)).once.and_call_original
|
27
|
-
JoinDependency::JoinAssociation.should_receive(:new).
|
28
|
-
with(User.reflections[:comments], kind_of(Array)).once.and_call_original
|
29
|
-
|
30
|
-
subject.add_join_to([:user, :comments])
|
31
|
-
end
|
32
|
-
|
33
|
-
it "extends upon existing joins when given stacks where parts are already mapped" do
|
34
|
-
JoinDependency::JoinAssociation.should_receive(:new).twice.and_call_original
|
35
|
-
|
36
|
-
join1 = subject.add_join_to([:user])
|
37
|
-
join2 = subject.add_join_to([:user, :comments])
|
38
|
-
|
39
|
-
join1.children.should include(join2)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
describe '#alias_for' do
|
45
|
-
it "returns the model's table name when no stack is given" do
|
46
|
-
subject.alias_for([]).should == 'articles'
|
47
|
-
end
|
48
|
-
|
49
|
-
it "gets join association using #add_join_to" do
|
50
|
-
subject.should_receive(:add_join_to).with([:user]).and_call_original
|
51
|
-
subject.alias_for([:user])
|
52
|
-
end
|
53
|
-
|
54
|
-
it "returns the aliased table name for the join" do
|
55
|
-
subject.alias_for([:user]).should == 'users'
|
56
|
-
end
|
57
|
-
|
58
|
-
it "does not duplicate joins when given the same stack twice" do
|
59
|
-
JoinDependency::JoinAssociation.should_receive(:new).once.and_call_original
|
60
|
-
|
61
|
-
subject.alias_for([:user])
|
62
|
-
subject.alias_for([:user])
|
63
|
-
end
|
64
|
-
|
65
|
-
context 'when joins are nested' do
|
66
|
-
it "returns the sub join's aliased table name" do
|
67
|
-
subject.alias_for([:user, :comments]).should == 'comments'
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
describe '#join_values' do
|
73
|
-
it "returns JoinDependency with all joins that have been created" do
|
74
|
-
join1 = subject.add_join_to([:user])
|
75
|
-
join2 = subject.add_join_to([:comments])
|
76
|
-
join3 = subject.add_join_to([:comments, :user])
|
77
|
-
|
78
|
-
join_values = subject.join_values
|
79
|
-
join_values.should be_a JoinDependency
|
80
|
-
join_values.join_root.children.should == [join1, join2]
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|