Explorar el Código

Merge pull request #252 from knu/clickable_diagram

Add links to a generated SVG diagram.
Andrew Cantino hace 11 años
padre
commit
079b02f1a9

+ 2 - 0
app/controllers/agents_controller.rb

@@ -1,4 +1,6 @@
 class AgentsController < ApplicationController
+  include DotHelper
+
   def index
     @agents = current_user.agents.page(params[:page])
 

+ 0 - 15
app/helpers/application_helper.rb

@@ -14,19 +14,4 @@ module ApplicationHelper
       link_to '<span class="label label-warning">No</span>'.html_safe, agent_path(agent, :tab => (agent.recent_error_logs? ? 'logs' : 'details'))
     end
   end
-
-  def render_dot(dot_format_string)
-    if (command = ENV['USE_GRAPHVIZ_DOT']) &&
-       (svg = IO.popen([command, *%w[-Tsvg -q1 -o/dev/stdout /dev/stdin]], 'w+') { |dot|
-          dot.print dot_format_string
-          dot.close_write
-          dot.read
-        } rescue false)
-      svg.html_safe
-    else
-      tag('img', src: URI('https://chart.googleapis.com/chart').tap { |uri|
-            uri.query = URI.encode_www_form(cht: 'gv', chl: dot_format_string)
-          })
-    end
-  end
 end

+ 40 - 0
app/helpers/dot_helper.rb

@@ -0,0 +1,40 @@
+module DotHelper
+  def render_agents_diagram(agents)
+    if (command = ENV['USE_GRAPHVIZ_DOT']) &&
+       (svg = IO.popen([command, *%w[-Tsvg -q1 -o/dev/stdout /dev/stdin]], 'w+') { |dot|
+          dot.print agents_dot(agents, true)
+          dot.close_write
+          dot.read
+        } rescue false)
+      svg.html_safe
+    else
+      tag('img', src: URI('https://chart.googleapis.com/chart').tap { |uri|
+            uri.query = URI.encode_www_form(cht: 'gv', chl: agents_dot(agents))
+          })
+    end
+  end
+
+  private
+
+  def dot_id(string)
+    # Backslash escaping seems to work for the backslash itself,
+    # despite the DOT language document.
+    '"%s"' % string.gsub(/\\/, "\\\\\\\\").gsub(/"/, "\\\\\"")
+  end
+
+  def agents_dot(agents, rich = false)
+    "digraph foo {".tap { |dot|
+      agents.each.with_index do |agent, index|
+        if rich
+          dot << '%s[URL=%s];' % [dot_id(agent.name), dot_id(agent_path(agent.id))]
+        else
+          dot << '%s;' % dot_id(agent.name)
+        end
+        agent.receivers.each do |receiver|
+          dot << "%s->%s;" % [dot_id(agent.name), dot_id(receiver.name)]
+        end
+      end
+      dot << "}"
+    }
+  end
+end

+ 1 - 11
app/views/agents/diagram.html.erb

@@ -9,17 +9,7 @@
       </div>
 
       <div class='digraph'>
-        <%
-           dot_format_string = "digraph foo {"
-           @agents.each.with_index do |agent, index|
-             dot_format_string += "\"#{agent.name}\";"
-             agent.receivers.each do |receiver|
-               dot_format_string += "\"#{agent.name}\"->\"#{receiver.name}\";"
-             end
-           end
-           dot_format_string = dot_format_string + "}"
-        %>
-        <%= render_dot(dot_format_string) %>
+        <%= render_agents_diagram(@agents) %>
       </div>
     </div>
   </div>

+ 48 - 0
spec/helpers/dot_helper_spec.rb

@@ -0,0 +1,48 @@
+require 'spec_helper'
+
+describe DotHelper do
+  describe "#dot_id" do
+    it "properly escapes double quotaion and backslash" do
+      dot_id('hello\\"').should == '"hello\\\\\\""'
+    end
+  end
+
+  describe "with example Agents" do
+    class Agents::DotFoo < Agent
+      default_schedule "2pm"
+
+      def check
+        create_event :payload => {}
+      end
+    end
+
+    class Agents::DotBar < Agent
+      cannot_be_scheduled!
+
+      def check
+        create_event :payload => {}
+      end
+    end
+
+    before do
+      stub(Agents::DotFoo).valid_type?("Agents::DotFoo") { true }
+      stub(Agents::DotBar).valid_type?("Agents::DotBar") { true }
+    end
+
+    describe "#agents_dot" do
+      it "generates a DOT script" do
+        @foo = Agents::DotFoo.new(:name => "foo")
+        @foo.user = users(:bob)
+        @foo.save!
+
+        @bar = Agents::DotBar.new(:name => "bar")
+        @bar.user = users(:bob)
+        @bar.sources << @foo
+        @bar.save!
+
+        agents_dot([@foo, @bar]).should == 'digraph foo {"foo";"foo"->"bar";"bar";}'
+        agents_dot([@foo, @bar], true).should == 'digraph foo {"foo"[URL="/agents/%d"];"foo"->"bar";"bar"[URL="/agents/%d"];}' % [@foo.id, @bar.id]
+      end
+    end
+  end
+end