我是铁轨初学者,这个简单的问题让我很困惑。 在每个页面上,我都想要一个包含我应用中所有可用页面的列表。所以在layouts / application.html.erb中我有以下代码:
<ul>
<!-- This loop prints out links to all the pages -->
<% @pages = Page.all %>
<% @pages.each do |page| %>
<li><%= link_to page.name, page_path(page) %></li>
<% end %>
这段代码有效,但我对它不满意,因为它违反了MVC原则。真的不是用&lt;%@pages = Page.all%&gt;查询数据库,而是想在PagesController中调用getpages方法,如下所示:
def getpages
@pages = Page.all
end
我的第一直觉是替换&lt;%@pages = Page.all%&gt;使用&lt;%PagesController.getpages%&gt;,这是不成功的。 我相信这个问题与路由有关,任何人都可以启发我。
答案 0 :(得分:1)
有几种方法可以实现这一目标。我会尝试对它们进行总结,但最简单的方法是在控制器上使用before_filter
。
考虑到您的方法在控制器中命名为get_pages
,只需写:
class SomeController < ApplicationController
before_filter :get_pages
def get_pages
@pages = Page.all
end
end
然后,在您的视图中,您将能够在所有控制器操作上以@pages
访问它。
答案 1 :(得分:1)
您可以像这样使用helper method:
#app/helpers/application_helper.rb
Class ApplicationHelper
def pages
Page.all
end
end
您的观点中提供了助手,因此您可以执行此操作:
#app/views/application/index.html.erb
<% pages.each do |page| %>
<%= page.title %>
<% end %>
答案 2 :(得分:1)
首先,我要说你的方法不是 错误的imho。引入一个仅仅是Page.all
的别名的额外方法并不是真正需要的,或者实际上并不是一种改进。
但肯定有更好的方法。
我会按如下方式解决这个问题:在ApplicationController
中我会添加方法
def get_all_pages
@pages ||= get_all_pages
end
这将确保任何控制器都知道该方法。
然后,如果您确定,在每个页面上都需要它,那么您before_filter
中只需ApplicationController
,但通常情况下,我更愿意将其写入控制器本身。
E.g。
class IdeasController < ApplicationController
before_action :get_all_pages
... the rest of your controller ...
end
此外,我会将您的网页列表提取到app/views/shared/_pages_list.html.erb
或app/views/pages/_pages_list.html.erb
下的部分商店,然后在您的application.html.erb
中调用以呈现部分内容。
我们调用的方法设置实例变量@pages
,它将在视图中可用,所以你的部分想要:
<ul>
<% @pages.each do |page| %>
<li><%= link_to page.name, page_path(page) %></li>
<% end %>
</ul>
最后,为了完整性,让我回答一下如何在视图中使用控制器方法。在控制器中写
def get_pages
# ..do something
end
helper_method :get_pages
这将使方法get_pages
在视图中可用,但仅适用于负责加载/呈现该视图的控制器。因此,如果您想要所有视图,请在ApplicationController
中进行定义。例如。这是我们在定义current_user
方法时通常所做的。
如果您开始获取更多代码,请将与页面列表提取和渲染相关的代码提取到单独的模块中,并将其包含在ApplicationController
中。这使您的ApplicationController
更具可读性。
concerns
引入的内容,因此您可以使用它,如果您使用的是rails 4 Page
是它自己的资源,所以你总是可以创建一个单独的PagesController
并确保它负责呈现列表,并使用ajax来获取它所在的页面需要。这是一个非常好的解决方案,但也有一些工作(矫枉过正?)。但结构非常好。
答案 3 :(得分:0)
如果是这样,只需在控制器
中添加以下代码即可def youraction
@pages = Page.all
end
这将使视图中的全局变量@pages可用。直接将其称为@pages。
答案 4 :(得分:0)
另一种方法是使用异步调用来加载PagesController#index
的结果并将其显示在应用程序布局中。
$.ajax("<%= pages_path %>").done(function(html) {
$("#pages-list").html(html);
});
要实现此目的,如果PagesController#index
返回layout: false
,您可以使用request.xhr?
进行true
渲染。