来源:https://www.gitbook.io/book/rocodev/rails-102
Scope
Scope的作用就是将时常使用或者复杂的ORM语法组合成懒人包,这样下次使用就可以直接拿过来使用。
例子:
class Topic < ActiveRecord::Base
scope :recent, -> { order("create_at DESC") }
end
使用情境:
- 当过于复杂的资料查询
- 当有重复使用的资料查询
使用方式
没有带参数的方式
class Post < ActiveRecord::Base
scope :published, -> { where(published: true) }
end带有参数的方式
class Post < ActiveRecord::Base
scope :created_before, ->(time) { where(“created_at < ?”, time) }
end可以串接在一起,顺序没有影响
class Event < ActiveRecord::Base
scope :published, -> { where(published: true) }
scope :created_before, ->(time) { where(“created_at < ?”, time) }
end
使用方法:Event.published.created_before(Time.now)
includes
当我们在操作关联性资料时,可以使用includes将关联性资料先抓出来,每次要调用资料时就不是去资料库搜寻了,而是从已经调阅出来的资料里搜寻,可以提供效能。
假设Board
has_many Tpoics
class Board < ActiveRecord::Base
def index
@boards = Board.all
end
end
假定我们有10条board,在view里面我们使用
<% @boards.each do |board| %>
<% borad.topics.each do |topic| %>
<%= topic.title %>
<% end %>
<% end %>
这样子的做法有一个很不好的地方那个就是我们需要重复查询数据库10次,增加了渲染时间。
若是加上includes
后会是这样子
class Board < ActiveRecord::Base
def index
@borads = Board.includes(:topics).all
end
end
这时候我们在view里面使用时
- 到数据库把boards的所有topics都提取出来
- 提取出来的topic中找到board_id相对应的topic
这样我们就只需要搜寻一次,直接减少了数据库的负担。
counter_cache
counter_cache 是在做关联性数据库时计算数据量的一个方法。
假如:Board
has_many Topics
,一般我们的写法如下:
@board.topics.count
这种方法就是我们要计算topic的数量时都需要下一个sql指令去计算topic的数量,一样会对性能有影响。
我们可以使用Rails内建的counter_cache的方法,我们只需要Topic model内加上counter_cache: true
class Topic < ActiveRecord::Base
belongs_to :board, counter_cache: true
end
然后在Board的表中新增topics_count字段。我们就可以直接使用@board.topics_count
来代替@board.topics.count
自定义字段:
例如将topics_count
改成count_of_topics
class Topic < ActiveRecord::Base
belongs_to :board, counter_cache: :count_of_topics
end