diff --git a/lib/baby_squeel.rb b/lib/baby_squeel.rb index 9b0b2fc..ffff872 100644 --- a/lib/baby_squeel.rb +++ b/lib/baby_squeel.rb @@ -7,6 +7,14 @@ require 'baby_squeel/active_record/query_methods' require 'baby_squeel/active_record/where_chain' +# FIXME: This DEFINITELY doesn't belong here. +class Arel::Nodes::TableAlias + def on(node = nil, &block) + table = BabySqueel::Table.new(self) + table.on(node, &block) + end +end + module BabySqueel class << self # Configures BabySqueel using the given block diff --git a/lib/baby_squeel/dsl.rb b/lib/baby_squeel/dsl.rb index 5cdaa97..0bd8f31 100644 --- a/lib/baby_squeel/dsl.rb +++ b/lib/baby_squeel/dsl.rb @@ -93,16 +93,6 @@ def quoted(value) sql _scope.connection.quote(value) end - # Evaluates a DSL block. If arity is given, this method - # `yield` itself, rather than `instance_eval`. - def evaluate(&block) - if block.arity.zero? - instance_eval(&block) - else - yield(self) - end - end - private def method_missing(meth, *args, &block) diff --git a/lib/baby_squeel/table.rb b/lib/baby_squeel/table.rb index 2a499ad..11555cc 100644 --- a/lib/baby_squeel/table.rb +++ b/lib/baby_squeel/table.rb @@ -51,15 +51,29 @@ def inner! # :nodoc: end # Specify an explicit join. - def on(node) - clone.on! node + def on(node = nil, &block) + clone.on!(node, &block) end - def on!(node) # :nodoc: - self._on = node + def on!(node = nil, &block) # :nodoc: + if node.nil? && !block_given? + raise 'FIXME: A proper error should be risen here!' + end + + self._on = node || evaluate(&block) self end + # Evaluates a DSL block. If arity is given, this method + # `yield` itself, rather than `instance_eval`. + def evaluate(&block) + if block.arity.zero? + instance_eval(&block) + else + yield(self) + end + end + # When referencing a joined table, the tables that # attributes reference can change (due to aliasing). # This method allows BabySqueel::Nodes::Attribute @@ -98,7 +112,11 @@ def not_found_error! end def resolve(name) - self[name] + if _table.kind_of?(Arel::Nodes::TableAlias) && _table.name == name.to_s + self + else + self[name] + end end def respond_to_missing?(name, *) diff --git a/spec/integration/joining_spec.rb b/spec/integration/joining_spec.rb index 69be8fe..fd6b870 100644 --- a/spec/integration/joining_spec.rb +++ b/spec/integration/joining_spec.rb @@ -1,6 +1,23 @@ require 'spec_helper' describe BabySqueel::ActiveRecord::QueryMethods, '#joining' do + context 'joining relations' do + it 'allows on to accept a block' do + authors = Author.where(id: 2) + relation = Post.joining do + authors.as('a').on { a.id == author_id } + end + + expect(relation).to produce_sql(<<-EOSQL) + SELECT "posts".* FROM "posts" + INNER JOIN ( + SELECT "authors".* FROM "authors" + WHERE "authors"."id" = 2 + ) a ON a."id" = a."author_id" + EOSQL + end + end + context 'when joining explicitly' do it 'inner joins' do relation = Post.joining {