访问多个表的范围

时间:2017-07-31 22:50:14

标签: ruby-on-rails activerecord

我有以下配置,我正在尝试编写一个范围来给我所有订单,其中order.buying_store.name等于搜索词,或者order.buying_store.company.name等于相同的搜索词。我写的范围正在产生错误:

ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR:  missing FROM-clause entry for table "company"

我的设置:

class Company
  has_many :stores
end 

class Store
  belongs_to :company
end

class Order
  belongs_to :buying_store, class_name: 'Store', foreign_key: 'buying_store_id', required: true 
  belongs_to :selling_store, class_name: 'Store', foreign_key: 'selling_store_id', required: true

  scope :with_buying_counterpart_like, ->(search_term) { joins(:buying_store).where(['buying_store.name = ? OR buying_store.company.name = ?', search_term, search_term]) }

end

我也尝试过:

  scope :with_buying_counterpart_like, ->(search_term) { joins(:buying_store, :company).where(['buying_store.name = ? OR company.name = ?', search_term, search_term]) }

但会产生以下错误:

ActiveRecord::ConfigurationError: Can't join 'Order' to association named 'company'; perhaps you misspelled it?

2 个答案:

答案 0 :(得分:1)

您在范围内使用公司,但您没有加入表公司 尝试类似的东西

class Order
  with_options class_name: 'Store', required: true  do
    belongs_to :buying_store, foreign_key: 'buying_store_id'
    belongs_to :selling_store, foreign_key: 'selling_store_id'
  end

  scope :with_buying_counterpart_like, (lambda do |search_term| 
    joins(buying_store: :company)
      .where('stores.name = :term OR companies.name = :term', term: search_term)
  end)    
end

答案 1 :(得分:1)

  

ActiveRecord :: ConfigurationError:无法将“订单”加入关联   命名为“公司”;也许你拼错了?

你的第二种方法是正确的,但有缺陷。你需要像下面那样

scope :with_buying_counterpart_like, ->(search_term) { joins(buying_store: [:company]).where(['buying_store.name = ? OR company.name = ?', search_term, search_term]) }

也就是说,您需要company 嵌套buying_store,因为OrderComapny之间没有关联

<强>更新

在编写where字符串表示法时,您需要编写完整的表名而不是关联名,所以最后的查询将是

scope :with_buying_counterpart_like, ->(search_term) { joins(buying_store: [:company]).where(['stores.name = ? OR companies.name = ?', search_term, search_term]) }