Rails3的一大亮点是 AR的query 接口:
1. 程序员最爱用就是它的及接方式
Uers.where().where().order()....
2. 还有LasyLoad可以增加灵活性
=================
但这个Relation还是很让人迷惑的。尤其是一上来:
delegate :find, :first, :last, :all, :destroy, :destroy_all, :exists?, :delete, :delete_all, :update, :update_all, :to => :scoped
delegate :find_each, :find_in_batches, :to => :scoped
delegate :select, :group, :order, :reorder, :except, :limit, :offset, :joins, :where, :preload, :eager_load, :includes, :from, :lock, :readonly, :having, :create_with, :to => :scoped
delegate :count, :average, :minimum, :maximum, :sum, :calculate, :to => :scoped
这么生猛的操作都被delegate到:scoped上。不熟悉rails的手法,更是不知所云。
NamedScope scoped
知道调用 relation,new出一个relation实例就行了
@relation ||= Relation.new(self, arel_table)
这样,所以的操作都被delegate到relation实例上。
===================
relation查询接口都在relation目录下的query_methods.rb文件中
像order这种简单谓词
def order(*args)
relation = clone
relation.order_values += args.flatten unless args.blank?
relation
end
就直接记到实例变量,后面产生sql用。
像where就复杂一些
def where(opts, *rest)
relation = clone
relation.where_values += build_where(opts, rest) unless opts.blank?
relation
end
build_where又调用了predicate_builder来builderwhere_value。在这里也是用了arel
================================
这些query动作完后,用all, first, last来向db fetch东西,最重要的东西来了!
调用relation to_a方法
def to_a
return @records if loaded?
@records = eager_loading? ? find_with_associations : @klass.find_by_sql(arel.to_sql)
...
@records
end
让are生成to_sql,还用是AR的base中的connection用查询数据回来
那么arel是如何生成的呢
def build_arel
arel = table
arel = build_joins(arel, @joins_values) unless @joins_values.empty?
arel = collapse_wheres(arel, (@where_values - ['']).uniq)
arel = arel.having(*@having_values.uniq.reject{|h| h.blank?}) unless @having_values.empty?
arel = arel.take(connection.sanitize_limit(@limit_value)) if @limit_value
arel = arel.skip(@offset_value) if @offset_value
arel = arel.group(*@group_values.uniq.reject{|g| g.blank?}) unless @group_values.empty?
arel = arel.order(*@order_values.uniq.reject{|o| o.blank?}) unless @order_values.empty?
arel = build_select(arel, @select_values.uniq)
arel = arel.from(@from_value) if @from_value
arel = arel.lock(@lock_value) if @lock_value
arel
end
arel本身可以不断及连。
========================
到时,真相大白。
relation是一个逻辑体,可以不断及联。are是一个sql factory。 AR:base是实体,有数据库连接。
那么要hook住AR的query,只要hook在relation的to_a方法上。
========================
设计上可以参考是:
1. 及联,类似decorator模式
2. base, relation, arel这种实体,逻辑体,工厂互相协同,松耦合,可扩展
分享到:
相关推荐
但在Rails 3中,`Article.all`返回的是一个`ActiveRecord::Relation`对象,它并不会立即执行查询,而是在真正需要数据时才执行,这就是所谓的懒加载。这种机制可以避免不必要的数据库操作,提高应用性能。 例如,...
针对Rails 4应用程序的ActiveRecord::Relation#in_batches实验性ActiveRecord::Relation#in_batches移植。安装将此行添加到您的Gemfile中。 gem "activerecord-in_batches", git: "git://github....
例如,`CollectionDecorator`可以包装一个`ActiveRecord::Relation`,并提供额外的方法来处理集合级别的逻辑。 Draper还支持继承和组合,这意味着你可以创建通用的装饰器,然后在特定的场景中进行扩展或嵌套。此外...
剥夺 这个宝石很珍贵,请使用{active_record-acts_as}( ),它是此宝石的完整重构。 ActsAsRelation 该gem帮助您为ActiveRecord模型实现多表继承(MTI)方法。... 如果您使用的是Rails 3,则必须在Gemfi
委托给ActiveRecord :: Relation,并在两者之间链接ActiveRecord条件 扩展ActiveRecord :: Relation 用法 定义查询对象 class ArtistQuery < BaseQuery # defines the default model on which queries will be ...
1.rails new blog --skip-bundle //创建项目 2.cd blog //进入项目根目录 3.subl . //打开项目开发环境 4.Bundle install //安装gem包环境 ... => #<ActiveRecord::Relation []> 2.4.1 :006 > Post
向 ActiveRecord (Rails) 添加支持。 它添加了.with查询方法,使构建和链接复杂的 CTE 查询变得非常容易。 让我们用简单的例子来解释它。 Post . with ( posts_with_comments : Post . where ( "comments_count...
从控制器到视图传递模型或模型集合或ActiveRecord :: Relation的实例 用模型渲染局部:object显式或隐式使用:collection或:object或:locals ) 获取已装饰的Active Record模型对象的关联 装饰器模块在模型的上下文...
关于这个程序 这是一个仅用于练习目的的小应用程序。... 确保您的解决方案返回ActiveRecord::Relation对象,而不是Array 。 这样,您可以链接示波器,并确保通过Kaminari或will_paginate分页能够按预期进行。 尝试通
查询对象需要ActiveRecord::Relation或ActiveRecord::Base作为构造函数参数 可以使用queries宏定义默认关系(请参见上文) 查询对象必须实现返回ActiveRecord::Relation #query方法 查询对象使用
从控制器到视图传递模型或模型集合或ActiveRecord :: Relation的实例 用模型渲染局部:object显式或隐式使用:collection或:object或:locals ) 获取已装饰的Active Record模型对象的关联 装饰器模块在模型的上下文...
该gem将atomic_first_or_create添加到ActiveRecord :: Relation,它与唯一性约束一起提供正确的行为。 安装 将此行添加到您的应用程序的Gemfile中: gem 'atomic_first_or_create' 然后执行: $ bundle 或将其...
神成 基于范围和引擎的,干净,功能强大,可自定义和复杂的分页器,适用于...Kaminari支持多个ORM(ActiveRecord,DataMapper,Mongoid,MongoMapper),多个Web框架(Rails,Sinatra,Grape)和多个模板引擎(ERB,