【问题标题】:Calling a class method through an object instance通过对象实例调用类方法
【发布时间】:2015-01-13 22:43:07
【问题描述】:

Railscasts #4 使用此示例代码:

class Task < ActiveRecord::Base
  belongs_to :project

  def self.find_incomplete
    find_all_by_complete(:false, :order => "created_at DESC")
  end
end

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

使用@project.tasks.find_incomplete,仅查找属于该特定Project 实例的不完整订单。

我希望该调用等同于Task.find_incomplete,但事实并非如此。怎么可能? Rails(或 Ruby)现在如何在 Project 实例中为那些特定的 Tasks 调用该方法?

【问题讨论】:

  • ActiveRecord 自动为您完成。
  • @ptd,你能解释一下它是如何在幕后工作的吗?
  • 最好的方法是查看代码。通过查看 ActiveRecord 之类的东西,您会发现更多关于 ruby​​ 的描述能力的信息。

标签: ruby-on-rails ruby railscasts class-method


【解决方案1】:

这是因为 ActiveRecord 关系的范围被合并了。并不是说find_incomplete 在单个任务实例上运行。

@project.tasks 为该项目实例创建任务的 ActiveRecord 范围,然后在调用 find_incomplete 方法时该范围仍然有效。

在此处查看文档:http://guides.rubyonrails.org/active_record_querying.html#scopes

您的 find_incomplete 方法的工作方式与文档中的 self.published 示例相同。

想想将要运行的底层 SQL 查询:

@project.tasks 会创建一个 where 条件,例如 SELECT * FROM projects WHERE project_id = &lt;project_id&gt;

find_all_by_complete 然后在and 条件中合并complete = 0


我认为另一个可能有帮助的难题是@project.tasks 不仅仅是Task 对象的简单数组数组,尽管如果您在Rails 控制台中键入project.tasks,它将被转换为这样的对象. project.tasks 实际上是一个 Active Record 关系对象(或者更准确地说是一个代理) 这有很多原因和好处,但主要的两个是它允许链接,并且它允许底层查询仅在需要时按需运行。

关系有一系列关于如何委托方法调用的规则,其中之一是在关联对象的类上调用类方法。 (关系知道它是与Tasks 的关系)

所以当你写 tasks.find_incomplete 仍然等于 Task.find_incomplete 时你是正确的,除了当通过 project.tasks 调用 find_incomplete 时,缩小到 project_id 的范围已经生效。

【讨论】:

  • 来自 C#,让我大吃一惊的是 foo_instance.class_method 不等于 Foo.class_method。我仍然很困惑。如果@project.tasks.find_incomplete不等于Task.find_incomplete,它等于什么?
  • 经过您的编辑,我想我明白了。发生的事情是Task.find_incomplete 产生complete = false 的约束,并返回不完整的任务,然后添加项目的范围,类似于project_id = [ID]。最后tasks.find_incomplete 仍然等于Task.find_incomplete。我说的对吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多