`
hideto
  • 浏览: 2690643 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Rails宝典之第三式: 通过关联做查询

    博客分类:
  • Ruby
阅读更多
Rails宝典之第三式: 通过关联做查询

我们来看一个has_many关联的例子:
class Project < ActiveRecord::Base
  has_many :tasks
end

class Task < ActiveRecord::Base
  belongs_to :project
end

class ProjectsController < ApplicationController
  def show
    @project = Project.find(params[:id])
    @tasks = Task.find_all_by_project_id_and_complete(@project.id, false)
  end
end

上面的Project类和Task类是一对多的关系,ProjctsController的show方法根据:id参数查询得到@project对象
这时,我们可以使用find_all_by_project_id_and_complete动态方法来查询belongs_to @project对象的@tasks
但是有更简洁的方法:
class ProjectsController < ApplicationController
  def show
    @project = Project.find(params[:id])
    @tasks = @project.tasks.find_all_by_complete(false)
  end
end


为什么可以在@project.tasks上调用find_all_by_complete这种ActiveRecord Model才有的动态查询方法呢?
让我们来回顾一下ActiveRecord的关联: Rails源码研究之ActiveRecord:二,Associations

我们看到,associations.rb定义了has_many、belongs_to等这些用来表示Model之间关联的方法 -- 也构成了Rails的数据库关联的DSL
然后,利用反射得到has_many、belongs_to等方法后面的参数所代表的Model类
最后,对这些Model类的操作被代理到具体的HasManyAssociation、BelongsToAssociation等类

HasManyAssociation、BelongsToAssociation等类里面定义了find、build等方法
并且,不难发现,HasManyAssociation、BelongsToAssociation等类都继承于AssociationCollection这个父类
看看AssociationCollection类,里面定义了<<、delete_all、sum、delete、create等方法,比如:
def create(attrs = {})
  record = @reflection.klass.send(:with_scope, :create => construct_scope[:create]) { @reflection.klass.create(attr) }
  @target ||= [] unless loaded?
  @target << record
  record
end

这里不难发现,create方法实际利用反射上调用了Model(如Task)的create方法,并把创建的对象加入到@target中(如@project.tasks)

好,现在来看AssociationCollection类的一个protected方法:
def method_missing(method, *args, &block)
  if @target.respond_to?(method) || (!@reflection.klass.respond_to?(method) && Class.respond_to?(method))
    super
  else
    @reflection.klass.send(:with_scope, construct_scope) { @reflection.klass.send(method, *args, &block) }
  end
end

现在明白为什么在@project.tasks上可以调用create、<<、build、find、find_all_by_complete等方法了吧!

@target是我们的@project.tasks,它是一个belongs_to @project的Task对象Array
而@reflection.klass为Task

当我们调用@project.tasks.find_all_by_complete时:
如果@project.tasks定义了find_all_by_complete方法,或者Task类没有定义find_all_by_complete方法并且
Class(这里的Class是指Associations模块下的Class)定义了find_all_by_complete方法,则调用父类的同名方法;
否则,调用Task类的同名方法。

这里find_all_by_complete显然符合后面的情况,即Task类定义了该方法(见Rails宝典之第二式: 动态find_by方法)

回到这个例子,除了在@project.tasks基础上调用基本的ActiveRecord Model层面的方法外,我们还可以通过指定find_sql参数来约束
想要得到的结果集:
  has_many :tasks, :finder_sql => %q/
  select * from tasks where project_id = #{id} and complete == 0
  /
分享到:
评论
1 楼 jonlove 2007-07-26  
太棒了

相关推荐

    Rails的精简版本Rails::API.zip

    Rails::API 是 Rails 的精简版本,针对不需要使用完整 Rails 功能的开发者。 Rails::API 移除了 ActionView 和其他一些渲染功能,不关心Web前端的开发者可更容易、快速地开发应用程序,因此运行速度比正常的 Rails ...

    Rails上的API:使用Rails构建REST APIAPIs on Rails: Building REST APIs with Rails

    在本篇内容中,我们将深入探讨如何利用Ruby on Rails(简称Rails)这一强大的Web应用程序框架来构建可伸缩且易于维护的RESTful API。Rails以其简洁优雅的语法、高效的开发速度以及良好的社区支持而闻名,这使得它...

    Rails中应用Ext.tree:以中国的省市地区三级联动选择为例

    在Ruby on Rails(Rails)框架中,开发人员经常需要实现各种...通过学习这个实例,开发者可以掌握如何在Rails应用中集成第三方库,处理层级数据,以及创建交互式的前端界面。这对于提升Web应用的用户体验非常有价值。

    rails查询学习笔记

    在Rails中,数据库查询主要通过ActiveRecord来实现,这是一个强大的ORM(对象关系映射)工具,能够将数据库表与Ruby类关联,简化数据操作。 描述中虽然没有具体信息,但我们可以推测这可能是一篇关于Rails中查询...

    Ruby on Rails Guides v2 - Ruby on Rails 4.2.5

    ### Ruby on Rails Guides v2 - Ruby on Rails 4.2.5 #### 一、重要概念及基础假设 - **重要概念**:本指南旨在帮助读者深入理解Ruby on Rails(以下简称Rails)4.2.5版本的核心功能与最佳实践。 - **基础假设**:...

    Advanced Rails

    3. **ActiveRecord高级用法**:ActiveRecord是Rails的ORM(对象关系映射)工具,用于数据库操作。书中会涵盖关联(如has_many, belongs_to, has_one, through)、查询API(如scopes, joins, group, having)以及事务...

    Rails 101S

    ### Rails 101S: 初学者必备的Ruby on Rails 宝典 #### Introduction: 深入了解Ruby on Rails 《Rails 101S》是一本为Ruby on Rails初学者准备的手册,旨在帮助新手快速入门并掌握基本的开发技能。本手册将从最...

    Ruby on Rails入门例子

    Ruby on Rails,简称Rails,是一种基于Ruby语言的开源Web应用程序框架,它遵循MVC(Model-View-Controller)架构模式,旨在使Web开发过程更加高效、简洁。本篇将通过一个入门实例,深入探讨Rails的基本概念和核心...

    Rails 101 入门电子书

    ### Rails 101 入门电子书知识点详解 #### 一、简介 ...通过以上内容的学习,初学者可以全面掌握Ruby on Rails的基础知识,包括环境搭建、基本操作、高级特性等,为后续更深入的学习打下坚实的基础。

    Rails3的ActiveRecord 查询API.doc

    Rails 3.1 及以后版本的 ActiveRecord 查询API发生了重大变化,主要目的是为了提供更清晰、更可维护的代码,并且提高性能。在 Rails 2.x 中,许多使用哈希参数的查询方法如 `:conditions`, `:include`, `:joins` 等...

    Rails相关电子书汇总

    11. **Rails Console**:提供了一个交互式的Ruby环境,便于开发者调试和实验代码。 12. **Rails API模式**:Rails 4引入了API模式,使得构建RESTful JSON接口变得更加简单。 13. **Webpacker和Webpack**:Rails ...

    应用Rails进行敏捷Web开发中文第三版

    《应用Rails进行敏捷Web开发》中文第三版是针对Ruby on Rails框架的一本详尽指南,主要聚焦于Rails 2.2.2版本。Ruby on Rails(简称Rails)是一款基于Ruby编程语言的开源Web应用程序框架,它遵循“Don't Repeat ...

    Ruby on Rails 指南 v5.0.1 中文版

    - **前提条件**:为了能够顺利地开始Rails的学习之旅,读者需要具备一定的Ruby语言基础,并且对Web开发有一定的了解。 - **Rails是什么?**:Rails是一种用于开发服务器端应用程序的模型-视图-控制器(MVC)框架,它...

    Agile Web Development with Rails 4th edition(敏捷Web开发与Rails:程序指南 第四版)

    《敏捷Web开发与Rails:程序指南 第四版》是一本深度探讨使用Ruby on Rails框架进行敏捷Web应用开发的专业书籍。本书旨在帮助开发者充分利用Rails 4的特性,提高开发效率,实现快速迭代和高质量的代码编写。 Rails是...

    Ruby on Rails入门经典代码

    Ruby on Rails,简称Rails,是基于Ruby语言的一个开源Web应用程序框架,它遵循MVC(Model-View-Controller)架构模式,旨在使Web开发过程更加高效、简洁。本压缩包中的"Ruby on Rails入门经典代码"提供了新手学习...

    rails敏捷开发,我的成功之路

    **标题与描述**:本书通过一个名为Depot的应用程序开发案例,详细介绍了如何使用Rails进行增量式开发,逐步完善功能并优化用户体验。 **详细说明**:Depot是一个在线商店应用,通过多个迭代步骤逐步构建和完善功能...

    Rails 3 in Action

    《Rails 3 in Action》是2011年由Ryan Bigg撰写的一本关于Ruby on Rails框架的权威指南,专门针对当时最新的Rails 3.1版本进行了深入解析。这本书旨在帮助开发者充分利用Rails 3.1的强大功能,提升Web应用开发的效率...

    rails有用的命令

    - `$ rails c` 或 `$ rails console`:启动Rails控制台,进行交互式编程。 - `$ rails server -p 3001`:在端口3001启动服务器。 - `$ rake doc:rails`:生成Rails API文档。 - `$ rails dbconsole`:打开数据库...

Global site tag (gtag.js) - Google Analytics