Skip to content

Instantly share code, notes, and snippets.

@cmbankester
Last active October 5, 2016 17:44
Show Gist options
  • Save cmbankester/64ef4eb125bf90dbe0274fab8e5427f1 to your computer and use it in GitHub Desktop.
Save cmbankester/64ef4eb125bf90dbe0274fab8e5427f1 to your computer and use it in GitHub Desktop.
Ruby file showing a potential bug with using scoped+argumented has_many :through in Rails 5
unless File.exist?('Gemfile')
File.write('Gemfile', <<-GEMFILE)
source 'https://rubygems.org'
gem 'rack', github: 'rack/rack'
gem 'rails', github: 'rails/rails'
gem 'sqlite3'
GEMFILE
system 'bundle'
end
require 'bundler'
Bundler.setup(:default)
require 'active_record'
require 'minitest/autorun'
require 'logger'
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Schema.define do
create_table :companies
create_table :items
create_table :homes do |t|
t.integer :company_id
end
create_table :company_items do |t|
t.integer :item_id
t.integer :item_company_id
t.integer :home_company_id
end
create_table :replacement_items do |t|
t.integer :item_id
t.integer :home_id
end
end
class Company < ActiveRecord::Base
has_many :homes, inverse_of: :company
has_many :item_company_items, class_name: 'CompanyItem', inverse_of: :item_company, foreign_key: :item_company_id
has_many :home_company_items, class_name: 'CompanyItem', inverse_of: :home_company, foreign_key: :home_company_id
has_many :replacement_items, through: :item_company_items, source: :replacement_items, inverse_of: :responsible_company
end
class Home < ActiveRecord::Base
belongs_to :company, inverse_of: :homes
has_many :company_items, through: :company, source: :home_company_items, inverse_of: :homes
has_many :replacement_items, inverse_of: :home
end
class CompanyItem < ActiveRecord::Base
belongs_to :item, inverse_of: :company_items
belongs_to :item_company, class_name: 'Company', inverse_of: :item_company_items, foreign_key: :item_company_id
belongs_to :home_company, class_name: 'Company', inverse_of: :home_company_items, foreign_key: :home_company_id
has_many :homes, through: :home_company, source: :homes, inverse_of: :company_items
has_many :replacement_items, -> company_item { where item_id: company_item.item_id },
through: :homes, source: :replacement_items, inverse_of: :company_item
end
class Item < ActiveRecord::Base
has_many :replacement_items, inverse_of: :item
has_many :company_items, inverse_of: :item
end
class ReplacementItem < ActiveRecord::Base
belongs_to :item, inverse_of: :replacement_items
belongs_to :home, inverse_of: :replacement_items
has_one :company_item, -> rep { where item_id: rep.item_id }, through: :home, source: :company_items, inverse_of: :replacement_items
has_one :responsible_company, through: :company_item, source: :item_company, inverse_of: :replacement_items
end
class Test < Minitest::Test
def test_hmt_with_conditions
home_company = Company.create!
item_company = Company.create!
home = home_company.homes.create!
item = Item.create!
company_item = item.company_items.create!(item_company: item_company, home_company: home_company)
replacement_item = home.replacement_items.create!(item: item)
item_company.reload
item_company.replacement_items.count
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment