0

我只是不想复制和粘贴。一定有更好的方法。

我有一个控制器,它使用单个模型将一些数据收集到两个数组中。然后我有一个在图中使用这些数组的单一视图(index.html.erb)。这很简单。这是整个视图。显然,来自控制器的数组是@buildStepArrays 和@buildDates。

<% chart = GChart.line(:title=>"Build Times", :size=>"1000x300", :data=>@buildStepArrays, :colors=>@colors, :legend=>@buildDates) %>
<% chart.axis(:left) %>
<%= image_tag chart.to_url %>

控制器在这里

def index
    # These three arrays should be the same size
    @buildStepArrays = []
    @buildDates = []
    @totalBuildTimes = []  

    @latestId = Env2.last().BuildId
    @latestId = @latestId - 1

    for buildNumber in (@latestId-4)..@latestId
        @build = Env2.find_all_by_BuildId(buildNumber)
        totalTime = 0
        @currentBuildTimes = []
        for step in @build
            @currentBuildTimes << step.Minutes
            totalTime += step.Minutes.to_i
        end
        @buildStepArrays << @currentBuildTimes.map { |e| e.nil? ? 0 : e }
        @totalBuildTimes << totalTime
        @buildDates << @build.last().Created
        @colors = [["FF1300"], ["FF8C00"], ["FFFF00"], ["00CC00"], ["1240AB"]]
    end
end

我想做的是从四个模型(四个不同数据库中的同一张表)中收集完全相同的数据,而不仅仅是一个,然后在视图上显示四个图表而不是一个。我对 Rails 知之甚少,不知道如何正确地做到这一点。我现在唯一的想法是将代码复制并粘贴到我的控制器中四次,然后更改变量名称。这太可怕了。我应该做些什么?

4

3 回答 3

0

尝试这个

控制器

def index
  @data = [Env1, Env2, Env3].map do |model|
    data = Hash.new
    data[:title] = "Build Times"
    data[:buildStepArrays] = []
    data[:buildDates] = []
    data[:totalBuildTimes] = []  

    data[:latestId] = model.last().BuildId
    data[:latestId] = data[:latestId] - 1

    for buildNumber in (data[:latestId]-4)..data[:latestId]
      data[:build] = model.find_all_by_BuildId(buildNumber)
      totalTime = 0
      data[:currentBuildTimes] = []
      for step in data[:build]
        data[:currentBuildTimes] << step.Minutes
        totalTime += step.Minutes.to_i
      end
      data[:buildStepArrays] << data[:currentBuildTimes].map { |e| e.nil? ? 0 : e }
      data[:totalBuildTimes] << totalTime
      data[:buildDates] << data[:build].last().Created
      data[:colors] = [["FF1300"], ["FF8C00"], ["FFFF00"], ["00CC00"], ["1240AB"]]
    end
  end
end

看法

<% @data.each do |data| %>
  <% chart = GChart.line(:title=>data[:title], :size=>"1000x300", :data=>data[:buildStepArrays], :colors=>data[:colors], :legend=>data[:buildDates]) %>
  <% chart.axis(:left) %>
  <%= image_tag chart.to_url %>
<% end %>

我只是将所有内容都放入哈希中,但您最好将需要在视图中渲染的内容放在那里。

于 2012-08-27T23:23:06.873 回答
0

实现此目的的一种方法是创建包含重复代码的模块,在您的情况下,至少重复四次。你要做的仍然是为每个模型创建控制器文件......

class ModelAController < ApplicationController
  include BasicActions
  before_filter get_model      

  def get_model
    @model = self.class.to_s.gsub("Controller").classify
  end
end

您会注意到 'get_model' 方法,这很重要,因为它将@model 变量设置为保存您正在处理的类。我没有确认确切的代码来获取 coass 名称文本,所以你必须玩弄它。你可能会在你的模块中使用@model。

这是一个骨骼模块:

module BasicActions

  def some_method
    ...
  end

对于呈现的每个操作,您仍然需要所有相关视图,但是有一些方法可以将其限制为一组视图......

于 2012-08-27T23:58:41.647 回答
0

最优雅的解决方案可能是使用演示者。Presenters 可以帮助您清理视图中的逻辑或清理控制器中的太多实例变量。后者似乎是这里的情况。

使用演示者可以让您:

  • 优化数据库查询,在您的情况下从所有四个数据库执行单个查询。
  • 通过允许您直接为演示者中的操作编写测试,可以更轻松地测试您的代码。

如果不了解更多有关您的应用程序的信息,很难准确地说出您将如何构建演示者,但我可以为您提供一些带有样机代码的通用指南,只是为了向您展示它是如何工作的。

与其简单地从四个不同的模型中定义实例变量,不如在控制器中定义一个类似于以下的新操作:

/app/controllers/charts_controller.rb

...
def show
    @data = ChartPresenter.new(argument)
end
...

然后,您将在新目录中定义新的演示者类,并使用与视图中所需的输出相对应的操作:

/app/presenters/chart_presenter.rb

class ChartPresenter

    def initialize(data)
        @data = data
    end

    def method_name
        ...
    end

end

/app/views/chart.html.erb

...
<%= @data.method_name %>
...

参考

附言

大多数教程会告诉你编辑你config/application.rb的设置config.autoload_paths到你的演示者目录。但是,在 Rails 3 中,这不再是必需的,因为下面的所有内容/app/*都会自动添加。

于 2012-08-28T00:18:40.990 回答