• 理解ruby on rails中的ActiveRecord::Relation


    ActiveRecord::Relation是rails3中添加的。rails2中的finders, named_scope, with_scope 等用法,在rails3统一为一种Relation用法。

    以下是返回ActiveRecord::Relation的方法:

    bind
    create_with
    distinct
    eager_load
    extending
    from
    group
    having
    includes
    joins
    limit
    lock
    none
    offset
    order
    preload
    readonly
    references
    reorder
    reverse_order
    select
    uniq
    where

     

    主要有以下优势:
    1,惰性加载( Lazy Loading)
    数据库并没有执行查询的动作,只有当真正使用这些数据的时候才会去查询数据库。
    2,可以链式操作
    Uers.where().where().order()....

    一,实验验证惰性加载:
    假设数据库中有一个posts表,表中有两个字段,id和title。
    现在表中只有一条数据,id=1, title = old_name。
    rails console
    进入rails的控制台

    p1 = Post.all
    p2 = Post.order(:id)
    p1.class #=> Array
    p2.class #=> ActiveRecord::Relation

    然后等待一会儿,去数据库中,将"old_name"改为"new_name"。这样的话,因为Post.all是立即加载数据,Post.order(:id)是惰性加载数据,所以改了 

    title之后,p1和p2的值应该是不相同的。

    p1[0]
    
    => #<Post id: 1, title: "old_name", created_at: "2014-05-08 00:45:27", updated_at: "2014-05-08 00:45:27">
    
    p2[0]
    => #<Post id: 1, title: "old_name", created_at: "2014-05-08 00:45:27", updated_at: "2014-05-08 00:45:27">

    发现p1和p2的结果是相同的,Post.order(:id)并没有惰性加载数据,为什么呢?

    原因是在rails的控制台中,会打印出语句的返回结果,也就使用了这些数据,所以这么修改p1和p2两行为:

    p1 = Post.all;nil
    p2 = Post.order(:id);nil

    这样重新执行上边的流程,结果如下:

    p1[0]
    
    => #<Post id: 1, title: "old_name", created_at: "2014-05-08 00:45:27", updated_at: "2014-05-08 00:45:27">
    
    p2[0]
    => #<Post id: 1, title: "new_name", created_at: "2014-05-08 00:45:27", updated_at: "2014-05-08 00:45:27">

    实验验证链式操作:
    操作Relation实例的时候,会查询数据库。进入 activerecord-3.2.13libactive_record elation.rb,找到inspect方法的定义:

    def inspect
       to_a.inspect
    end


    可以看出,调用先将Relation实例转换成数据,然后再将其inspect。

    p2.inspoect
    => "[#<Post id: 1, title: "new_name", created_at: "2014-05-08 00:45:27", updated_at: "2014-05-08 00:45:27">]"

    将inspect方法注释掉,然后看Relation实例中的内容

    "#<ActiveRecord::Relation:0x463cbf0
    @table=#<Arel::Table:0x4626e88 @name="posts",
    @engine=Post(id: integer, title: string, body: text, created_at: datetime, updated_at: datetime),
    @columns=nil,
    @aliases=[],
    @table_alias=nil,
    @primary_key=nil>,
    @klass=Post(id: integer, title: string, body: text, created_at: datetime, updated_at: datetime),
    @implicit_readonly=nil,
    .......
    @group_values=[],
    @order_values=[:id],
    @joins_values=[],
    @where_values=[],
    @having_values=[],
    .......
    @records=[]>"

    可以看出Relation对象中根本就没有存储数据库中的内容,因为使用了order(:id)方法,所以@order_values=[:id]存储了查询信息。
    对以Post.where("id = 1").order(:id),相应的Relation实例中值为:
    @order_values=[:id],
    @where_values=["id = 1"]

    每一次链式操作都会在Relation中添加对应的查询条件,在使用的时候才去生成SQL语句,查询数据库。

    总结:

    知道了ActiveRecord::Relation的内部组织结构就非常好理解惰性加载和链式操作了,Relation让数据库操作更加优雅!

  • 相关阅读:
    Pytorch对比clone、detach以及copy_等张量复制操作【转】
    最简单的appium程序
    无线连接adb
    adb命令
    appium环境搭建
    fiddler修改请求以及返回,mock返回
    request库上传文件
    jmeter关于cookie提取问题
    cookie的操作
    下拉框元素定位
  • 原文地址:https://www.cnblogs.com/fanxiaopeng/p/3716671.html
Copyright © 2020-2023  润新知