ConfirmationController中的NoMethodError

时间:2013-06-22 20:03:18

标签: ruby-on-rails ruby ruby-on-rails-3

我一直试图解决以下问题几天。请原谅我,如果这是一个常见的问题,因为我是rails的新手,可能无法在stackoverflow或google中查询正确的问题/关键字。

我正在建立一个系统,用户可以通过电子邮件获得邀请,点击一个独特的链接,转到他/她可以接受或拒绝邀请的页面。我陷入了用户接受或拒绝邀请的部分。

我围绕两个控制器构建它:一个邀请控制器和一个确认控制器。邀请控制器创建一个包含名称,电子邮件和唯一生成的令牌的记录。然后控制器将带有令牌的链接通过电子邮件发送到定义的电子邮件。该链接指向确认控制器,并从邀请中传递唯一令牌。但是,当点击链接并接受邀请时,我收到以下错误:

NoMethodError in ConfirmationController#confirm
undefined method `update_attribute' for nil:NilClass

以下是解决此问题的一些代码:

Confirmation_controller.rb

class ConfirmationController < ApplicationController
    def new
      @confirmation = Invitation.find_by_invite_token(params[:invite_token])
    end

    def confirm
      if @confirmation.update_attribute(:accepted, true) 
         flash[:success] = "Invitation confirmed!"
         redirect_to 'static_pages/home'
      else
         flash[:notice] = "Failed :("
         redirect_to 'static_pages/home'
      end
    end
end

的routes.rb

match '/confirmation/:invite_token', to: 'confirmation#new'
match '/confirmation/:invite_token/confirm', to: 'confirmation#confirm'

应用程序/视图/确认/ new.html.erb

Click here to accept:
<%= link_to "Confirm", :controller => "confirmation", :action => "confirm" %>

3 个答案:

答案 0 :(得分:2)

您还需要使用Invitation方法获取confirm

如果您希望rails在未找到邀请时引发异常

def confirm
  @confirmation = Invitation.find_by_invite_token!(params[:invite_token])
  @confirmation.update_...
end

不会引发任何例外。在下列情况下,您可能需要手动检查条件。

def confirm
  @confirmation = Invitation.find_by_invite_token(params[:invite_token])
  if @confirmation
    @confirmation.update_...
  else
    # do something
  end
end

答案 1 :(得分:0)

您应该在调用confirmation之前找到update_attribute记录,就像您在new操作中所做的那样:

@confirmation = Invitation.find_by_invite_token(params[:invite_token])

或者,在找不到记录时抛出异常并向用户呈现404页面:

@ocnfirmation = Invitation.find_by_invite_token!(params[:invite_token])

答案 2 :(得分:0)

问题是你从未告诉程序@confirmation是什么。你应该做的是先找到它然后运行更新。请注意,这与不同的答案不同,只是想我会投入一些变化。

def confirm
  # You're missing this line below. Basic search for the confirmation.
  # Note too that you will have to pass in the parameter `invite_token` for it to work
  # I'm also assuming invite_token is unique among each invitation 
  confirmation = Invitation.where(invite_token: params[:invite_token])

  # Notice that I'm first checking to see if the confirmation record exists, then doing an update
  if confirmation and confirmation.update_attribute(:accepted, true) 
     flash[:success] = "Invitation confirmed!"
     redirect_to 'static_pages/home'
  else
     flash[:notice] = "Failed :("
     redirect_to 'static_pages/home'
  end
end