Skip to content

Instantly share code, notes, and snippets.

@mitsuru
Created November 23, 2017 06:54
Show Gist options
  • Save mitsuru/e3c22d4da79c0b7fb816786ded15ff9f to your computer and use it in GitHub Desktop.
Save mitsuru/e3c22d4da79c0b7fb816786ded15ff9f to your computer and use it in GitHub Desktop.
Visualize aasm state diagram
class AasmvizController < ApplicationController
before_action :authenticate_account!
before_action :require_admin!
def index
Rails.application.eager_load!
@models = ActiveRecord::Base.descendants.select { |c| c.respond_to? :aasm }
end
def show
cname = params[:id]
@klass = cname.sub(/^(\w)/, &:capitalize).constantize
respond_to do |format|
format.html { render }
format.dot { render }
end
end
private
def require_admin!
raise CanCan::AccessDenied.new unless current_account.admin?
end
end
.main-container
.container
%h2 State Diaglams
%ul
- @models.each do |model|
%li= link_to model, aasmviz_path(model)
<% resource = @klass.new %>
digraph sm_hoge {
rankdir=LR;
<%= @klass.aasm.initial_state %> [ shape = diamond ]
<%
resource.aasm.states.each do |state|
next if state.name == @klass.aasm.initial_state
if resource.aasm.events.empty?
%><%= "#{state.name} [ shape = diamond ]\n" %><%
else
%><%= "#{state.name}\n" %><%
end
end
@klass.aasm.events.each do |event|
event.transitions.each do |t|
if t.from && t.to
%><%= t.from %> -> <%= t.to %> [ label = "<%= event.name %>" <%
if t.opts[:guard].try(:is_a?, Symbol)
%>, headlabel = "<%= t.opts[:guard] %>" <%
end
%> ]
<%
end
end
end
%>
}
%script{src: 'http://d3js.org/d3.v3.js' }
%script{src: 'http://cpettitt.github.io/project/graphlib-dot/v0.5.2/graphlib-dot.js'}
%script{src: 'http://cpettitt.github.io/project/dagre-d3/latest/dagre-d3.js'}
.main-container
.container
%h2 #{@klass.name} (#{@klass.model_name.human})
%svg#graphContainer
%g
:coffee
$(document).ready ->
e = document.querySelector('#graphContainer')
$.get("#{url_for(format: 'dot')}")
.success (data) ->
g = graphlibDot.read(data)
g.graph().marginx = 20
g.graph().marginy = 20
g.graph().transition = (selection) ->
selection.transition().duration(500)
render = new dagreD3.render()
d3.select("svg g").call(render, g);
svg = document.querySelector('#graphContainer')
bbox = svg.getBBox()
svg.style.width = bbox.width + 40.0 + 'px'
svg.style.height = bbox.height + 40.0 + 'px'
:css
.node rect, .node polygon {
stroke: #333;
stroke-width: 1.5px;
fill: #fff;
}
.edgeLabel rect {
fill: #fff;
}
.edgePath {
stroke: #333;
stroke-width: 1.5px;
fill: none;
}
.main-container .container {
overflow: scroll;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment