私有方法“update_without_password”调用了 nil:NilClass

private method `update_without_password' called for nil:NilClass

我正在遵循 this tutorial on cancancan authentication, and specifically wanting admins to update users without needing a password. I've also seen this 建议,但不确定如何将其应用到我自己的代码中。当我点击更新时,它说 'NoMethodError in UsersController#update' 私有方法“update_without_password”调用了 nil:NilClass

我的应用程序 returns 所有用户的参数,所以我不明白这里发生了什么。 rails 仍然很新 - 如果您需要任何进一步的信息,请告诉我。提前致谢!

用户控制器

class UsersController < ApplicationController
before_filter :authenticate_user!



 def update
  if user_params[:password].blank?
    user_params.delete(:password)
    user_params.delete(:password_confirmation)
  end


  successfully_updated = if needs_password?(@user, user_params)
                           @user.update(user_params)
                         else
                           @user.update_without_password(user_params)
                         end
 respond_to do |format|
    if successfully_updated
      format.html { redirect_to @user, notice: 'User was successfully updated.' }
      format.json { head :no_content }
    else
      format.html { render action: 'edit' }
      format.json { render json: @user.errors, status: :unprocessable_entity }
    end
  end


  rescue ActiveRecord::RecordNotFound
    respond_to_not_found(:js, :xml, :html)
  end


private
def needs_password?(user, params)
  params[:password].present?
end

def update_without_password(user_params)
  user.update_without_password(user_params)
end



def user_params
        params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation, :name, :role_id, :accepted)
end

编辑表格

<h3><%= @user == @current_user ? "Your Account Settings" : "Edit User" %></h3>

<%= form_for(@user, :html => { :method => :put }) do |f| %>
 <p><%= f.label :first_name %></p>
 <p><%= f.text_field :first_name %></p>

 <p><%= f.label :last_name %></p>
 <p><%= f.text_field :last_name %></p>

 <p><%= f.label :email %></p>
 <p><%= f.text_field :email %></p>
  <% if can? :read, Role %>
 <%= collection_select(:user, :role_id, Role.all, :id, :name, {prompt: true}) %>
  <% end %>
 <p><%= f.submit "Update" %></p>
<% end %>

我在这里错过了什么?请让我知道是否应该提供其他任何东西。谢谢!!

在我看来您看到了那个错误,因为 @user 没有在 update 方法中实例化。您需要将 @user 设置为 User 模型的一个实例。没有看到你的完整应用程序,我不能确定,但​​你应该可以访问参数哈希中的 :id,允许你设置 @user 做这样的事情:

@user = User.find(params[:id])

由于您正在深入研究 CanCan,我强烈建议您通读 their documentation 以了解 load_and_authorize_resource 方法。你在你的控制器中使用它来 D.R.Y。加载您要使用的对象或集合的重复代码。它使用您所在控制器的名称和 params 中的 :id 值来自动实例化您的资源。因此,在您的 showeditupdate 方法中,它将在您的 UsersControllerindex 中实例化单个 @user 对象] 方法,它将实例化集合 @users.

FWIW,您可能想知道为什么在 if needs_password?(@user, user_params) 行中看不到 NoMethodError。即使 @user 在那里使用,如果您查看 needs_password? 方法的定义,它需要一个 user 参数,但实际上并没有使用它,所以它不会抱怨关于 @user 在被调用时为 nil 的事实。但是,在这一行 @user.update_without_password(user_params) 中,您直接将 update_without_password method/message 发送到 @user 变量,即 nil.

希望对您有所帮助!