rzane/baby_squeel

Improper casting when joined tables share common column name but different column type

Closed this issue · 4 comments

Issue

If you have two tables with a common column name, but different column types, which you're joining via an association, baby_squeel improperly casts the column based on the column type of the primary table instead of the joining table. We setup two specs demonstrating the issue on our fork: https://github.com/boltthreads/baby_squeel

Reproduction

require 'bundler/inline'
require 'minitest/spec'
require 'minitest/autorun'

gemfile true do
  source 'https://rubygems.org'
  gem 'activerecord', '~> 5.0.0' # which Active Record version?
  gem 'sqlite3'
  gem 'baby_squeel', github: 'rzane/baby_squeel'
end

ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')

ActiveRecord::Schema.define do
  create_table :stations, force: true do |t|
    t.float :frequency
  end

  create_table :shows, force: true do |t|
    t.string :frequency
    t.belongs_to :station
  end
end

class Station < ActiveRecord::Base
  has_many :shows
end

class Show < ActiveRecord::Base
  belongs_to :station
end

class BabySqueelTest < Minitest::Spec

  describe "joining tables with matching attributes"  do
    describe "where the parent table column_type is float and the child table column_type is string" do
      describe "wheres based on the child model's attribute" do
        it 'uses the column_type of the child' do
          relation = Station.joins(:shows).where.has { shows.frequency == 'daily' }

          relation.to_sql.must_equal %{
            SELECT "stations".* FROM "stations"
            INNER JOIN "shows" ON "shows"."station_id" = "stations"."id"
            WHERE "shows"."frequency" = "daily"
          }.squish
        end
      end

      describe "wheres based on the parent model's attribute" do
        it 'uses the column_type of the parent' do
          relation = Show.joins(:station).where.has { station.frequency == 4.2 }

          relation.to_sql.must_equal %{
            SELECT "shows".* FROM "shows"
            INNER JOIN "stations" ON "stations"."id" = "shows"."station_id"
            WHERE "stations"."frequency" = 4.2
          }.squish
        end
      end
    end
  end

end
rzane commented

That's a weird one! It seems there's a silent bug in Active Record. By silent, I mean that I don't think you could come across it using the public API.

I have a workaround for this in mind, but this is the root of the issue: rails/rails#27994

Awesome. We weren't able to reproduce the issue using pure Active Record calls, so silent is an apt description. Thanks for responding so promptly! Look forward to either your own workaround or an eventual upstream fix.

Thanks! Worked like a charm!

rzane commented

Pushed v1.1.1 to RubyGems.