未设置before_action却触发方法调用,如何允许直接访问results动作?
你遇到的核心问题是路由配置误把results当成了需要ID的成员动作(member action),导致系统错误触发set_preference方法去查找ID为result的Preference记录,最终抛出找不到资源的错误。下面给你分步解决的方案:
1. 修正路由配置,将results设为集合动作(collection action)
集合动作不需要传入资源ID,完全匹配你直接访问/preferences/results的需求。打开config/routes.rb,修改Preferences的路由规则:
resources :preferences do # 把results设为集合动作,无需ID参数 collection do get 'results' end # 保留原有的成员动作(需要ID的,比如test) member do get 'test' end end
这样配置后,路由会生成/preferences/results的合法GET路径,不会再把results当作ID参数传递给控制器。
2. 确认前置动作范围(已有配置正确,再核对下)
你的代码里已经把set_preference的作用范围限定在:show, :edit, :test, :update, :destroy,这个设置是正确的——因为results动作需要加载所有Preference记录,不需要单个资源,所以完全不需要触发这个前置方法。
之前的报错本质是路由匹配错误导致的:如果路由把results设成了member,访问/preferences/results时Rails会把results当作ID参数传给set_preference,这就是你看到Couldn't find Preference with 'id'=result的原因。
3. 可选:优化test动作的跳转逻辑
你的test动作里用了render action: "results",这只是渲染results模板,并不会执行results动作里的逻辑(比如@results = Preference.all)。如果希望test流程结束后跳转到独立的results页面,建议改成重定向:
def test # 你的业务逻辑代码 redirect_to results_preferences_path end
这样用户完成test流程后,地址栏会变成/preferences/results,和直接访问的路径一致,体验更统一。
完成以上配置后,用户直接访问/preferences/results就不会再触发查找单个资源的逻辑,能正常加载所有Preference的列表了。
内容的提问来源于stack exchange,提问作者Bad Programmer

