Ruby on rails 在联接表时,rails在从联接表访问字段时仍会发出附加请求

Ruby on rails 在联接表时,rails在从联接表访问字段时仍会发出附加请求,ruby-on-rails,ruby,Ruby On Rails,Ruby,我有公司表和城市表;这家公司属于伦敦金融城 我的db架构的一部分是: create_table "companies", force: true do |t| t.string "title", default: "", null: false t.string "address", default: "", null: false t.integer "city_id" t.datetime "created_at" t.d

我有公司表和城市表;这家公司属于伦敦金融城

我的db架构的一部分是:

  create_table "companies", force: true do |t|
    t.string   "title",      default: "", null: false
    t.string   "address",    default: "", null: false
    t.integer  "city_id"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "cities", force: true do |t|
    t.string   "title",      default: "", null: false
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "test"
  end
公司的一部分
型号:

class Company < ActiveRecord::Base
  belongs_to    :city,   :inverse_of => :companies
  # ....
end
class City < ActiveRecord::Base
  has_many      :companies, :inverse_of => :city
  # ....
end
当我获取公司名称,然后获取其城市名称时,Rails显然会发出额外的请求来获取城市名称:

$ rails console
2.1.5 :001 > Company.first.city.title
  Company Load (0.2ms)  SELECT  "companies".* FROM "companies"   ORDER BY "companies"."id" ASC LIMIT 1
  City Load (0.3ms)  SELECT  "cities".* FROM "cities"  WHERE "cities"."id" = ? LIMIT 1  [["id", 2]]
 => "My city 1"
我很确定我可以通过加入
cities
表来避免这种情况。但我错了:

2.1.5 :002 > Company.joins(:city).first.city.title
  Company Load (0.3ms)  SELECT  "companies".* FROM "companies" INNER JOIN "cities" ON "cities"."id" = "companies"."city_id"  ORDER BY "companies"."id" ASC LIMIT 1
  City Load (0.1ms)  SELECT  "cities".* FROM "cities"  WHERE "cities"."id" = ? LIMIT 1      [["id", 2]]
 => "My city 1" 
所以,
cities
表被加入,但Rails仍然对
cities
执行额外的请求

为什么会这样,以及如何避免对
cities
表的额外请求


当我只有一条记录时(如上面的例子中),这不会造成太大的伤害,但是如果我想获得
公司.加入(:city).all
,然后获得每个公司的city,那么从
城市
每次获取的额外开销是非常重要。

尝试
包括
公司.包括(:city).first.city.title

没有帮助。它甚至不加入表,当然有两个查询。输出:其工作方式是在一个查询中选择所有公司,然后在另一个查询中选择公司引用的所有城市(注意,第二个查询现在是
id in(2)
,而不是
id=2
——这意味着所有公司都有id为2的城市)。如果你真的,真的想强制一个查询,这里有
references
method-
Company.includes(:city)。references(:city)
应该可以。哦,太好了!我已经在
Company.includes(:city).all.each{c|c | put c.city.title}
上测试了它,它的工作原理如您所解释的。非常感谢。顺便说一句,它也可以像这样作为单个查询:
Company.joins(:city).includes(:city)
,但是在您解释之后,它就不那么重要了。