繁体   English   中英

理解Rails中与ActiveRecord的关系

[英]Understanding Relational with ActiveRecord in Rails

我理解SQL我理解数据库方法我理解Rails我不懂ActiveRecord关系

我有三个模型(简化),我用rails g模型创建,然后执行rake db:使用mysql db进行迁移。

Calendar
id: number
name: string

Event
id: number
title: string

Event_Tag
id: number
event_id
key: string
value: string

我如何对所有事件执行查询并检索每个事件的所有event_tags,以便我可以用最少的查询构建JSON模型?

Event
id: number
title: string
tags: [
    <key>:<value>,
    <key>:<value>,
    <key>:<value>,
]

我试过这个:

events = Event.includes(:event_tag).where("events.calendar_id" => params[:calendar_id])

我所见,避免了N + 1查询问题。 它执行2个查询。

Event Load (47.1ms)  SELECT `events`.* FROM `events`  WHERE `events`.`calendar_id` = 1

EventTag Load (46.3ms)  SELECT `event_tags`.* FROM `event_tags`  WHERE `event_tags`.`event_id` IN (1) 

但是,当我检查一个事件

eventHash = events[0]

我收到

#<ActiveRecord::Relation [#<Event id: 1, title: "Test", calendar_id: 1, created_at: nil, updated_at: nil>]>

ActiveRecord的

虽然我不知道ActiveRecord的幕后工作,但我知道这就是所谓的ORM(对象相关映射)系统 (SQL框架)

这意味着它为您提供了一系列调用方法,然后将其转换为相关的SQL查询( joins等)


协会

ActiveRecord关联基本上是美化的join语句 - 每次调用一个对象,然后引用它的关联数据,你基本上会调用两个查询来ping两个单独的数据表。

AR的工作方式是使用foreign_key

我认为使用Event模型定义的关联可以最好地解决问题:

#app/models/event.rb
Class Event < ActiveRecord::Base
    has_many :tags, class_name: "EventTag"
end
#app/models/event_tag.rb
Class EventTag < ActiveRecord::Base
    belongs_to :event
end

这将允许您调用以下内容:

@event = Event.find params[:id]
@event.tags.each do |tag|
   tag.name
   tag.value
end

如果这有帮助,如果你发表评论,我会看到有关帮助将tags组合成JSON哈希的方法,虽然我不确定你要用的是什么

Rails eager中的includes方法将关系加载到内存中以便更快地访问,因此应用程序不会执行所有N + 1查询。

因此,即使在检查代码时没有显示关系,如果通过关系(例如event.event_tag.key )访问它,应用程序也不会执行其他查询,因为数据已经存在于内存中。

这是一篇非常好的文章,解释了Rails中的热切加载(讨论includes和其他有用的方法eager_loadpreload以及它们如何相关): httpeager_load

至于构建JSON对象,它实际上取决于你如何处理它。 我想最常见的库(例如jbuilder或active_model_serializers)会处理关系查询。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM