Skip to content

Instantly share code, notes, and snippets.

@coorasse
Created October 31, 2019 14:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save coorasse/63fc88b58e13a2eae27e27d95e82db05 to your computer and use it in GitHub Desktop.
Save coorasse/63fc88b58e13a2eae27e27d95e82db05 to your computer and use it in GitHub Desktop.
Preloading issue on Rails 6.0
begin
require 'bundler/inline'
rescue LoadError => e
$stderr.puts 'Bundler version 1.10 or later is required. Please update your Bundler'
raise e
end
gemfile(true) do
source 'https://rubygems.org'
# gem 'rails', '~> 5.2'
gem 'rails', '~> 6.0'
gem 'sqlite3'
end
require 'active_record'
require 'minitest/autorun'
require 'logger'
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
ActiveRecord::Base.logger = Logger.new(STDOUT)
# create your tables here
ActiveRecord::Schema.define do
create_table :products, force: true do |t|
t.string :name
end
create_table :users, force: true do |t|
t.string :name
end
create_table :custom_names, force: true do |t|
t.string :text
t.references :user
t.references :product
end
end
class Product < ActiveRecord::Base
has_many :custom_names, inverse_of: :product
end
class CustomName < ActiveRecord::Base
belongs_to :user
belongs_to :product, inverse_of: :custom_names
end
class User < ActiveRecord::Base
end
book, apple, orange = Product.create([{ name: 'book' }, { name: 'apple' }, { name: 'orange' }])
mario, luigi = User.create([{ name: 'Mario' }, { name: 'Luigi' }])
CustomName.create([{ user: mario, product: book, text: 'libro' },
{ user: luigi, product: book, text: 'buch' },
{ user: mario, product: apple, text: 'mela' }])
products = Product.all
ActiveRecord::Associations::Preloader.new.preload(products, :custom_names, CustomName.where(user: mario))
products.each do |product|
puts "product name: #{product.name}. mario names: #{product.custom_names.map { |cn| cn.text }}"
end
@schmijos
Copy link

schmijos commented Mar 18, 2020

(Referencing rails/rails#36638)

A workaround using the public API (replacing https://gist.github.com/coorasse/63fc88b58e13a2eae27e27d95e82db05#file-test-rb-L57-L58):

products = Product.includes(:custom_names).where(custom_names: { user: [mario, nil] })

@NoNonsenseSolutions
Copy link

@schmijos

Your code will not return products which have custom names with other users, but not with mario

With the example above,
If we added an additional CustomName
CustomName.create({user: luigi, product: orange, text: 'abc'})

there will only be two products returned.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment