Rails 5将错误的参数传递给has_many:通过范围

时间:2016-10-05 17:46:35

标签: ruby ruby-on-rails-5

假设我们有以下(尽管很复杂)设置:

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

因此,实际上,Item有许多CompanyItem个代表Company的{​​{1}},CompanyItem#item_company属于ReplacementItem Item ReplacementItem适用于属于HomeCompany)指定的CompanyItem的{​​{1}}。

非常迂回,但它正是我们所需要的。

现在,正如我们所看到的,在CompanyItem#home_company模型上,ReplacementItem关系使用范围来选择属于与has_one :company_item, through: :home匹配的CompanyItem的特定home {1}}。当我们真正需要匹配给定item_id的项目时,只需执行replacement_item.home.company_items就可以为我们提供所有homes公司项目。调用ReplacementItem方法可以完美地运行,并为我们提供我们想要的内容。

同样,ReplacementItem#company_item模型具有CompanyItem,使用完全相同的范围来获取与给定has_many :replacement_items, through: :homes匹配的替换项。但是,在这种情况下,我们在调用CompanyItem时遇到错误:

CompanyItem#replacement_items

对我来说,这看起来像是一个Rails错误。绝对没有办法将NoMethodError: undefined method `item_id' for #<Company id: 2> /Users/cbankester/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/bundler/gems/rails-bf5876af099f/activemodel/lib/active_model/attribute_methods.rb:434:in `method_missing' bug.rb:59:in `block in <class:CompanyItem>' /Users/cbankester/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/bundler/gems/rails-bf5876af099f/activerecord/lib/active_record/associations/association_scope.rb:161:in `instance_exec' /Users/cbankester/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/bundler/gems/rails-bf5876af099f/activerecord/lib/active_record/associations/association_scope.rb:161:in `eval_scope' /Users/cbankester/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/bundler/gems/rails-bf5876af099f/activerecord/lib/active_record/associations/association_scope.rb:139:in `block in add_constraints' /Users/cbankester/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/bundler/gems/rails-bf5876af099f/activerecord/lib/active_record/associations/association_scope.rb:138:in `each' /Users/cbankester/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/bundler/gems/rails-bf5876af099f/activerecord/lib/active_record/associations/association_scope.rb:138:in `add_constraints' /Users/cbankester/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/bundler/gems/rails-bf5876af099f/activerecord/lib/active_record/associations/association_scope.rb:28:in `scope' /Users/cbankester/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/bundler/gems/rails-bf5876af099f/activerecord/lib/active_record/associations/association_scope.rb:5:in `scope' /Users/cbankester/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/bundler/gems/rails-bf5876af099f/activerecord/lib/active_record/associations/association.rb:97:in `association_scope' /Users/cbankester/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/bundler/gems/rails-bf5876af099f/activerecord/lib/active_record/associations/association.rb:86:in `scope' /Users/cbankester/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/bundler/gems/rails-bf5876af099f/activerecord/lib/active_record/associations/collection_association.rb:327:in `scope' /Users/cbankester/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/bundler/gems/rails-bf5876af099f/activerecord/lib/active_record/associations/collection_proxy.rb:36:in `initialize' /Users/cbankester/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/bundler/gems/rails-bf5876af099f/activerecord/lib/active_record/relation/delegation.rb:101:in `new' /Users/cbankester/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/bundler/gems/rails-bf5876af099f/activerecord/lib/active_record/relation/delegation.rb:101:in `create' /Users/cbankester/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/bundler/gems/rails-bf5876af099f/activerecord/lib/active_record/associations/collection_association.rb:46:in `reader' /Users/cbankester/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/bundler/gems/rails-bf5876af099f/activerecord/lib/active_record/associations/builder/association.rb:111:in `replacement_items' bug.rb:85:in `test_hmt_with_conditions' 对象传递到Company模型上定义的has_many :replacement_items范围。不过,在讨论Rails团队之前,我希望有人在这里看到类似的问题,或者可以在我的代码中指出错误。

请参阅我的要点,了解可运行的失败测试:https://gist.github.com/cmbankester/64ef4eb125bf90dbe0274fab8e5427f1

0 个答案:

没有答案