新手问题 Rails 中如何正确的理解 Layout 中 application.html.erb 插入其他 controller 的对应 view 的 partial?

shane51 · 2014年06月23日 · 最后由 sandwind 回复于 2015年05月12日 · 4951 次阅读

HI,大家好,我业余自学 rail3 个月,水平浅薄,自己做了个小网站,借鉴了 Pragramic Aigle Web Development with Rails 4 里面关于将_cart.html.erb 插入到 application.html.erb 中的例子,想将一个某个 model 对应的表里面的数据显示到 application.html.erb 里面导航栏的 dropdownlist 里。相当于我希望导航栏里面的每个栏的数据能够根据 model 的数据动态刷新。 页面如图:

我当时是在 Docs 页面对应的 doc_controller 里的 Index 方法下定义了@doc_recent = Doc.order(:updated_at)[0..5] 来取最最近更新的 5 的 Doc,然后写了个_doc_recent.html.erb,作为 partial,最好在 application.html.erb 中里面 render @doc_recent

结果,到这的时候,报错了,显示@doc_recent值为‘nil’,我来回改了很多,也遇到很多的错,我在想我就是按照书上照猫画虎,为啥我画的不对。。。所以,请大家帮我讲下,像我这样想在 layout 中的 application.html.erb 中插入其他 controller 的 view 的 partial 有什么特殊的要求或者要注意的地方没有?

另外,我这个错,我想是不是,因为导航栏被渲染出来的时候,Docs 页面还没有渲染,因此我在 doc_controller 下定义的值就不会被取出。因此会报错???正确的是不是应该这样:应该为导航栏上 Doc 的 dropdown list 创建一个 model 和 controller,让这个 Model 与之前 Docs 页面的 Model 相关联,然后从新创建的 Model 里面去取@doc_recent的值?这样就正确了??

写有些复杂,请见谅。。。非常感谢能讲讲原理,十分感谢!!

因为 application.html.erb 是一个 layout,这个 layout 与 view 一起构成一个完整的页面,也就是“每个”view 都会渲染一次 layout。 你只在 doc_controller#index 里面做了查询,在其他页面当然为 nil 了。

这种情况是从数据库里面调最近的 5 个 docs,但也不算动态的,因为这个数据其实和当前的 controller action 无关。

做法很简单,不要在 controller 里面定义@doc_recent,直接在 partial 里面做。Controller 里面只定义和当前 action 直接相关的 instance variable.

# _nav partial
<% Doc.recent.each do |doc| %>
  <li><%= doc.title %>
<% end %>

然后 Doc model 里面

def self.recent
  order('updated_at DESC').limit(5)
end

这种做法可以达到要求。但有一个小问题就是流量大之后 cache 可能会更新很快,如果经常有新的 doc 创建的话。当然你现在可以暂时不用关心这个问题。

以后如果改进,可以在用户点击"Doc“菜单后,用 Javascript 动态调取数据,这样 cache 就可以维持比较久。

#1 楼 @saiga 谢谢回复!恩,我大概理解了为什么出错,不过不是很明白,这里如果用 partial 该如何用

#2 楼 @billy 非常感谢!我回头试试。对于 controller,view 和 partial 我还需要继续学习,还是不能在有 layout 情况下正确的使用。。

#2 楼 @billy 我按你的方法试了,终于成功了,非常感谢!!

需要 登录 后方可回复, 如果你还没有账号请 注册新账号