Devise注册报错:undefined method `fetch_value' for nil:NilClass
undefined method 'fetch_value' for nil:NilClass错误 我一直用Devise做身份认证,它简单还够灵活。但今天注册新用户的时候毫无征兆地出了错——我既没跑bundle update,也没误删控制器或配置文件,实在搞不懂哪里出问题了。搜了常见错误也没找到解法,换Rails、Devise版本,重置数据库这些操作都试过了,甚至都想换个认证gem或者自己从头写认证了。
下面是相关代码和终端的栈追踪信息:
视图文件:new_reviewer.html.erb
<%= form_for(@user, url: registration_path(@user)) do |f| %> <div class="registration-container"> <h2>Sign up today!</h2> <div class="profile-pic"> <%= f.label "Add a profile pic" %><br /> <%= f.file_field :avatar %> </div><br /> <div class="user-roles"> <%= f.select(:access_level, [['Reviewer', 'reviewer']]) %> </div><br /> <div class="user-name"> <%= f.label :first_name %> <%= f.text_field :first_name %><br /> <%= f.label :last_name %> <%= f.text_field :last_name %> </div><br /> <div class="field"> <%= f.label :email %><br /> <%= f.email_field :email, autofocus: true, autocomplete: "email" %> </div> <div class="field"> <%= f.label :password %> <% if @minimum_password_length %> <em>(<%= @minimum_password_length %> characters minimum)</em> <% end %><br /> <%= f.password_field :password, autocomplete: "new-password" %> </div> <div class="field"> <%= f.label :password_confirmation %><br /> <%= f.password_field :password_confirmation, autocomplete: "new-password" %> </div> <div class="actions"> <%= f.submit "Sign up" %> </div> </div> <% end %>
控制器文件:users_controller.rb
class UsersController < ApplicationController def new_author @user = User.new end def new_reviewer @user = User.new end def show @user = User.find(params[:id]) @user.books.each do |b| @avg_rating = if b.reviews.blank? 0 else b.reviews.average(:rating).round(2) end end end def profile @current_user = current_user @helpful = current_user.reviews.where(helpful: true) @unhelpful = current_user.reviews.where(unhelpful: true) @reviews = current_user.reviews unhelpful = @unhelpful.count total = @reviews.count subtotal = total - unhelpful @score = subtotal.to_f / total end def reviewer if params[:search] @reviewers_search = User.search(params[:search]).paginate(:page => params[:page], :per_page => 2) else @reviewers_search = User.where(access_level: :reviewer).order('first_name ASC').paginate(:page => params[:page], :per_page => 2) end end def author if params[:search] @authors_search = User.search(params[:search]).paginate(:page => params[:page], :per_page => 2) @author_rank = b.reviews.count else @authors_search = User.where(access_level: :author).order('first_name ASC').paginate(:page => params[:page], :per_page => 2) end end def edit end def update @user = User.find(params[:id]) if @user.update(user_params) redirect_to @user end end def destroy user = User.find(params[:id]) user.destroy redirect_to root_path end private def user_params params.require(:user).permit(:bio, :ranking, :first_name, :last_name, :email, :password, :avatar, :access_level) end end
终端栈追踪信息
ActionView::Template::Error (undefined method `fetch_value' for nil:NilClass): 1: 2: <%= form_for(@user, url: registration_path(@user)) do |f| %> 3: <div class="registration-container"> 4: <h2>Sign up today!</h2> 5: app/views/users/new_reviewer.html.erb:2:in `_app_views_users_new_reviewer_html_erb__2780381832095941109_47402928557320'
嘿,我瞅了下你的代码和报错信息,发现几个可能的点,咱们一个个来捋:
1. 视图路由参数的直接问题
Devise的registration_path处理新用户注册时,不需要传@user参数——新用户还没保存到数据库,传了反而会让路由生成逻辑出错,导致内部某个对象变成nil,触发fetch_value错误。把视图里的表单行改成下面两种方式之一:
- 明确指定资源类型:
<%= form_for(@user, url: registration_path(:user)) do |f| %>
- 或者让
form_for自动识别路由(更简洁):
<%= form_for(@user, as: :user, url: registration_path) do |f| %>
2. 控制器里的隐藏bug
看你的users_controller.rb里的author方法,有一行@author_rank = b.reviews.count——这里的b完全没定义啊!虽然这个方法看起来和注册流程不直接相关,但如果应用有全局异常处理或中间件预加载控制器方法,这个未定义变量可能会引发连锁的奇怪错误。要么删掉这行,要么修正逻辑,比如如果想统计作者的书籍评论数,可以改成:
@author_rank = @authors_search.sum { |user| user.books.sum { |b| b.reviews.count } }
3. 补全Devise默认变量(可选但推荐)
Devise默认会给注册视图提供@minimum_password_length变量,但你是自定义的注册视图,没有继承Devise的注册控制器逻辑,所以这个变量可能未被设置。虽然不是当前报错的原因,但后续可能出问题,建议在new_reviewer方法里加上:
def new_reviewer @user = User.new @minimum_password_length = Devise.password_length.min end
最后一步:清理缓存重启
修改完后,重启服务器,再试试注册流程。如果还是不行,清空一下临时缓存:
rails tmp:clear
有时候奇怪的错误就是缓存残留导致的。
内容的提问来源于stack exchange,提问作者dmberko11

