Rails自定义命名空间控制器视图用simple_form报`resource'未定义错误
两步调研流程Rails实现报错修复
业务场景
- 设计的两步用户调研流程:
- 第一步:用户提交
SurveyResults模型新记录后,自动重定向至第二步页面 - 第二步:用户通过单选按钮选择自身的使用经验等级,提交后更新当前登录用户的
User模型对应字段
- 第一步:用户提交
现有实现
控制器代码
新建控制器app/controllers/users/user_experience_levels_controller.rb,当前仅编写了update动作逻辑:
def update if current_user.update(experience_level: users_user_experience_level_params) redirect_to root_path, notice: 'User experience level was successfully submitted.' else render :edit end end private def users_user_experience_level_params params.fetch(:users_user_experience_level).permit(:experience_level) end
视图代码
对应edit页面的视图文件app/views/users/user_experience_levels/edit.html.erb:
<%= simple_form_for(resource, as: resource_name, url: edit_users_user_experience_level_path(resource_name), html: { method: :put }) do |f| %> <%= f.error_notification %> <%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %> <%= f.input :experience_level, collection: User::USER_EXPERIENCE_LEVEL, as: :radio_buttons %> <%= f.button :submit %> <% end %>
路由配置
config/routes.rb中的对应路由规则:
namespace :users do resources :user_experience_levels, only: [:edit, :update] end
报错信息
访问edit页面时触发如下错误:
NameError in Users::UserExperienceLevels#edit undefined local variable or method `resource' for #<ActionView::Base:0x0000000000bbd0>
问题根因
视图中使用的resource、resource_name是Devise体系下默认向视图注入的辅助变量,当前新建的独立控制器既没有继承Devise的控制器基类,也没有编写edit动作向视图传递对应的实例变量,导致视图无法找到对应变量触发NameError。
同时现有实现还存在3个隐含的逻辑不匹配问题:
- 路由采用多记录资源的
resources配置,会要求请求传递记录id参数,和“操作当前登录用户自身信息”的场景不匹配 - 表单提交的参数键和强参数逻辑不匹配:表单通过
as: resource_name指定的参数前缀和强参数里取的users_user_experience_level键无法对应 - 表单的提交路由指向了edit动作的路径,和PUT请求对应的update路径不匹配
修复步骤
- 补全控制器缺失的edit动作,向视图传递绑定表单所需的变量
def edit # 将当前登录用户作为表单绑定对象 @resource = current_user # 指定表单对应的参数前缀 @resource_name = :user end - 调整表单的绑定对象和提交路径,适配控制器传递的变量和路由规则
<%= simple_form_for @resource, as: @resource_name, url: users_user_experience_level_path, html: { method: :put } do |f| %> - 调整强参数的取值逻辑,匹配表单提交的参数结构
def users_user_experience_level_params params.require(:user).permit(:experience_level) end - 优化路由配置,将多资源的
resources改为单资源resource,生成不需要传递id参数的路由,适配当前用户的单条信息操作场景:namespace :users do resource :user_experience_level, only: [:edit, :update] end
内容的提问来源于stack exchange,提问作者mr_muscle
相关产品推荐
相关产品推荐

