ActionView::Template::Error(nil:NilClass 的未定义方法 `each'):

key*_*ons 0 ruby-on-rails heroku

我在本地没有遇到错误,但在 Heroku 上。错误是:

'ActionView::Template::Error(nil:NilClass 的未定义方法 `each')'

“每个”指的是下面我的 User callback.html.erb 视图的 <% for i in @positions %> 行中 @position 中的每个 i:

<% for i in @positions %>
<strong>
<% begin %>
<%= @user.positions.find_by_id(i).title + " at " %>
<% rescue %>
<% end %>

<% begin %>
<%= @user.positions.find_by_id(i).company %>
<% rescue %>
<% end %>
</strong>
Run Code Online (Sandbox Code Playgroud)

这是我的身份验证控制器的相关部分(回调部分)

def callback

...

    @user = current_user

...

    #positions
    for i in 0..(positions.count-1)

      begin
        @company_i = companies[i]['name']
      rescue
      end

      begin
        @title_i = positions[i]['title']
      rescue
      end

      begin
        @industry_i = companies[i]['industry']
      rescue
      end

      begin
        @start_month_i = positions[i]['start-date']['month']
        @start_year_i = positions[i]['start-date']['year']
      rescue
      end

      begin
        @end_month_i = positions[i]['end-date']['month']
        @end_year_i = positions[i]['end-date']['year']
      rescue
      end

      begin
        @li_pos_id_i = positions[i]['id']
      rescue
      end

      if Position.find_by_li_pos_id(@li_pos_id_i).nil?
        @user.positions.build(li_pos_id: @li_pos_id_i, company: @company_i, title: @title_i, 
          industry: @industry_i, start_month: @start_month_i, start_year: @start_year_i, 
          end_month: @end_month_i, end_year: @end_year_i)
      end
    end

    @user.save
    @positions = @user.positions.map(&:id)
end
Run Code Online (Sandbox Code Playgroud)

我认为这与我的 .find_by 方法返回 nil 值有关,但我不确定如何修复它。谢谢!

编辑授权控制器:

positions.each do |position|
      begin
        @li_pos_id = position.id
        @title = position.title
        @company = position.company.name
        @industry = position.company.industry
        @start_month = position.start_date.month
        @start_year = position.start_date.year
        @end_month = position.end_date.month
        @end_year = position.end_date.year
      rescue
      end

      unless Position.find_by_li_pos_id(@li_pos_id)
        current_user.positions.build(li_pos_id: @li_pos_id, title: @title, company: @company, industry: @industry, 
          start_month: @start_month, start_year: @start_year, end_month: @end_month, end_year: @end_year)
      end

      @user.save
      @user.positions.save
    end
Run Code Online (Sandbox Code Playgroud)

tad*_*man 5

您在这里所做的称为“Pokemon 异常处理”,因为您捕获所有异常并将它们扔进垃圾箱。这是一个非常糟糕的养成习惯,如果您与其他开发人员在一个团队中工作,则会导致巨大的挫败感,因为它隐藏了意外错误并使调试变得更加困难,因为在这些部分中您将永远无法获得正确的堆栈跟踪已经被挡住了。

与其盲目地捕捉异常,您应该在适用的情况下捕捉特定的、预期的异常,并且只在可能引发它们的地方捕捉。您还应该尽一切努力避免首先生成它们。

这方面的一个例子是:

<% @position_ids.present? and @position_ids.each do |position_id| %>
Run Code Online (Sandbox Code Playgroud)

调用您的位置变量i也是一种非常糟糕的风格,因为这种名称通常是为增量或索引保留的,仅此而已。使用稍长但更具描述性的名称有很大帮助。

您还for x in y为循环使用了这种非常奇特的符号,其中 Ruby 鼓励使用更简洁的y.each do |x|版本。

此外,测试nil?而不仅仅是测试对象本身几乎总是多余的,可以消除。在nil?当你想分清测试才有意义false以及nil它们在Ruby中仅有的两个非真值。在这种情况下,简单unless (x)if (x.nil?).

至于为什么你没有得到任何东西@positions,这可能是因为callback例程首先没有运行。从表面上看,除非那里有return某个地方,否则必须在例程结束时分配该值。