Ruby on rails 在联接表时,rails在从联接表访问字段时仍会发出附加请求
我有公司表和城市表;这家公司属于伦敦金融城 我的db架构的一部分是: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
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)
,但是在您解释之后,它就不那么重要了。