polyamorous 1.1.0 → 1.2.0

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.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +27 -6
  3. data/Gemfile +15 -13
  4. data/README.md +7 -2
  5. data/lib/polyamorous.rb +30 -12
  6. data/lib/polyamorous/{activerecord_3_and_4.0 → activerecord_3_and_4.0_ruby_1.9}/join_association.rb +28 -27
  7. data/lib/polyamorous/{activerecord_3_and_4.0 → activerecord_3_and_4.0_ruby_1.9}/join_dependency.rb +7 -4
  8. data/lib/polyamorous/activerecord_4.1_ruby_1.9/join_association.rb +2 -0
  9. data/lib/polyamorous/activerecord_4.1_ruby_1.9/join_dependency.rb +4 -0
  10. data/lib/polyamorous/activerecord_4.1_ruby_2/join_association.rb +2 -0
  11. data/lib/polyamorous/activerecord_4.1_ruby_2/join_dependency.rb +3 -0
  12. data/lib/polyamorous/activerecord_4.1_ruby_2/make_joins.rb +11 -0
  13. data/lib/polyamorous/activerecord_4.2_ruby_1.9/join_association.rb +46 -0
  14. data/lib/polyamorous/activerecord_4.2_ruby_1.9/join_dependency.rb +94 -0
  15. data/lib/polyamorous/activerecord_4.2_ruby_2/join_association.rb +37 -0
  16. data/lib/polyamorous/{activerecord_4.1 → activerecord_4.2_ruby_2}/join_dependency.rb +39 -44
  17. data/lib/polyamorous/swapping_reflection_class.rb +11 -0
  18. data/lib/polyamorous/version.rb +1 -1
  19. data/polyamorous.gemspec +4 -3
  20. data/spec/polyamorous/join_association_spec.rb +3 -3
  21. data/spec/polyamorous/join_dependency_spec.rb +3 -3
  22. data/spec/polyamorous/join_spec.rb +2 -2
  23. data/spec/spec_helper.rb +10 -2
  24. data/spec/support/schema.rb +47 -51
  25. data/spec/support/shared_examples/join_association_3_and_4.0.rb +6 -3
  26. data/spec/support/shared_examples/join_association_4.1.rb +9 -4
  27. data/spec/support/shared_examples/join_dependency_3_and_4.0.rb +22 -11
  28. data/spec/support/shared_examples/join_dependency_4.1.rb +25 -6
  29. metadata +41 -12
  30. data/lib/polyamorous/activerecord_4.1/join_association.rb +0 -75
  31. data/lib/polyamorous/activerecord_4.2/join_dependency.rb +0 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5a256aa59edc7952f875968b4de3aba8b9ae2ef1
4
- data.tar.gz: 44fe6b2d97fde89c883db2b58d2fe847d8e70217
3
+ metadata.gz: a754ac3545728f4de5d4d5e4f75687991f7b41ca
4
+ data.tar.gz: c2a55008f158f99fd534e66b2306e045271edf1d
5
5
  SHA512:
6
- metadata.gz: 17b12b0d0ade5088d17bf164b03145b239ee184c5115d294cc7feda1d57e7085cceb1891b5a1640702fd1a182507277af155387732810d5719418f4bbb48cdea
7
- data.tar.gz: 5090142ad7882a7efa7c3fa4ca72f74627d64d5537b1310c0f156325e4b54b004e2d09b0666b33cb981fad74bf3eca68ae6cf92538a13a39002571306576a64d
6
+ metadata.gz: 1ae3f57016adf1c30563485ae3ae7155aa3e95c880241231e346930de0ab16e1a75082d79563ba2850f2f2513ab7f7a92dd78a5d14e88c19e0aebaf551cdf422
7
+ data.tar.gz: e0f9296bbbe67e09691d67e5d70b4a0809e71db9ae9a79fcd6bfed483834cf9dae15bf733ed22f645009a7cca66d4f4f79a7fd6aef3952a28fd75d4259e41f06
@@ -1,33 +1,54 @@
1
1
  language: ruby
2
2
 
3
+ sudo: false
4
+
3
5
  before_install:
4
6
  - travis_retry gem install bundler
5
7
 
6
8
  rvm:
7
- - 1.9.3
8
- - 2.0.0
9
- - 2.1.1
9
+ - 2.2.1
10
+ - 2.1
11
+ - 2.0
12
+ - 1.9
10
13
 
11
14
  env:
12
- - RAILS=master AREL=master DB=sqlite
13
- - RAILS=master AREL=master DB=mysql
14
- - RAILS=master AREL=master DB=postgres
15
+ - RAILS=4-2-stable AREL=6-0-stable DB=sqlite
16
+ - RAILS=4-2-stable AREL=6-0-stable DB=mysql
17
+ - RAILS=4-2-stable AREL=6-0-stable DB=postgres
18
+
15
19
  - RAILS=4-1-stable AREL=5-0-stable DB=sqlite
16
20
  - RAILS=4-1-stable AREL=5-0-stable DB=mysql
17
21
  - RAILS=4-1-stable AREL=5-0-stable DB=postgres
22
+
18
23
  - RAILS=4-0-stable AREL=4-0-stable DB=sqlite
19
24
  - RAILS=4-0-stable AREL=4-0-stable DB=mysql
20
25
  - RAILS=4-0-stable AREL=4-0-stable DB=postgres
26
+
21
27
  - RAILS=3-2-stable AREL=3-0-stable DB=sqlite
22
28
  - RAILS=3-2-stable AREL=3-0-stable DB=mysql
23
29
  - RAILS=3-2-stable AREL=3-0-stable DB=postgres
30
+
24
31
  - RAILS=3-1-stable AREL=2-2-stable DB=sqlite
25
32
  - RAILS=3-1-stable AREL=2-2-stable DB=mysql
26
33
  - RAILS=3-1-stable AREL=2-2-stable DB=postgres
34
+
27
35
  - RAILS=3-0-stable AREL=2-0-stable DB=sqlite
28
36
  - RAILS=3-0-stable AREL=2-0-stable DB=mysql
29
37
  - RAILS=3-0-stable AREL=2-0-stable DB=postgres
30
38
 
39
+ matrix:
40
+ include:
41
+ - rvm: 2.2.1
42
+ env: RAILS=master DB=sqlite3
43
+ - rvm: 2.2.1
44
+ env: RAILS=master DB=mysql
45
+ - rvm: 2.2.1
46
+ env: RAILS=master DB=postgres
47
+ allow_failures:
48
+ - env: RAILS=master DB=sqlite3
49
+ - env: RAILS=master DB=mysql
50
+ - env: RAILS=master DB=postgres
51
+
31
52
  before_script:
32
53
  - mysql -e 'create database ransack collate utf8_general_ci;'
33
54
  - mysql -e 'use ransack;show variables like "%character%";show variables like "%collation%";'
data/Gemfile CHANGED
@@ -4,28 +4,30 @@ gemspec
4
4
  gem 'rake'
5
5
 
6
6
  rails = ENV['RAILS'] || 'master'
7
- arel = ENV['AREL'] || 'master'
8
7
 
9
- arel_opts = case arel
10
- when /\// # A path
11
- {:path => arel}
12
- when /^v/ # A tagged version
13
- {:git => 'git://github.com/rails/arel.git', :tag => arel}
14
- else
15
- {:git => 'git://github.com/rails/arel.git', :branch => arel}
8
+ if rails == 'master'
9
+ arel = ENV['AREL'] || 'master'
10
+ arel_opts =
11
+ case arel
12
+ when /\// # A path
13
+ { path: arel }
14
+ when /^v/ # A tagged version
15
+ { git: 'git://github.com/rails/arel.git', tag: arel }
16
+ else
17
+ { git: 'git://github.com/rails/arel.git', branch: arel }
18
+ end
19
+ gem 'arel', arel_opts
16
20
  end
17
21
 
18
- gem 'arel', arel_opts
19
-
20
22
  case rails
21
23
  when /\// # A path
22
- gem 'activerecord', :path => "#{rails}/activerecord"
24
+ gem 'activerecord', path: "#{rails}/activerecord"
23
25
  when /^v/ # A tagged version
24
- git 'git://github.com/rails/rails.git', :tag => rails do
26
+ git 'git://github.com/rails/rails.git', tag: rails do
25
27
  gem 'activerecord'
26
28
  end
27
29
  else
28
- git 'git://github.com/rails/rails.git', :branch => rails do
30
+ git 'git://github.com/rails/rails.git', branch: rails do
29
31
  gem 'activerecord'
30
32
  end
31
33
  end
data/README.md CHANGED
@@ -6,8 +6,13 @@
6
6
  (http://badge.fury.io/rb/polyamorous)
7
7
 
8
8
  Polyamorous is an extraction from MetaSearch 1.1.x, Ransack, and Squeel by
9
- [Ernie Miller](http://twitter.com/erniemiller).
9
+ [Ernie Miller](http://twitter.com/erniemiller) and maintained by
10
+ [Ryan Bigg](http://twitter.com/ryanbigg),
11
+ [Xiang Li](http://bigxiang.github.io),
12
+ [Jon Atack](http://twitter.com/jonatack) and a great group of
13
+ [contributors]
14
+ (https://github.com/activerecord-hackery/polyamorous/graphs/contributors).
10
15
 
11
16
  ## Copyright
12
17
 
13
- Copyright © 2011-2014 [Ernie Miller](http://twitter.com/erniemiller)
18
+ Copyright © 2011-2015 [Ernie Miller](http://twitter.com/erniemiller)
@@ -1,4 +1,4 @@
1
- require "polyamorous/version"
1
+ require 'polyamorous/version'
2
2
 
3
3
  if defined?(::ActiveRecord)
4
4
  module Polyamorous
@@ -23,20 +23,38 @@ if defined?(::ActiveRecord)
23
23
 
24
24
  require 'polyamorous/tree_node'
25
25
  require 'polyamorous/join'
26
+ require 'polyamorous/swapping_reflection_class'
26
27
 
27
- if ActiveRecord::VERSION::STRING >= "4.2"
28
- require 'polyamorous/activerecord_4.1/join_association'
29
- require 'polyamorous/activerecord_4.2/join_dependency'
30
- elsif ActiveRecord::VERSION::STRING >= "4.1"
31
- require 'polyamorous/activerecord_4.1/join_association'
32
- require 'polyamorous/activerecord_4.1/join_dependency'
33
- else
34
- require 'polyamorous/activerecord_3_and_4.0/join_association'
35
- require 'polyamorous/activerecord_3_and_4.0/join_dependency'
28
+ ar_version =
29
+ case ::ActiveRecord::VERSION::STRING[0,3]
30
+ when '4.2', '5.0'
31
+ '4.2'
32
+ when '4.1'
33
+ '4.1'
34
+ else
35
+ '3_and_4.0'
36
+ end
37
+
38
+ method, ruby_version =
39
+ if RUBY_VERSION >= '2.0' && ar_version >= '4.1'
40
+ # Ruby 2; we can use `prepend` to patch Active Record cleanly.
41
+ [:prepend, '2']
42
+ else
43
+ # Ruby 1.9; we must use `alias_method` to patch Active Record.
44
+ [:include, '1.9']
45
+ end
46
+
47
+ %w(join_association join_dependency).each do |file|
48
+ require "polyamorous/activerecord_#{ar_version}_ruby_#{ruby_version}/#{file}"
49
+ end
50
+
51
+ Polyamorous::JoinDependency.send(method, Polyamorous::JoinDependencyExtensions)
52
+ if method == :prepend
53
+ Polyamorous::JoinDependency.singleton_class
54
+ .send(:prepend, Polyamorous::JoinDependencyExtensions::ClassMethods)
36
55
  end
56
+ Polyamorous::JoinAssociation.send(method, Polyamorous::JoinAssociationExtensions)
37
57
 
38
- Polyamorous::JoinDependency.send(:include, Polyamorous::JoinDependencyExtensions)
39
- Polyamorous::JoinAssociation.send(:include, Polyamorous::JoinAssociationExtensions)
40
58
  Polyamorous::JoinBase.class_eval do
41
59
  if method_defined?(:active_record)
42
60
  alias_method :base_klass, :active_record
@@ -1,6 +1,7 @@
1
+ # active_record_3_and_4.0_ruby_1.9/join_association.rb
1
2
  module Polyamorous
2
3
  module JoinAssociationExtensions
3
-
4
+ include SwappingReflectionClass
4
5
  def self.included(base)
5
6
  base.class_eval do
6
7
  alias_method_chain :initialize, :polymorphism
@@ -18,7 +19,9 @@ module Polyamorous
18
19
  end
19
20
  end
20
21
 
21
- def initialize_with_polymorphism(reflection, join_dependency, parent = nil, polymorphic_class = nil)
22
+ def initialize_with_polymorphism(
23
+ reflection, join_dependency, parent = nil, polymorphic_class = nil
24
+ )
22
25
  if polymorphic_class && ::ActiveRecord::Base > polymorphic_class
23
26
  swapping_reflection_klass(reflection, polymorphic_class) do |reflection|
24
27
  initialize_without_polymorphism(reflection, join_dependency, parent)
@@ -29,47 +32,45 @@ module Polyamorous
29
32
  end
30
33
  end
31
34
 
32
- def swapping_reflection_klass(reflection, klass)
33
- new_reflection = reflection.clone
34
- new_reflection.instance_variable_set(:@options, reflection.options.clone)
35
- new_reflection.options.delete(:polymorphic)
36
- new_reflection.instance_variable_set(:@klass, klass)
37
- yield new_reflection
38
- end
39
-
40
35
  def equality_with_polymorphism(other)
41
36
  equality_without_polymorphism(other) && base_klass == other.base_klass
42
37
  end
43
38
 
44
- def build_constraint_with_polymorphism(reflection, table, key, foreign_table, foreign_key)
39
+ def build_constraint_with_polymorphism(
40
+ reflection, table, key, foreign_table, foreign_key
41
+ )
45
42
  if reflection.options[:polymorphic]
46
- build_constraint_without_polymorphism(reflection, table, key, foreign_table, foreign_key).and(
47
- foreign_table[reflection.foreign_type].eq(reflection.klass.name)
43
+ build_constraint_without_polymorphism(
44
+ reflection, table, key, foreign_table, foreign_key
48
45
  )
46
+ .and(foreign_table[reflection.foreign_type].eq(reflection.klass.name))
49
47
  else
50
- build_constraint_without_polymorphism(reflection, table, key, foreign_table, foreign_key)
48
+ build_constraint_without_polymorphism(
49
+ reflection, table, key, foreign_table, foreign_key
50
+ )
51
51
  end
52
52
  end
53
53
 
54
54
  def association_join_with_polymorphism
55
55
  return @join if @Join
56
-
57
56
  @join = association_join_without_polymorphism
58
-
59
57
  if reflection.macro == :belongs_to && reflection.options[:polymorphic]
60
- aliased_table = Arel::Table.new(table_name, :as => @aliased_table_name,
61
- :engine => arel_engine,
62
- :columns => klass.columns)
63
-
64
- parent_table = Arel::Table.new(parent.table_name, :as => parent.aliased_table_name,
65
- :engine => arel_engine,
66
- :columns => parent.base_klass.columns)
67
-
68
- @join << parent_table[reflection.options[:foreign_type]].eq(reflection.klass.name)
58
+ aliased_table = Arel::Table.new(
59
+ table_name,
60
+ as: @aliased_table_name,
61
+ engine: arel_engine,
62
+ columns: klass.columns
63
+ )
64
+ parent_table = Arel::Table.new(
65
+ parent.table_name,
66
+ as: parent.aliased_table_name,
67
+ engine: arel_engine,
68
+ columns: parent.base_klass.columns
69
+ )
70
+ @join << parent_table[reflection.options[:foreign_type]]
71
+ .eq(reflection.klass.name)
69
72
  end
70
-
71
73
  @join
72
74
  end
73
-
74
75
  end
75
76
  end
@@ -1,3 +1,4 @@
1
+ # active_record_3_and_4.0_ruby_1.9/join_dependency.rb
1
2
  module Polyamorous
2
3
  module JoinDependencyExtensions
3
4
  def self.included(base)
@@ -45,22 +46,24 @@ module Polyamorous
45
46
  end
46
47
  end
47
48
 
48
- def build_with_polymorphism(associations, parent = nil, join_type = InnerJoin)
49
+ def build_with_polymorphism(
50
+ associations, parent = nil, join_type = InnerJoin
51
+ )
49
52
  case associations
50
53
  when Join
51
54
  parent ||= _join_parts.last
52
55
  reflection = parent.reflections[associations.name] or
53
56
  raise ::ActiveRecord::ConfigurationError,
54
57
  "Association named '#{associations.name
55
- }' was not found; perhaps you misspelled it?"
58
+ }' was not found; perhaps you misspelled it?"
56
59
 
57
60
  unless join_association = find_join_association_respecting_polymorphism(
58
61
  reflection, parent, associations.klass
59
- )
62
+ )
60
63
  @reflections << reflection
61
64
  join_association = build_join_association_respecting_polymorphism(
62
65
  reflection, parent, associations.klass
63
- )
66
+ )
64
67
  join_association.join_type = associations.type
65
68
  _join_parts << join_association
66
69
  cache_joined_association(join_association)
@@ -0,0 +1,2 @@
1
+ # active_record_4.1_ruby_1.9/join_association.rb
2
+ require 'polyamorous/activerecord_4.2_ruby_1.9/join_association'
@@ -0,0 +1,4 @@
1
+ # active_record_4.1_ruby_1.9/join_dependency.rb
2
+ require 'polyamorous/activerecord_4.2_ruby_2/join_dependency'
3
+ require 'polyamorous/activerecord_4.2_ruby_1.9/join_dependency'
4
+ require 'polyamorous/activerecord_4.1_ruby_2/make_joins'
@@ -0,0 +1,2 @@
1
+ # active_record_4.1_ruby_2/join_association.rb
2
+ require 'polyamorous/activerecord_4.2_ruby_2/join_association'
@@ -0,0 +1,3 @@
1
+ # active_record_4.1_ruby_2/join_dependency.rb
2
+ require 'polyamorous/activerecord_4.2_ruby_2/join_dependency'
3
+ require 'polyamorous/activerecord_4.1_ruby_2/make_joins'
@@ -0,0 +1,11 @@
1
+ module Polyamorous
2
+ module JoinDependencyExtensions
3
+ # Replaces ActiveRecord::Associations::JoinDependency#make_inner_joins
4
+ def make_joins(parent, child)
5
+ make_constraints(
6
+ parent, child, child.tables, child.join_type || Arel::Nodes::InnerJoin
7
+ )
8
+ .concat child.children.flat_map { |c| make_inner_joins(child, c) }
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,46 @@
1
+ # active_record_4.2_ruby_1.9/join_association.rb
2
+ module Polyamorous
3
+ module JoinAssociationExtensions
4
+ include SwappingReflectionClass
5
+ def self.included(base)
6
+ base.class_eval do
7
+ attr_reader :join_type
8
+ alias_method_chain :initialize, :polymorphism
9
+ alias_method_chain :build_constraint, :polymorphism
10
+ end
11
+ end
12
+
13
+ def initialize_with_polymorphism(reflection, children,
14
+ polymorphic_class = nil, join_type = Arel::Nodes::InnerJoin)
15
+ @join_type = join_type
16
+ if polymorphic_class && ::ActiveRecord::Base > polymorphic_class
17
+ swapping_reflection_klass(reflection, polymorphic_class) do |reflection|
18
+ initialize_without_polymorphism(reflection, children)
19
+ self.reflection.options[:polymorphic] = true
20
+ end
21
+ else
22
+ initialize_without_polymorphism(reflection, children)
23
+ end
24
+ end
25
+
26
+ # Reference https://github.com/rails/rails/commit/9b15db51b78028bfecdb85595624de4b838adbd1
27
+ def ==(other)
28
+ base_klass == other.base_klass
29
+ end
30
+
31
+ def build_constraint_with_polymorphism(
32
+ klass, table, key, foreign_table, foreign_key
33
+ )
34
+ if reflection.polymorphic?
35
+ build_constraint_without_polymorphism(
36
+ klass, table, key, foreign_table, foreign_key
37
+ )
38
+ .and(foreign_table[reflection.foreign_type].eq(reflection.klass.name))
39
+ else
40
+ build_constraint_without_polymorphism(
41
+ klass, table, key, foreign_table, foreign_key
42
+ )
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,94 @@
1
+ # active_record_4.2_ruby_1.9/join_dependency.rb
2
+ require 'polyamorous/activerecord_4.2_ruby_2/join_dependency'
3
+
4
+ module Polyamorous
5
+ module JoinDependencyExtensions
6
+ def self.included(base)
7
+ base.extend ClassMethods
8
+ base.class_eval do
9
+ class << self
10
+ alias_method :walk_tree_without_polymorphism, :walk_tree
11
+ alias_method :walk_tree, :walk_tree_with_polymorphism
12
+ end
13
+
14
+ alias_method :build_without_polymorphism, :build
15
+ alias_method :build, :build_with_polymorphism
16
+
17
+ alias_method :join_constraints_without_polymorphism, :join_constraints
18
+ alias_method :join_constraints, :join_constraints_with_polymorphism
19
+ end
20
+ end
21
+
22
+ # Replaces ActiveRecord::Associations::JoinDependency#build
23
+ def build_with_polymorphism(associations, base_klass)
24
+ associations.map do |name, right|
25
+ if name.is_a? Join
26
+ reflection = find_reflection base_klass, name.name
27
+ reflection.check_validity!
28
+ if reflection.polymorphic?
29
+ JoinAssociation.new(
30
+ reflection,
31
+ build(right, name.klass || base_klass),
32
+ name.klass,
33
+ name.type
34
+ )
35
+ else
36
+ JoinAssociation.new(
37
+ reflection,
38
+ build(right, reflection.klass),
39
+ name.klass,
40
+ name.type
41
+ )
42
+ end
43
+ else
44
+ reflection = find_reflection base_klass, name
45
+ reflection.check_validity!
46
+ if reflection.polymorphic?
47
+ raise ActiveRecord::EagerLoadPolymorphicError.new(reflection)
48
+ end
49
+ JoinAssociation.new reflection, build(right, reflection.klass)
50
+ end
51
+ end
52
+ end
53
+
54
+ # Replaces ActiveRecord::Associations::JoinDependency#join_constraints
55
+ # to call #make_joins instead of #make_inner_joins.
56
+ def join_constraints_with_polymorphism(outer_joins)
57
+ joins = join_root.children.flat_map { |child|
58
+ make_joins(join_root, child)
59
+ }
60
+ joins.concat outer_joins.flat_map { |oj|
61
+ if join_root.match? oj.join_root
62
+ walk(join_root, oj.join_root)
63
+ else
64
+ oj.join_root.children.flat_map { |child|
65
+ make_outer_joins(oj.join_root, child)
66
+ }
67
+ end
68
+ }
69
+ end
70
+
71
+ module ClassMethods
72
+ # Replaces ActiveRecord::Associations::JoinDependency#self.walk_tree
73
+ def walk_tree_with_polymorphism(associations, hash)
74
+ case associations
75
+ when TreeNode
76
+ associations.add_to_tree(hash)
77
+ when Hash
78
+ associations.each do |k, v|
79
+ cache =
80
+ case k
81
+ when TreeNode
82
+ k.add_to_tree(hash)
83
+ else
84
+ hash[k] ||= {}
85
+ end
86
+ walk_tree(v, cache)
87
+ end
88
+ else
89
+ walk_tree_without_polymorphism(associations, hash)
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end