2

所以,我是一个 Rails 新手,可能遗漏了一些明显的东西,但是当我尝试使用 .includes 急切地加载关联时,为什么我得到一个 NoMethodError 让我有点惊讶。

这是我的代码:

预测控制器.rb

def show
    @forecast = Forecast.find(params[:id])      
    @forecast_projects = Project.includes(:project_type).where("forecast_id =?", params[:id])
end

_project.html.erb(此文件是在 Forecast 操作中呈现的集合部分)

<%= project.project_type.title %>

由于某种原因,这会产生以下错误:

预测中的 NoMethodError#show

显示第 1 行引发的 /path :

nil:NilClass 的未定义方法“标题”

奇怪的是,如果我将forecasts_controller.rb更改为...

def show
    @forecast = Forecast.find(params[:id])      
    @forecast_projects = Project.joins(:project_type).where("forecast_id =?", params[:id])
end

突然间,一切都开始完美运行。有人可以帮我弄清楚我在这里缺少什么(并原谅我缺乏经验)吗?

4

2 回答 2

3

您的代码不起作用,因为有一个(或多个)project没有project_type关联。

joins和之间的最大区别includes

  • joins检索至少有 1 个关联的记录
  • includes检索记录并加载它们的关联(如果存在)

Rails :include 与 :joins

这意味着当你打电话时:

@forecast_projects = Project.includes(:project_type).where("forecast_id =?", params[:id])
# loads all the projects AND their associated project_type if exists
@forecast_projects = Project.joins(:project_type).where("forecast_id =?", params[:id])
# loads all the projects HAVING at least 1 project_type associated

要清楚地看到差异,请尝试以下操作:

Project.includes(:project_type).count # total number of entries in projects table
Project.joins(:project_type).count # number of projects having at least 1 project_type

要解决您的问题,您可以try显示关联的标题(project_type如果存在):

<%= project.project_type.try(:title) %>
# will print the project_type.title if exists, prints nothing if project_type.nil?
<%= project.project_type.try(:title) || 'No ProjectType for this Project' %>
# will print the string if project_type is nil
于 2013-05-22T19:59:33.990 回答
1

您至少有一个项目没有project_type. 当您使用includesrails 选择所有记录并在没有project_type. 当您使用joins它时,它只选择带有 的那些project_type但不包括它们

要解决问题,您最好找到bad记录并将其添加project_type到其中并添加验证以避免将来出现此错误。但是,如果可以有空白项目,project_type那么同时使用joinsincludeslike Project.joins(:project_type).includes(:project_type)

于 2013-05-22T20:29:15.643 回答