Skip to content

Commit

Permalink
fixed joins association
Browse files Browse the repository at this point in the history
  • Loading branch information
stasl committed Apr 5, 2016
1 parent e4e062c commit 1167b19
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 1 deletion.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,6 @@ gemfile:
- gemfiles/rails_4.2.3.gemfile
- gemfiles/rails_4.2.4.gemfile
- gemfiles/rails_4.2.5.1.gemfile
- gemfiles/rails_4.2.6.gemfile

sudo: false
1 change: 1 addition & 0 deletions Appraisals
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ RAILS_VERSIONS = %w(
4.2.3
4.2.4
4.2.5.1
4.2.6
)

RAILS_VERSIONS.each do |version|
Expand Down
7 changes: 7 additions & 0 deletions gemfiles/rails_4.2.6.gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# This file was generated by Appraisal

source "https://rubygems.org"

gem "activerecord", "4.2.6"

gemspec :path => "../"
7 changes: 6 additions & 1 deletion lib/store_base_sti_class_for_4_1.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,12 @@ def join_constraints(foreign_table, foreign_klass, node, join_type, tables, scop
end
scope_chain_index += 1

scope_chain_items.concat [klass.send(:build_default_scope, ActiveRecord::Relation.create(klass, table))].compact
default_scope = if klass.method(:build_default_scope).arity == 0
klass.send(:build_default_scope)
else
klass.send(:build_default_scope, ActiveRecord::Relation.create(klass, table))
end
scope_chain_items.concat [default_scope].compact

rel = scope_chain_items.inject(scope_chain_items.shift) do |left, right|
left.merge right
Expand Down
89 changes: 89 additions & 0 deletions lib/store_base_sti_class_for_4_2.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require 'active_record/associations/join_dependency/join_part'

if ActiveRecord::VERSION::STRING =~ /^4\.2/
module ActiveRecord

Expand Down Expand Up @@ -29,6 +31,72 @@ def creation_attributes
end
end

class JoinDependency # :nodoc:
class JoinAssociation < JoinPart # :nodoc:
def join_constraints(foreign_table, foreign_klass, node, join_type, tables, scope_chain, chain)
joins = []
bind_values = []
tables = tables.reverse

scope_chain_index = 0
scope_chain = scope_chain.reverse

# The chain starts with the target table, but we want to end with it here (makes
# more sense in this context), so we reverse
chain.reverse_each do |reflection|
table = tables.shift
klass = reflection.klass

join_keys = reflection.join_keys(klass)
key = join_keys.key
foreign_key = join_keys.foreign_key

constraint = build_constraint(klass, table, key, foreign_table, foreign_key)

scope_chain_items = scope_chain[scope_chain_index].map do |item|
if item.is_a?(Relation)
item
else
ActiveRecord::Relation.create(klass, table).instance_exec(node, &item)
end
end
scope_chain_index += 1

scope_chain_items.concat [klass.send(:build_default_scope, ActiveRecord::Relation.create(klass, table))].compact

rel = scope_chain_items.inject(scope_chain_items.shift) do |left, right|
left.merge right
end

if rel && !rel.arel.constraints.empty?
bind_values.concat rel.bind_values
constraint = constraint.and rel.arel.constraints
end

if reflection.type
# START PATCH
# original:
# value = foreign_klass.base_class.name
value = ActiveRecord::Base.store_base_sti_class ? foreign_klass.base_class.name : foreign_klass.name
# END PATCH
column = klass.columns_hash[reflection.type.to_s]

substitute = klass.connection.substitute_at(column)
bind_values.push [column, value]
constraint = constraint.and table[reflection.type].eq substitute
end

joins << table.create_join(table, table.create_on(constraint), join_type)

# The current table in this iteration becomes the foreign table in the next
foreign_table, foreign_klass = table, klass
end

JoinInformation.new joins, bind_values
end
end
end

class BelongsToPolymorphicAssociation
private

Expand Down Expand Up @@ -231,6 +299,27 @@ def construct_join_attributes(*records)

end

class HasManyThroughAssociation

def build_through_record(record)
@through_records[record.object_id] ||= begin
ensure_mutable

through_record = through_association.build(*options_for_through_record)
through_record.send("#{source_reflection.name}=", record)

# START PATCH
if ActiveRecord::Base.store_base_sti_class
if options[:source_type]
through_record.send("#{source_reflection.foreign_type}=", options[:source_type])
end
end
# END PATCH

through_record
end
end
end
end

module Reflection
Expand Down
7 changes: 7 additions & 0 deletions test/test_store_base_sti_class.rb
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,13 @@ def test_polymorphic_has_many_through_with_double_sti_on_join_model
assert_equal post, tagging.taggable
end

def test_join_association
tag = SpecialTag.create!(:name => 'Special')
tag.polytaggings << Tagging.new

assert SpecialTag.joins(:polytaggings).where(id: tag.id).first
end

if Gem::Version.new(ActiveRecord::VERSION::STRING) < Gem::Version.new('4.1.0')
def test_finder_sql_is_supported
author = Author.create!(:name => 'Bob')
Expand Down

0 comments on commit 1167b19

Please sign in to comment.