如何在两个控制器之间共享代码

时间:2013-08-25 10:06:26

标签: ruby-on-rails

我在两个控制器中定义了一个实例变量@posts_by_month,用于两个视图:

帖子控制器:

class PostsController < ApplicationController

def index
    @posts = Post.all
    @posts_by_month = Post.all.group_by { |post| post.created_at.strftime("%L") }

    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @posts }
    end
  end  
.
.
end

档案管理员:

class ArchivesController < ApplicationController
  def index  
    @posts_by_month = Post.all.group_by { |post| post.created_at.strftime("%B") }
  end  
end

发布索引视图:

<h1>Listing posts</h1>
.
.
.
<div>
  <% @posts_by_month.each do |millisecond, posts| %>
    <p><%= millisecond %>milliseconds <%= posts.count %></p>
  <% end %>
</div>

档案索引视图:

<% @posts_by_month.each do |monthname, posts| %>
<%= monthname %>
<ul>
   <% posts.each do |post| %>
     <h3><%= post.title %></h3>
     <p><%= post.body %></p>
   <% end %>
</ul>
<% end %>

我有两个问题。有没有什么方法可以定义@posts_by_month实例变量,这样我就可以让两个视图都可以使用它而不必在每个控制器中重复它?

其次,有没有办法可以将<p><%= millisecond %>milliseconds <%= posts.count %></p>的毫秒部分变成一个导致存档视图的链接?

注意:在我的应用程序中,毫秒将替换为存档视图中的月份。

2 个答案:

答案 0 :(得分:2)

当执行一个动作(又称渲染)时,实例结束了。没有更多的实例变量。

View中的实例变量不是真实的实例变量。 View和Controller属于不同的类,它们如何共享实例?实际情况是,Rails所做的是将这些实例变量从Controller实例复制到View实例。

所以你问题的答案是:不。

但你仍然可以通过应用程序控制器中的私有方法来干燥代码,与PostsController和ArchiveController共享。

class ApplicationController
  private
  def posts_by_time(arg)
    Post.all.group_by { |post| post.created_at.strftime(arg) }
  end
end

class PostsController < ApplicationController
  def index
    @posts = posts_by_time "%L"
    # ...
  end
end

class ArchievesController < ApplicationController
  def index
    @posts = posts_by_time "%B"
    # ...
  end
end

答案 1 :(得分:1)

是的,您可以减少相同变量的重复。一种方法是使用过滤器:

在应用程序控制器中定义一个方法:

class ApplicationController < ActionController::Base
  private
  def find_post_by_month
    @posts_by_month = Post.all.group_by { |post| post.created_at.strftime("%L") }
  end
end

然后在存档和发布控制器内:

class ArchivesController < ApplicationController
  before_filter :find_post_by_month, :only => :index  
  ...    
end


class PostsController < ApplicationController
  before_filter :find_post_by_month, :only => :index  
  ...
end

这将为您提供@posts_by_month变量的值。

并且,为了建立所提及文本的链接,您应该使用以下代码:

<p><%= link_to "#{millisecond} milliseconds", path %></p>   # Replace path with your url