RoR渲染Partial异常:跨视图调用报错,直接访问路径正常
undefined method each for nil:NilClass错误 这个问题我之前也碰到过,本质原因很简单——你的posts/_dashboard.html.erb Partial依赖某个集合变量(比如@posts),但跨视图调用时没有给它传递这个变量,导致Partial里的变量是nil,自然没法调用each方法。
先给你理清楚前因后果:你说直接访问0.0.0.0:3000/posts/_dashboard能正常工作,其实这不是直接访问Partial本身(Rails的Partial是不能通过路由直接访问的),应该是你的路由里有对应posts#dashboard的action,这个action里已经给@posts(或者Partial需要的其他变量)赋了值,然后渲染了这个Partial,所以能正常显示。但当你在其他视图里调用这个Partial时,那个视图对应的Controller action并没有赋值这个变量,也没有传递给Partial,就触发了错误。
下面给你几个具体的解决步骤:
1. 先确认Partial依赖的变量
打开posts/_dashboard.html.erb,找到报错的那行代码,比如大概率是类似<% @posts.each do |post| %>这样的遍历。记下来这个变量名(比如@posts)。
2. 调用Partial时主动传递局部变量(推荐方式)
不要依赖实例变量(@xxx),改用局部变量传递,这样Partial的复用性更高,也不会和其他视图的变量冲突。
比如在你要调用Partial的视图里,这样写:
<%= render partial: 'posts/dashboard', locals: { posts: @target_posts } %>
这里的@target_posts是你在当前视图对应的Controller action里赋值的集合(比如@target_posts = Post.all或者其他查询结果)。
然后把Partial里的@posts改成posts(局部变量),比如:
<% posts.each do |post| %> <!-- 你的Post内容渲染代码 --> <% end %>
3. 可选:给Partial设置变量默认值(容错处理)
如果担心有时候忘记传递变量,可以在Partial的开头加一行默认值设置,这样即使没传变量,也只会显示空内容而不会报错:
<% posts ||= [] %> <% posts.each do |post| %> <!-- 你的Post内容渲染代码 --> <% end %>
这样调整后,不管在哪个视图里调用这个Partial,只要传递对应的集合变量,就能正常工作啦。
内容的提问来源于stack exchange,提问作者George Morris

