Commit 0a3501c9 authored by ameera's avatar ameera

Import Upstream version 1.3.3

parents
*.gem
.bundle
Gemfile.lock
pkg/*
.ruby-version
.ruby-gemset
language: ruby
sudo: false
cache: bundler
before_install:
- travis_retry gem install bundler
rvm:
- 2.5.0
- 2.4.3
- 2.3.6
- 2.2.9
env:
- RAILS=4-2-stable AREL=6-0-stable DB=sqlite
- RAILS=4-2-stable AREL=6-0-stable DB=mysql
- RAILS=4-2-stable AREL=6-0-stable DB=postgres
- RAILS=5-0-stable AREL=7-0-stable DB=sqlite
- RAILS=5-0-stable AREL=7-0-stable DB=mysql
- RAILS=5-0-stable AREL=7-0-stable DB=postgres
- RAILS=5-1-stable AREL=8-0-stable DB=sqlite
- RAILS=5-1-stable AREL=8-0-stable DB=mysql
- RAILS=5-1-stable AREL=8-0-stable DB=postgres
matrix:
include:
- rvm: 2.5.0
env: RAILS=master DB=sqlite3
- rvm: 2.5.0
env: RAILS=master DB=mysql
- rvm: 2.5.0
env: RAILS=master DB=postgres
- rvm: 2.4.3
env: RAILS=master DB=sqlite3
- rvm: 2.4.3
env: RAILS=master DB=mysql
- rvm: 2.4.3
env: RAILS=master DB=postgres
- rvm: 2.3.6
env: RAILS=master DB=sqlite3
- rvm: 2.3.6
env: RAILS=master DB=mysql
- rvm: 2.3.6
env: RAILS=master DB=postgres
- rvm: 2.2.9
env: RAILS=master DB=sqlite3
- rvm: 2.2.9
env: RAILS=master DB=mysql
- rvm: 2.2.9
env: RAILS=master DB=postgres
before_script:
- mysql -e 'create database ransack collate utf8_general_ci;'
- mysql -e 'use ransack;show variables like "%character%";show variables like "%collation%";'
- psql -c 'create database ransack;' -U postgres
source 'https://rubygems.org'
gemspec
gem 'rake'
rails = ENV['RAILS'] || 'master'
if rails == 'master'
arel = ENV['AREL'] || 'master'
arel_opts =
case arel
when /\// # A path
{ path: arel }
when /^v/ # A tagged version
{ git: 'git://github.com/rails/arel.git', tag: arel }
else
{ git: 'git://github.com/rails/arel.git', branch: arel }
end
gem 'arel', arel_opts
end
case rails
when /\// # A path
gem 'activerecord', path: "#{rails}/activerecord"
when /^v/ # A tagged version
git 'git://github.com/rails/rails.git', tag: rails do
gem 'activerecord'
end
else
git 'git://github.com/rails/rails.git', branch: rails do
gem 'activerecord'
end
end
Copyright (c) 2011 Ernie Miller
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# Polyamorous
[![Build Status](https://travis-ci.org/activerecord-hackery/polyamorous.svg?branch=master)](https://travis-ci.org/activerecord-hackery/polyamorous)
[![Gem Version](https://badge.fury.io/rb/polyamorous.svg)](https://badge.fury.io/rb/polyamorous)
[![Code Climate](https://codeclimate.com/github/activerecord-hackery/polyamorous/badges/gpa.svg)](https://codeclimate.com/github/activerecord-hackery/polyamorous)
Polyamorous is an extraction of shared code from the
[Active Record Hackery](https://github.com/activerecord-hackery) gems
[Ransack](https://github.com/activerecord-hackery/ransack),
[Squeel](https://github.com/activerecord-hackery/squeel) and
[MetaSearch](https://github.com/activerecord-hackery/meta_search) by
[Ernie Miller](http://twitter.com/erniemiller) and maintained by
[Ryan Bigg](http://twitter.com/ryanbigg),
[Xiang Li](http://bigxiang.github.io),
[Jon Atack](http://twitter.com/jonatack),
[Sean Carroll](https://github.com/seanfcarroll) and a great little group of
[contributors]
(https://github.com/activerecord-hackery/polyamorous/graphs/contributors).
It is an internal library for extending various versions of Active Record with
polymorphism. There is no public API, so it's `:nodoc:`. Move along. Nothing to
see here.
require 'bundler/gem_tasks'
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec) do |rspec|
rspec.rspec_opts = ['--backtrace']
end
task :default => :spec
desc "Open an irb session with Ransack and the sample data used in specs"
task :console do
require 'irb'
require 'irb/completion'
require 'console'
ARGV.clear
IRB.start
end
\ No newline at end of file
require 'polyamorous/version'
if defined?(::ActiveRecord)
module Polyamorous
if defined?(Arel::InnerJoin)
InnerJoin = Arel::InnerJoin
OuterJoin = Arel::OuterJoin
else
InnerJoin = Arel::Nodes::InnerJoin
OuterJoin = Arel::Nodes::OuterJoin
end
if defined?(::ActiveRecord::Associations::JoinDependency)
JoinDependency = ::ActiveRecord::Associations::JoinDependency
JoinAssociation = ::ActiveRecord::Associations::JoinDependency::JoinAssociation
JoinBase = ::ActiveRecord::Associations::JoinDependency::JoinBase
else
JoinDependency = ::ActiveRecord::Associations::ClassMethods::JoinDependency
JoinAssociation = ::ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation
JoinBase = ::ActiveRecord::Associations::ClassMethods::JoinDependency::JoinBase
end
end
require 'polyamorous/tree_node'
require 'polyamorous/join'
require 'polyamorous/swapping_reflection_class'
ar_version = ::ActiveRecord::VERSION::STRING[0,3]
ar_version = '3_and_4.0' if ar_version < '4.1'
method, ruby_version =
if RUBY_VERSION >= '2.0' && ar_version >= '4.1'
# Ruby 2; we can use `prepend` to patch Active Record cleanly.
[:prepend, '2']
else
# Ruby 1.9; we must use `alias_method` to patch Active Record.
[:include, '1.9']
end
%w(join_association join_dependency).each do |file|
require "polyamorous/activerecord_#{ar_version}_ruby_#{ruby_version}/#{file}"
end
Polyamorous::JoinDependency.send(method, Polyamorous::JoinDependencyExtensions)
if method == :prepend
Polyamorous::JoinDependency.singleton_class
.send(:prepend, Polyamorous::JoinDependencyExtensions::ClassMethods)
end
Polyamorous::JoinAssociation.send(method, Polyamorous::JoinAssociationExtensions)
Polyamorous::JoinBase.class_eval do
if method_defined?(:active_record)
alias_method :base_klass, :active_record
end
end
end
# active_record_3_and_4.0_ruby_1.9/join_association.rb
module Polyamorous
module JoinAssociationExtensions
include SwappingReflectionClass
def self.included(base)
base.class_eval do
alias_method_chain :initialize, :polymorphism
alias_method :equality_without_polymorphism, :==
alias_method :==, :equality_with_polymorphism
if base.method_defined?(:active_record)
alias_method :base_klass, :active_record
end
if ActiveRecord::VERSION::STRING =~ /^3\.0\./
alias_method_chain :association_join, :polymorphism
else
alias_method_chain :build_constraint, :polymorphism
end
end
end
def initialize_with_polymorphism(
reflection, join_dependency, parent = nil, polymorphic_class = nil
)
if polymorphic_class && ::ActiveRecord::Base > polymorphic_class
swapping_reflection_klass(reflection, polymorphic_class) do |reflection|
initialize_without_polymorphism(reflection, join_dependency, parent)
self.reflection.options[:polymorphic] = true
end
else
initialize_without_polymorphism(reflection, join_dependency, parent)
end
end
def equality_with_polymorphism(other)
equality_without_polymorphism(other) && base_klass == other.base_klass
end
def build_constraint_with_polymorphism(
reflection, table, key, foreign_table, foreign_key
)
if reflection.options[:polymorphic]
build_constraint_without_polymorphism(
reflection, table, key, foreign_table, foreign_key
)
.and(foreign_table[reflection.foreign_type].eq(reflection.klass.name))
else
build_constraint_without_polymorphism(
reflection, table, key, foreign_table, foreign_key
)
end
end
def association_join_with_polymorphism
return @join if @Join
@join = association_join_without_polymorphism
if reflection.macro == :belongs_to && reflection.options[:polymorphic]
aliased_table = Arel::Table.new(
table_name,
as: @aliased_table_name,
engine: arel_engine,
columns: klass.columns
)
parent_table = Arel::Table.new(
parent.table_name,
as: parent.aliased_table_name,
engine: arel_engine,
columns: parent.base_klass.columns
)
@join << parent_table[reflection.options[:foreign_type]]
.eq(reflection.klass.name)
end
@join
end
end
end
# active_record_3_and_4.0_ruby_1.9/join_dependency.rb
module Polyamorous
module JoinDependencyExtensions
def self.included(base)
base.class_eval do
alias_method_chain :build, :polymorphism
alias_method_chain :graft, :polymorphism
if base.method_defined?(:active_record)
alias_method :base_klass, :active_record
end
end
end
def graft_with_polymorphism(*associations)
associations.each do |association|
unless join_associations.detect { |a| association == a }
if association.reflection.options[:polymorphic]
build(
Join.new(
association.reflection.name,
association.join_type,
association.reflection.klass
),
association.find_parent_in(self) || join_base,
association.join_type
)
else
build(
association.reflection.name,
association.find_parent_in(self) || join_base,
association.join_type
)
end
end
end
self
end
if ActiveRecord::VERSION::STRING =~ /^3\.0\./
def _join_parts
@joins
end
else
def _join_parts
@join_parts
end
end
def build_with_polymorphism(
associations, parent = nil, join_type = InnerJoin
)
case associations
when Join
parent ||= _join_parts.last
reflection = parent.reflections[associations.name] or
raise ::ActiveRecord::ConfigurationError,
"Association named '#{associations.name
}' was not found; perhaps you misspelled it?"
unless join_association = find_join_association_respecting_polymorphism(
reflection, parent, associations.klass
)
@reflections << reflection
join_association = build_join_association_respecting_polymorphism(
reflection, parent, associations.klass
)
join_association.join_type = associations.type
_join_parts << join_association
cache_joined_association(join_association)
end
join_association
else
build_without_polymorphism(associations, parent, join_type)
end
end
def find_join_association_respecting_polymorphism(reflection, parent, klass)
if association = find_join_association(reflection, parent)
unless reflection.options[:polymorphic]
association
else
association if association.base_klass == klass
end
end
end
def build_join_association_respecting_polymorphism(reflection, parent, klass)
if reflection.options[:polymorphic] && klass
JoinAssociation.new(reflection, self, parent, klass)
else
JoinAssociation.new(reflection, self, parent)
end
end
end
end
# active_record_4.1_ruby_1.9/join_association.rb
require 'polyamorous/activerecord_4.2_ruby_1.9/join_association'
# active_record_4.1_ruby_1.9/join_dependency.rb
require 'polyamorous/activerecord_4.2_ruby_2/join_dependency'
require 'polyamorous/activerecord_4.2_ruby_1.9/join_dependency'
require 'polyamorous/activerecord_4.1_ruby_2/make_polyamorous_inner_joins'
# active_record_4.1_ruby_2/join_association.rb
require 'polyamorous/activerecord_5.0_ruby_2/join_association'
# active_record_4.1_ruby_2/join_dependency.rb
require 'polyamorous/activerecord_4.2_ruby_2/join_dependency'
require 'polyamorous/activerecord_4.1_ruby_2/make_polyamorous_inner_joins'
module Polyamorous
module JoinDependencyExtensions
# Replaces ActiveRecord::Associations::JoinDependency#make_inner_joins
#
def make_polyamorous_inner_joins(parent, child)
make_constraints(
parent, child, child.tables, child.join_type || Arel::Nodes::InnerJoin
)
.concat child.children.flat_map { |c|
make_polyamorous_inner_joins(child, c)
}
end
end
end
# active_record_4.2_ruby_1.9/join_association.rb
module Polyamorous
module JoinAssociationExtensions
include SwappingReflectionClass
def self.included(base)
base.class_eval do
attr_reader :join_type
alias_method_chain :initialize, :polymorphism
alias_method_chain :build_constraint, :polymorphism
end
end
def initialize_with_polymorphism(reflection, children,
polymorphic_class = nil, join_type = Arel::Nodes::InnerJoin)
@join_type = join_type
if polymorphic_class && ::ActiveRecord::Base > polymorphic_class
swapping_reflection_klass(reflection, polymorphic_class) do |reflection|
initialize_without_polymorphism(reflection, children)
self.reflection.options[:polymorphic] = true
end
else
initialize_without_polymorphism(reflection, children)
end
end
# Reference https://github.com/rails/rails/commit/9b15db51b78028bfecdb85595624de4b838adbd1
def ==(other)
base_klass == other.base_klass
end
def build_constraint_with_polymorphism(
klass, table, key, foreign_table, foreign_key
)
if reflection.polymorphic?
build_constraint_without_polymorphism(
klass, table, key, foreign_table, foreign_key
)
.and(foreign_table[reflection.foreign_type].eq(reflection.klass.name))
else
build_constraint_without_polymorphism(
klass, table, key, foreign_table, foreign_key
)
end
end
end
end
# active_record_4.2_ruby_1.9/join_dependency.rb
require 'polyamorous/activerecord_4.2_ruby_2/join_dependency'
module Polyamorous
module JoinDependencyExtensions
def self.included(base)
base.extend ClassMethods
base.class_eval do
class << self
alias_method :walk_tree_without_polymorphism, :walk_tree
alias_method :walk_tree, :walk_tree_with_polymorphism
end
alias_method :build_without_polymorphism, :build
alias_method :build, :build_with_polymorphism
alias_method :join_constraints_without_polymorphism, :join_constraints
alias_method :join_constraints, :join_constraints_with_polymorphism
end
end
# Replaces ActiveRecord::Associations::JoinDependency#build
#
def build_with_polymorphism(associations, base_klass)
associations.map do |name, right|
if name.is_a? Join
reflection = find_reflection base_klass, name.name
reflection.check_validity!
klass = if reflection.polymorphic?
name.klass || base_klass
else
reflection.klass
end
JoinAssociation.new(reflection, build(right, klass), name.klass, name.type)
else
reflection = find_reflection base_klass, name
reflection.check_validity!
if reflection.polymorphic?
raise ActiveRecord::EagerLoadPolymorphicError.new(reflection)
end
JoinAssociation.new reflection, build(right, reflection.klass)
end
end
end
# Replaces ActiveRecord::Associations::JoinDependency#join_constraints
# to call #make_polyamorous_inner_joins instead of #make_inner_joins
#
def join_constraints_with_polymorphism(outer_joins)
joins = join_root.children.flat_map { |child|
make_polyamorous_inner_joins join_root, child
}
joins.concat outer_joins.flat_map { |oj|
if join_root.match? oj.join_root
walk(join_root, oj.join_root)
else
oj.join_root.children.flat_map { |child|
make_outer_joins(oj.join_root, child)
}
end
}
end
module ClassMethods
# Replaces ActiveRecord::Associations::JoinDependency#self.walk_tree
#
def walk_tree_with_polymorphism(associations, hash)
case associations
when TreeNode
associations.add_to_tree(hash)
when Hash
associations.each do |k, v|
cache =
if TreeNode === k
k.add_to_tree(hash)
else
hash[k] ||= {}
end
walk_tree(v, cache)
end
else
walk_tree_without_polymorphism(associations, hash)
end
end
end
end
end
# active_record_4.2_ruby_2/join_association.rb
require 'polyamorous/activerecord_5.0_ruby_2/join_association'
# active_record_4.2_ruby_2/join_dependency.rb
require 'polyamorous/activerecord_5.0_ruby_2/join_dependency'
module Polyamorous
module JoinDependencyExtensions
# Replaces ActiveRecord::Associations::JoinDependency#join_constraints
# to call #make_polyamorous_inner_joins instead of #make_inner_joins.
#
def join_constraints(outer_joins)
joins = join_root.children.flat_map { |child|
make_polyamorous_inner_joins join_root, child
}
joins.concat outer_joins.flat_map { |oj|
if join_root.match? oj.join_root
walk(join_root, oj.join_root)
else
oj.join_root.children.flat_map { |child|
make_outer_joins(oj.join_root, child)
}
end
}
end
end
end
# active_record_5.0_ruby_2/join_association.rb
require 'polyamorous/activerecord_5.1_ruby_2/join_association'
# active_record_5.0_ruby_2/join_dependency.rb
require 'polyamorous/activerecord_5.1_ruby_2/join_dependency'
# active_record_5.1_ruby_2/join_association.rb
module Polyamorous
module JoinAssociationExtensions
include SwappingReflectionClass
def self.prepended(base)
base.class_eval { attr_reader :join_type }
end
def initialize(reflection, children, polymorphic_class = nil,
join_type = Arel::Nodes::InnerJoin)
@join_type = join_type
if polymorphic_class && ::ActiveRecord::Base > polymorphic_class
swapping_reflection_klass(reflection, polymorphic_class) do |reflection|
super(reflection, children)
self.reflection.options[:polymorphic] = true
end
else
super(reflection, children)
end
end
# Reference: https://github.com/rails/rails/commit/9b15db5
# NOTE: Not sure we still need it?
#
def ==(other)
base_klass == other.base_klass
end
def build_constraint(klass, table, key, foreign_table, foreign_key)
if reflection.polymorphic?
super(klass, table, key, foreign_table, foreign_key)
.and(foreign_table[reflection.foreign_type].eq(reflection.klass.name))
else
super(klass, table, key, foreign_table, foreign_key)
end
end
end
end
# active_record_5.1_ruby_2/join_dependency.rb
module Polyamorous
module JoinDependencyExtensions
# Replaces ActiveRecord::Associations::JoinDependency#build
#
def build(associations, base_klass)
associations.map do |name, right|
if name.is_a? Join
reflection = find_reflection base_klass, name.name
reflection.check_validity!
reflection.check_eager_loadable! if ActiveRecord::VERSION::MAJOR >= 5
klass = if reflection.polymorphic?
name.klass || base_klass
else
reflection.klass
end
JoinAssociation.new(reflection, build(right, klass), name.klass, name.type)
else
reflection = find_reflection base_klass, name
reflection.check_validity!
reflection.check_eager_loadable! if ActiveRecord::VERSION::MAJOR >= 5
if reflection.polymorphic?
raise ActiveRecord::EagerLoadPolymorphicError.new(reflection)
end
JoinAssociation.new reflection, build(right, reflection.klass)
end
end
end
def find_join_association_respecting_polymorphism(reflection, parent, klass)
if association = parent.children.find { |j| j.reflection == reflection }
unless reflection.polymorphic?
association
else
association if association.base_klass == klass
end
end
end
def build_join_association_respecting_polymorphism(reflection, parent, klass)
if reflection.polymorphic? && klass
JoinAssociation.new(reflection, self, klass)
else
JoinAssociation.new(reflection, self)
end
end
# Replaces ActiveRecord::Associations::JoinDependency#join_constraints
#
# This internal method was changed in Rails 5.0 by commit
# https://github.com/rails/rails/commit/e038975 which added
# left_outer_joins (see #make_polyamorous_left_outer_joins below) and added
# passing an additional argument, `join_type`, to #join_constraints.
#
def join_constraints(outer_joins, join_type)
joins = join_root.children.flat_map { |child|
if join_type == Arel::Nodes::OuterJoin
make_polyamorous_left_outer_joins join_root, child
else
make_polyamorous_inner_joins join_root, child
end