从Rails中的控制器调用方法?

时间:2014-06-08 08:39:45

标签: ruby-on-rails ruby

我是铁轨初学者,这个简单的问题让我很困惑。 在每个页面上,我都想要一个包含我应用中所有可用页面的列表。所以在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;,这是不成功的。 我相信这个问题与路由有关,任何人都可以启发我。

5 个答案:

答案 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.erbapp/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来获取它所在的页面需要。这是一个非常好的解决方案,但也有一些工作(矫枉过正?)。但结构非常好。

  • 这个问题,你在页面上有不同的区域,每个区域应该有自己的Controller-Model-View,这正是cells gem gem以非常干净的方式解决的问题。在我链接的页面上有一个非常好的例子来呈现购物车,所以你总是可以检查出来。

答案 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渲染。