aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2016-01-04 00:02:21 +0900
committerKazuki Yamaguchi <k@rhe.jp>2016-01-04 00:02:21 +0900
commit09116c1ab91677f950b7e4795d7a31324253be6d (patch)
tree49a5302b7eda3d32c057b0ee0d0e85a54b13c68a
parentad5967a256dfefe5191013b56f1fc37fdb87e33c (diff)
downloadpoe-09116c1ab91677f950b7e4795d7a31324253be6d.tar.gz
🔪
-rw-r--r--.gitignore4
-rw-r--r--Gemfile8
-rw-r--r--Gemfile.lock34
-rw-r--r--app/assets/javascripts/application.js6
-rw-r--r--app/assets/javascripts/cable.coffee11
-rw-r--r--app/assets/javascripts/channels/.keep0
-rw-r--r--app/assets/javascripts/results.es6 (renamed from app/assets/javascripts/snippets.js)0
-rw-r--r--app/assets/javascripts/snippets.es653
-rw-r--r--app/assets/stylesheets/application.css15
-rw-r--r--app/assets/stylesheets/application.scss4
-rw-r--r--app/assets/stylesheets/results.scss3
-rw-r--r--app/assets/stylesheets/scaffold.css84
-rw-r--r--app/assets/stylesheets/snippets.scss (renamed from app/assets/stylesheets/snippets.css)0
-rw-r--r--app/channels/application_cable/channel.rb5
-rw-r--r--app/channels/application_cable/connection.rb5
-rw-r--r--app/controllers/application_controller.rb3
-rw-r--r--app/controllers/results_controller.rb20
-rw-r--r--app/controllers/snippets_controller.rb30
-rw-r--r--app/helpers/application_helper.rb3
-rw-r--r--app/helpers/results_helper.rb2
-rw-r--r--app/jobs/execute_job.rb8
-rw-r--r--app/models/compiler.rb58
-rw-r--r--app/models/result.rb40
-rw-r--r--app/models/snippet.rb14
-rw-r--r--app/views/layouts/application.html.erb21
-rw-r--r--app/views/results/_result.html.erb16
-rw-r--r--app/views/snippets/_form.html.erb45
-rw-r--r--app/views/snippets/edit.html.erb6
-rw-r--r--app/views/snippets/index.html.erb29
-rw-r--r--app/views/snippets/new.html.erb6
-rw-r--r--app/views/snippets/show.html.erb18
-rw-r--r--config.ru4
-rw-r--r--config/application.rb2
-rw-r--r--config/routes.rb19
-rw-r--r--db/migrate/20160101024323_extend_result.rb6
-rw-r--r--db/migrate/20160101060555_add_command_line_to_compilers.rb5
-rw-r--r--db/migrate/20160101121151_add_language_to_snippet.rb5
-rw-r--r--db/schema.rb14
-rw-r--r--db/seeds.rb5
39 files changed, 334 insertions, 277 deletions
diff --git a/.gitignore b/.gitignore
index 9df4381..59e4c48 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,3 +18,7 @@
# Vim
.*.sw*
+
+# Playground
+playground/base
+playground/ruby
diff --git a/Gemfile b/Gemfile
index 0f4aec0..cd48405 100644
--- a/Gemfile
+++ b/Gemfile
@@ -6,11 +6,14 @@ gem "sidekiq"
gem "sinatra", require: false
gem "sprockets"
+gem "sass-rails"
gem "uglifier", ">= 1.3.0"
gem "sprockets-es6"
-gem "turbolinks"
+gem "jquery-rails"
+gem "bootstrap-sass"
+gem "codemirror-rails"
-gem "puma"
+gem "plum"
group :development, :test do
gem "byebug"
@@ -18,4 +21,5 @@ end
group :development do
gem "web-console", "~> 3.0"
+ gem "quiet_assets"
end
diff --git a/Gemfile.lock b/Gemfile.lock
index f05b7d5..0e0427f 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -46,10 +46,16 @@ GEM
minitest (~> 5.1)
tzinfo (~> 1.1)
arel (7.0.0)
+ autoprefixer-rails (6.2.3)
+ execjs
+ json
babel-source (5.8.34)
babel-transpiler (0.7.0)
babel-source (>= 4.0, < 6)
execjs (~> 2.0)
+ bootstrap-sass (3.3.6)
+ autoprefixer-rails (>= 5.2.1)
+ sass (>= 3.3.4)
builder (3.2.2)
byebug (8.2.1)
celluloid (0.17.2)
@@ -69,6 +75,8 @@ GEM
timers (>= 4.1.1)
celluloid-supervision (0.20.5)
timers (>= 4.1.1)
+ codemirror-rails (5.6)
+ railties (>= 3.0, < 5)
coffee-rails (4.1.1)
coffee-script (>= 2.2.0)
railties (>= 4.0.0, < 5.1.x)
@@ -93,6 +101,10 @@ GEM
hiredis (0.5.2)
hitimes (1.2.3)
i18n (0.7.0)
+ jquery-rails (4.0.5)
+ rails-dom-testing (~> 1.0)
+ railties (>= 4.2.0)
+ thor (>= 0.14, < 2.0)
json (1.8.3)
loofah (2.0.3)
nokogiri (>= 1.5.9)
@@ -105,7 +117,9 @@ GEM
mysql2 (0.4.2)
nokogiri (1.6.7.1)
mini_portile2 (~> 2.0.0.rc2)
- puma (2.15.3)
+ plum (0.2.8)
+ quiet_assets (1.1.0)
+ railties (>= 3.1, < 5.0)
rack (2.0.0.alpha)
json
rack-test (0.6.3)
@@ -138,6 +152,13 @@ GEM
thor (>= 0.18.1, < 2.0)
rake (10.4.2)
redis (3.2.2)
+ sass (3.4.20)
+ sass-rails (5.0.4)
+ railties (>= 4.0.0, < 5.0)
+ sass (~> 3.1)
+ sprockets (>= 2.8, < 4.0)
+ sprockets-rails (>= 2.0, < 4.0)
+ tilt (>= 1.1, < 3)
sidekiq (4.0.1)
concurrent-ruby (~> 1.0)
connection_pool (~> 2.2, >= 2.2.0)
@@ -158,10 +179,9 @@ GEM
sprockets (>= 3.0.0)
thor (0.19.1)
thread_safe (0.3.5)
+ tilt (2.0.1)
timers (4.1.1)
hitimes
- turbolinks (2.5.3)
- coffee-rails
tzinfo (1.2.2)
thread_safe (~> 0.1)
uglifier (2.7.2)
@@ -179,15 +199,19 @@ PLATFORMS
ruby
DEPENDENCIES
+ bootstrap-sass
byebug
+ codemirror-rails
+ jquery-rails
mysql2 (>= 0.3.18, < 0.5)
- puma
+ plum
+ quiet_assets
rails (>= 5.0.0.beta1, < 5.1)
+ sass-rails
sidekiq
sinatra
sprockets
sprockets-es6
- turbolinks
uglifier (>= 1.3.0)
web-console (~> 3.0)
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index b12018d..dfb23a2 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -12,5 +12,9 @@
//
//= require jquery
//= require jquery_ujs
-//= require turbolinks
+//= require bootstrap-sprockets
+//= require codemirror
+//= require codemirror/modes/ruby
+//= require codemirror/addons/edit/matchbrackets
+//= require codemirror/addons/edit/closebrackets
//= require_tree .
diff --git a/app/assets/javascripts/cable.coffee b/app/assets/javascripts/cable.coffee
deleted file mode 100644
index 49a7cfa..0000000
--- a/app/assets/javascripts/cable.coffee
+++ /dev/null
@@ -1,11 +0,0 @@
-# Action Cable provides the framework to deal with WebSockets in Rails.
-# You can generate new channels where WebSocket features live using the rails generate channel command.
-#
-# Turn on the cable connection by removing the comments after the require statements (and ensure it's also on in config/routes.rb).
-#
-#= require action_cable
-#= require_self
-#= require_tree ./channels
-#
-# @App ||= {}
-# App.cable = ActionCable.createConsumer()
diff --git a/app/assets/javascripts/channels/.keep b/app/assets/javascripts/channels/.keep
deleted file mode 100644
index e69de29..0000000
--- a/app/assets/javascripts/channels/.keep
+++ /dev/null
diff --git a/app/assets/javascripts/snippets.js b/app/assets/javascripts/results.es6
index dee720f..dee720f 100644
--- a/app/assets/javascripts/snippets.js
+++ b/app/assets/javascripts/results.es6
diff --git a/app/assets/javascripts/snippets.es6 b/app/assets/javascripts/snippets.es6
new file mode 100644
index 0000000..d3c3be1
--- /dev/null
+++ b/app/assets/javascripts/snippets.es6
@@ -0,0 +1,53 @@
+// Place all the behaviors and hooks related to the matching controller here.
+// All this logic will automatically be available in application.js.
+
+const codeField = document.querySelector("#code-field");
+if (codeField !== null) {
+ const origTextarea = codeField.querySelector("textarea[name=\"snippet[code]\"]");
+ const codeMirror = CodeMirror.fromTextArea(origTextarea, {
+ mode: "ruby",
+ lineNumbers: true,
+ });
+ codeMirror.on("change", cm => cm.save());
+}
+
+const agg = (elm, n) => {
+ if (!n) n = 0;
+ n++;
+ setTimeout(() => {
+ $.ajax({
+ type: "GET",
+ url: "/results/" + elm.getAttribute("data-id"),
+ dataType: "text",
+ success: (text, st) => {
+ console.log(text);
+ elm.outerHTML = text;
+ if (n < 3) agg(elm, n);
+ }
+ });
+ }, 1000);
+};
+
+const refresher = () => {
+ const runnings = document.querySelectorAll(".result-item[data-status=running]");
+ for (var i = 0, len = runnings.length; i < len; i++) {
+ agg(runnings[i]);
+ }
+};
+refresher();
+
+const notrans = document.querySelectorAll(".result-item[data-status=notran]");
+const snippet_id = document.querySelector("#snippet-id").innerHTML;
+for (var i = 0, len = notrans.length; i < len; i++) {
+ const elm = notrans[i];
+ $.ajax({
+ type: "POST",
+ url: "/results/run",
+ dataType: "text",
+ data: { compiler_id: elm.getAttribute("data-compiler-id"), snippet_id: snippet_id },
+ success: (text, st) => {
+ console.log(text);
+ elm.outerHTML = text;
+ }
+ });
+}
diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css
deleted file mode 100644
index 0ebd7fe..0000000
--- a/app/assets/stylesheets/application.css
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * This is a manifest file that'll be compiled into application.css, which will include all the files
- * listed below.
- *
- * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
- * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
- *
- * You're free to add application-wide styles to this file and they'll appear at the bottom of the
- * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
- * files in this directory. Styles in this file should be added after the last require_* statement.
- * It is generally better to create a new file per style scope.
- *
- *= require_tree .
- *= require_self
- */
diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss
new file mode 100644
index 0000000..37928eb
--- /dev/null
+++ b/app/assets/stylesheets/application.scss
@@ -0,0 +1,4 @@
+@import "bootstrap-sprockets";
+@import "bootstrap";
+@import "codemirror";
+@import "./*";
diff --git a/app/assets/stylesheets/results.scss b/app/assets/stylesheets/results.scss
new file mode 100644
index 0000000..07dafa5
--- /dev/null
+++ b/app/assets/stylesheets/results.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the results controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/app/assets/stylesheets/scaffold.css b/app/assets/stylesheets/scaffold.css
deleted file mode 100644
index 79f8b7f..0000000
--- a/app/assets/stylesheets/scaffold.css
+++ /dev/null
@@ -1,84 +0,0 @@
-body {
- background-color: #fff;
- color: #333;
-}
-
-body, p, ol, ul, td {
- font-family: verdana, arial, helvetica, sans-serif;
- font-size: 13px;
- line-height: 18px;
- margin: 33px;
-}
-
-pre {
- background-color: #eee;
- padding: 10px;
- font-size: 11px;
-}
-
-a {
- color: #000;
-}
-
-a:visited {
- color: #666;
-}
-
-a:hover {
- color: #fff;
- background-color: #000;
-}
-
-th {
- padding-bottom: 5px;
-}
-
-td {
- padding-bottom: 7px;
- padding-left: 5px;
- padding-right: 5px;
-}
-
-div.field,
-div.actions {
- margin-bottom: 10px;
-}
-
-#notice {
- color: green;
-}
-
-.field_with_errors {
- padding: 2px;
- background-color: red;
- display: table;
-}
-
-#error_explanation {
- width: 450px;
- border: 2px solid red;
- padding: 7px;
- padding-bottom: 0;
- margin-bottom: 20px;
- background-color: #f0f0f0;
-}
-
-#error_explanation h2 {
- text-align: left;
- font-weight: bold;
- padding: 5px 5px 5px 15px;
- font-size: 12px;
- margin: -7px;
- margin-bottom: 0;
- background-color: #c00;
- color: #fff;
-}
-
-#error_explanation ul li {
- font-size: 12px;
- list-style: square;
-}
-
-label {
- display: block;
-}
diff --git a/app/assets/stylesheets/snippets.css b/app/assets/stylesheets/snippets.scss
index afad32d..afad32d 100644
--- a/app/assets/stylesheets/snippets.css
+++ b/app/assets/stylesheets/snippets.scss
diff --git a/app/channels/application_cable/channel.rb b/app/channels/application_cable/channel.rb
deleted file mode 100644
index 438c841..0000000
--- a/app/channels/application_cable/channel.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-# Be sure to restart your server when you modify this file. Action Cable runs in an EventMachine loop that does not support auto reloading.
-module ApplicationCable
- class Channel < ActionCable::Channel::Base
- end
-end
diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb
deleted file mode 100644
index 965046f..0000000
--- a/app/channels/application_cable/connection.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-# Be sure to restart your server when you modify this file. Action Cable runs in an EventMachine loop that does not support auto reloading.
-module ApplicationCable
- class Connection < ActionCable::Connection::Base
- end
-end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index d83690e..607f101 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -2,4 +2,7 @@ class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
+
+ def not_found
+ end
end
diff --git a/app/controllers/results_controller.rb b/app/controllers/results_controller.rb
new file mode 100644
index 0000000..60ade5a
--- /dev/null
+++ b/app/controllers/results_controller.rb
@@ -0,0 +1,20 @@
+class ResultsController < ApplicationController
+ before_action :set_result, only: [:show]
+
+ def run
+ compiler = Compiler.find(params[:compiler_id])
+ snippet = Snippet.find(params[:snippet_id])
+ @result = compiler.run(snippet)
+
+ show
+ end
+
+ def show
+ render text: render_to_string(partial: "results/result", locals: { result: @result, compiler: @result.compiler }), content_type: "text/plain"
+ end
+
+ private
+ def set_result
+ @result = Result.find(params[:id])
+ end
+end
diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb
index 7d6f1b3..6fe26b1 100644
--- a/app/controllers/snippets_controller.rb
+++ b/app/controllers/snippets_controller.rb
@@ -1,12 +1,6 @@
class SnippetsController < ApplicationController
before_action :set_snippet, only: [:show]
- # GET /snippets
- # TODO
- # def index
- # @snippets = Snippet.all
- # end
-
# GET /1234
def show
end
@@ -16,11 +10,6 @@ class SnippetsController < ApplicationController
@snippet = Snippet.new
end
- # GET /snippets/1/edit
- # TODO
- # def edit
- # end
-
# POST /create
def create
@snippet = Snippet.new(snippet_params)
@@ -32,23 +21,6 @@ class SnippetsController < ApplicationController
end
end
- # PATCH/PUT /snippets/1
- # TODO
- # def update
- # if @snippet.update(snippet_params)
- # redirect_to @snippet, notice: "Snippet was successfully updated."
- # else
- # render :edit
- # end
- # end
-
- # DELETE /snippets/1
- # TODO
- # def destroy
- # @snippet.destroy
- # redirect_to snippets_url, notice: "Snippet was successfully destroyed."
- # end
-
private
# Use callbacks to share common setup or constraints between actions.
def set_snippet
@@ -57,6 +29,6 @@ class SnippetsController < ApplicationController
# Only allow a trusted parameter "white list" through.
def snippet_params
- params.require(:snippet).permit(:title, :code)
+ params.require(:snippet).permit(:title, :code, :language)
end
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index de6be79..2394f77 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -1,2 +1,5 @@
module ApplicationHelper
+ def application_name
+ Rails.application.class.to_s.split("::").first
+ end
end
diff --git a/app/helpers/results_helper.rb b/app/helpers/results_helper.rb
new file mode 100644
index 0000000..c3fd7a5
--- /dev/null
+++ b/app/helpers/results_helper.rb
@@ -0,0 +1,2 @@
+module ResultsHelper
+end
diff --git a/app/jobs/execute_job.rb b/app/jobs/execute_job.rb
index f5dd436..1d05aba 100644
--- a/app/jobs/execute_job.rb
+++ b/app/jobs/execute_job.rb
@@ -1,7 +1,11 @@
class ExecuteJob < ApplicationJob
queue_as :default
- def perform(compiler, snippet)
- compiler.run! snippet
+ def perform(compiler, snippet, result = nil)
+ if result
+ compiler.run_body(snippet, result)
+ else
+ compiler.run(snippet)
+ end
end
end
diff --git a/app/models/compiler.rb b/app/models/compiler.rb
index 7cf7152..c25bf2e 100644
--- a/app/models/compiler.rb
+++ b/app/models/compiler.rb
@@ -1,19 +1,51 @@
+require "shellwords"
+
class Compiler < ApplicationRecord
- def _run!(snippet)
- raise NotImplementedError
+ def to_s
+ "#{language} #{version}"
+ end
+
+ def run_lazy(snippet)
+ r = Result.prepare_execution(self, snippet)
+ ExecuteJob.perform_later(self, snippet, r)
+ r
end
- if Rails.env.development?
- require "shellwords"
- def run!(snippet)
- if self.language == "ruby" && self.version == "!!unsafe!!"
- out = `ruby -e #{Shellwords.escape(snippet.code)}`
- Result.create(snippet: snippet, compiler: self, output: out)
- else
- _run!(snippet)
- end
+ def run(snippet)
+ r = Result.prepare_execution(self, snippet)
+ run_body(snippet, r)
+ r
+ end
+
+ private
+ def run_body(snippet, r)
+ baseroot = Rails.root.join("playground/base").to_s
+ env_overlay = Rails.root.join("playground").join(language).join(version).to_s
+ sf = Tempfile.open
+ sf.write(snippet.code)
+ sf.fsync
+ of = Tempfile.open
+ pid = spawn("/usr/bin/sudo", Rails.root.join("sandbox/sandbox").to_s, baseroot, env_overlay, sf.path, *Shellwords.split(command_line),
+ in: :close, # TODO
+ out: of,
+ err: STDERR)
+ _, pst = Process.waitpid2(pid)
+ if pst.signaled? || pst.exitstatus > 0
+ result = :errored
+ status = -1
+ else
+ result = :success
+ status = 0
end
- else
- alias run! _run!
+
+ of.rewind
+ r.update!(output: of.read,
+ status: status,
+ result: result)
+ rescue
+ r.update!(status: -1, result: :errored)
+ ensure
+ sf.close if sf
+ of.close if of
end
end
diff --git a/app/models/result.rb b/app/models/result.rb
index 8ca10e2..1bbdb29 100644
--- a/app/models/result.rb
+++ b/app/models/result.rb
@@ -1,4 +1,44 @@
+require "cgi"
+
class Result < ApplicationRecord
belongs_to :snippet
belongs_to :compiler
+
+ enum result: [:success, :failed, :errored, :running]
+
+ def finished?
+ !running?
+ end
+
+ def parse_output
+ orig = output.b
+ ret = []
+ while orig.bytesize > 0
+ fd, len = orig.slice!(0, 5).unpack("CV")
+ raise "output is too short" if !len || orig.bytesize < len
+ ret << [fd, orig.slice!(0, len)]
+ end
+ ret
+ end
+
+ def formatted_output
+ parse_output.inject("".b) { |s, (fd, c)|
+ if fd == 1
+ s << CGI.escapeHTML(c)
+ else
+ s << "<span style='color: red'>" << CGI.escapeHTML(c) << "</span>"
+ end
+ }.html_safe
+ end
+
+ def self.prepare_execution(compiler, snippet)
+ # kuso
+ r = Result.find_by(snippet: snippet, compiler: compiler)
+ if r
+ r.update(output: "", status: -1, result: :running)
+ else
+ r = Result.create!(snippet: snippet, compiler: compiler, output: "", status: -1, result: :running)
+ end
+ r
+ end
end
diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index 5412492..a55b732 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -1,4 +1,14 @@
class Snippet < ApplicationRecord
- has_many :result
- has_many :compiler
+ has_many :results
+
+ validates :code, length: { maximum: 65535, tokenizer: :bytes.to_proc }
+
+ def compilers
+ Compiler.where(language: language)
+ end
+
+ def results_all
+ r = results.map { |r| [r.compiler_id, r] }.to_h
+ compilers.map { |c| [r[c.id], c] }
+ end
end
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
index 5d5a9c0..fd1d40c 100644
--- a/app/views/layouts/application.html.erb
+++ b/app/views/layouts/application.html.erb
@@ -1,15 +1,24 @@
<!DOCTYPE html>
-<html>
+<html lang="ja">
<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
<title>Poe</title>
<%= csrf_meta_tags %>
- <%= action_cable_meta_tag %>
-
- <%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
- <%= javascript_include_tag "application", "data-turbolinks-track" => true %>
+ <%= stylesheet_link_tag "application", media: "all" %>
</head>
<body>
- <%= yield %>
+ <nav class="navbar navbar-default navbar-static-top">
+ <div class="container-fluid">
+ <div class="navbar-header">
+ <a class="navbar-brand" href="/"><%= application_name %></a>
+ </div>
+ </div>
+ </nav>
+ <div class="container-fluid">
+ <%= yield %>
+ </div>
+ <%= javascript_include_tag "application" %>
</body>
</html>
diff --git a/app/views/results/_result.html.erb b/app/views/results/_result.html.erb
new file mode 100644
index 0000000..fd59416
--- /dev/null
+++ b/app/views/results/_result.html.erb
@@ -0,0 +1,16 @@
+<% if result && result.finished? %>
+ <div class="result-item panel <%= result.success? ? "panel-success" : "panel-danger" %>" data-id="<%= result.id %>">
+ <div class="panel-heading"><%= compiler %></div>
+ <div class="panel-body">
+ <pre><code><%= result.formatted_output %></code></pre>
+ </div>
+ </div>
+<% else %>
+ <div class="result-item panel panel-default" data-status="<%= result ? "running" : "notran" %>" data-id="<%= result&.id %>" data-compiler-id="<%= compiler.id %>">
+ <div class="panel-heading"><%= compiler %></div>
+ <div class="panel-body">
+ <p>running....</p>
+ </div>
+ </div>
+<% end %>
+
diff --git a/app/views/snippets/_form.html.erb b/app/views/snippets/_form.html.erb
index 1c37b00..8b21b3d 100644
--- a/app/views/snippets/_form.html.erb
+++ b/app/views/snippets/_form.html.erb
@@ -1,27 +1,26 @@
-<%= form_for(snippet) do |f| %>
- <% if snippet.errors.any? %>
- <div id="error_explanation">
- <h2><%= pluralize(snippet.errors.count, "error") %> prohibited this snippet from being saved:</h2>
+<div class="panel panel-default">
+ <div class="panel-body">
+ <%= form_for(snippet, url: "/", html: { method: "post" }) do |f| %>
+ <% if snippet.errors.any? %>
+ <div class="alert alert-danger" role="alert">
+ <p><%= pluralize(snippet.errors.count, "error") %> prohibited this snippet from being saved:</p>
- <ul>
- <% snippet.errors.full_messages.each do |message| %>
- <li><%= message %></li>
+ <ul>
+ <% snippet.errors.full_messages.each do |message| %>
+ <li><%= message %></li>
+ <% end %>
+ </ul>
+ </div>
<% end %>
- </ul>
- </div>
- <% end %>
- <div class="field">
- <%= f.label :title %>
- <%= f.text_field :title %>
+ <div class="form-group">
+ <%= f.text_field :title, placeholder: "Untitled", class: "form-control" %>
+ </div>
+ <div class="form-group" id="code-field">
+ <%= f.text_area :code, style: "display: none" %>
+ </div>
+ <%= f.hidden_field :language, value: "Ruby" %>
+ <button type="submit" class="btn btn-default">Run</button>
+ <% end %>
</div>
-
- <div class="field">
- <%= f.label :code %>
- <%= f.text_area :code %>
- </div>
-
- <div class="actions">
- <%= f.submit %>
- </div>
-<% end %>
+</div>
diff --git a/app/views/snippets/edit.html.erb b/app/views/snippets/edit.html.erb
deleted file mode 100644
index c27040f..0000000
--- a/app/views/snippets/edit.html.erb
+++ /dev/null
@@ -1,6 +0,0 @@
-<h1>Editing Snippet</h1>
-
-<%= render 'form', snippet: @snippet %>
-
-<%= link_to 'Show', @snippet %> |
-<%= link_to 'Back', snippets_path %>
diff --git a/app/views/snippets/index.html.erb b/app/views/snippets/index.html.erb
deleted file mode 100644
index 601ba13..0000000
--- a/app/views/snippets/index.html.erb
+++ /dev/null
@@ -1,29 +0,0 @@
-<p id="notice"><%= notice %></p>
-
-<h1>Snippets</h1>
-
-<table>
- <thead>
- <tr>
- <th>Title</th>
- <th>Code</th>
- <th colspan="3"></th>
- </tr>
- </thead>
-
- <tbody>
- <% @snippets.each do |snippet| %>
- <tr>
- <td><%= snippet.title %></td>
- <td><%= snippet.code %></td>
- <td><%= link_to 'Show', snippet %></td>
- <td><%= link_to 'Edit', edit_snippet_path(snippet) %></td>
- <td><%= link_to 'Destroy', snippet, method: :delete, data: { confirm: 'Are you sure?' } %></td>
- </tr>
- <% end %>
- </tbody>
-</table>
-
-<br>
-
-<%= link_to 'New Snippet', new_snippet_path %>
diff --git a/app/views/snippets/new.html.erb b/app/views/snippets/new.html.erb
index 0a9ebaf..2d2567d 100644
--- a/app/views/snippets/new.html.erb
+++ b/app/views/snippets/new.html.erb
@@ -1,5 +1 @@
-<h1>New Snippet</h1>
-
-<%= render 'form', snippet: @snippet %>
-
-<%= link_to 'Back', snippets_path %>
+<%= render "form", snippet: @snippet %>
diff --git a/app/views/snippets/show.html.erb b/app/views/snippets/show.html.erb
index 9e59d7a..e2a1566 100644
--- a/app/views/snippets/show.html.erb
+++ b/app/views/snippets/show.html.erb
@@ -1,14 +1,6 @@
-<p id="notice"><%= notice %></p>
+<%= render "form", snippet: @snippet %>
+<span style="display: none" id="snippet-id"><%= @snippet.id %></span>
-<p>
- <strong>Title:</strong>
- <%= @snippet.title %>
-</p>
-
-<p>
- <strong>Code:</strong>
- <%= @snippet.code %>
-</p>
-
-<%= link_to 'Edit', edit_snippet_path(@snippet) %> |
-<%= link_to 'Back', snippets_path %>
+<% @snippet.results_all.each do |result, compiler| %>
+ <%= render partial: "results/result", locals: { result: result, compiler: compiler } %>
+<% end %>
diff --git a/config.ru b/config.ru
index c634fa4..33d9cb1 100644
--- a/config.ru
+++ b/config.ru
@@ -2,8 +2,4 @@
require ::File.expand_path("../config/environment", __FILE__)
-# Action Cable uses EventMachine which requires that all classes are loaded in advance
-Rails.application.eager_load!
-require "action_cable/process/logging"
-
run Rails.application
diff --git a/config/application.rb b/config/application.rb
index 4dc52f9..f41dc96 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -8,7 +8,7 @@ require "active_record/railtie"
require "action_controller/railtie"
# require "action_mailer/railtie"
require "action_view/railtie"
-require "action_cable/engine"
+# require "action_cable/engine"
require "sprockets/railtie"
# require "rails/test_unit/railtie"
diff --git a/config/routes.rb b/config/routes.rb
index 19d6a03..b547a66 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,15 +1,22 @@
Rails.application.routes.draw do
- resources :snippets
- # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
+ resources :snippets, only: [:new, :create, :update, :show], path: "", path_names: {
+ new: "",
+ create: "create",
+ update: ":id",
+ show: ":id"
+ }
+
+ post "results/run" => "results#run"
+ get "results/:id" => "results#show"
# Serve websocket cable requests in-process
# mount ActionCable.server => "/cable"
- root to: "snippets#new"
+ #root to: "snippets#new"
- post "/create" => "snippets#create"
- put "/update" => "snippets#update"
- get "/:id" => "snippets#show", constraints: { id: /[1-9][0-9]*/ }
+ #post "/create" => "snippets#create"
+ #put "/update" => "snippets#update"
+ #get "/:id" => "snippets#show", constraints: { id: /[1-9][0-9]*/ }
match "*any" => "application#not_found", via: :all
end
diff --git a/db/migrate/20160101024323_extend_result.rb b/db/migrate/20160101024323_extend_result.rb
new file mode 100644
index 0000000..7c04f69
--- /dev/null
+++ b/db/migrate/20160101024323_extend_result.rb
@@ -0,0 +1,6 @@
+class ExtendResult < ActiveRecord::Migration[5.0]
+ def change
+ add_column :results, :result, :integer, null: false
+ add_column :results, :status, :integer, null: false
+ end
+end
diff --git a/db/migrate/20160101060555_add_command_line_to_compilers.rb b/db/migrate/20160101060555_add_command_line_to_compilers.rb
new file mode 100644
index 0000000..215855d
--- /dev/null
+++ b/db/migrate/20160101060555_add_command_line_to_compilers.rb
@@ -0,0 +1,5 @@
+class AddCommandLineToCompilers < ActiveRecord::Migration[5.0]
+ def change
+ add_column :compilers, :command_line, :string, null: false
+ end
+end
diff --git a/db/migrate/20160101121151_add_language_to_snippet.rb b/db/migrate/20160101121151_add_language_to_snippet.rb
new file mode 100644
index 0000000..d3fe545
--- /dev/null
+++ b/db/migrate/20160101121151_add_language_to_snippet.rb
@@ -0,0 +1,5 @@
+class AddLanguageToSnippet < ActiveRecord::Migration[5.0]
+ def change
+ add_column :snippets, :language, :string, null: false
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 5812893..f60b7ab 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,13 +11,14 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20151226120716) do
+ActiveRecord::Schema.define(version: 20160101121151) do
create_table "compilers", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4" do |t|
- t.string "language", limit: 64, null: false
- t.string "version", limit: 64, null: false
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
+ t.string "language", limit: 64, null: false
+ t.string "version", limit: 64, null: false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.string "command_line", null: false
t.index ["language", "version"], name: "index_compilers_on_language_and_version", unique: true, using: :btree
end
@@ -26,6 +27,8 @@ ActiveRecord::Schema.define(version: 20151226120716) do
t.integer "compiler_id", null: false
t.binary "output", limit: 65535, null: false
t.datetime "created_at", null: false
+ t.integer "result", null: false
+ t.integer "status", null: false
t.index ["compiler_id"], name: "index_results_on_compiler_id", using: :btree
t.index ["snippet_id", "compiler_id"], name: "index_results_on_snippet_id_and_compiler_id", unique: true, using: :btree
t.index ["snippet_id"], name: "index_results_on_snippet_id", using: :btree
@@ -35,6 +38,7 @@ ActiveRecord::Schema.define(version: 20151226120716) do
t.string "title"
t.binary "code", limit: 65535, null: false
t.datetime "created_at", null: false
+ t.string "language", null: false
end
add_foreign_key "results", "compilers"
diff --git a/db/seeds.rb b/db/seeds.rb
index f16f4fa..cfadd24 100644
--- a/db/seeds.rb
+++ b/db/seeds.rb
@@ -5,8 +5,3 @@
#
# movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }])
# Character.create(name: 'Luke', movie: movies.first)
-
-if Rails.env.development?
- # just eval
- Compiler.create(language: "ruby", version: "!!unsafe!!")
-end