├── .gitignore ├── Gemfile ├── MIT-LICENSE ├── README.md ├── Rakefile ├── app ├── assets │ ├── images │ │ ├── dir_icon.png │ │ ├── file_icon.png │ │ └── rails.png │ ├── javascripts │ │ ├── conductor.js │ │ └── conductor │ │ │ ├── codes.js │ │ │ ├── databases.js │ │ │ ├── db_task.js │ │ │ ├── editor.js │ │ │ ├── generators.js │ │ │ ├── index_code.js │ │ │ ├── installgems.js │ │ │ ├── recorder.js.erb │ │ │ ├── rollback.js │ │ │ └── tests.js │ └── stylesheets │ │ ├── conductor.css.erb │ │ └── conductor │ │ ├── annotations.css │ │ ├── code.css.erb │ │ ├── editor.css │ │ ├── recorder.css │ │ └── statistics.css ├── controllers │ └── conductor │ │ ├── annotations_controller.rb │ │ ├── app_controllers_controller.rb │ │ ├── application_controller.rb │ │ ├── codes_controller.rb │ │ ├── databases_controller.rb │ │ ├── editor_controller.rb │ │ ├── gemfiles_controller.rb │ │ ├── mailers_controller.rb │ │ ├── migrations_controller.rb │ │ ├── models_controller.rb │ │ ├── recorder_controller.rb │ │ ├── resources_controller.rb │ │ ├── routes_controller.rb │ │ ├── scaffolds_controller.rb │ │ ├── statistics_controller.rb │ │ ├── tests_controller.rb │ │ └── welcome_controller.rb ├── forms │ └── conductor │ │ ├── base_generator_form.rb │ │ ├── controller_generator_form.rb │ │ ├── mailer_generator_form.rb │ │ ├── model_generator_form.rb │ │ ├── resource_generator_form.rb │ │ └── scaffold_generator_form.rb ├── helpers │ └── conductor │ │ ├── application_helper.rb │ │ ├── routes_helper.rb │ │ └── scaffolds_helper.rb ├── models │ └── conductor │ │ ├── code.rb │ │ ├── code_statistics.rb │ │ ├── database.rb │ │ ├── migrations.rb │ │ └── scaffold.rb └── views │ ├── conductor │ ├── annotations │ │ └── index.html.erb │ ├── app_controllers │ │ └── new.html.erb │ ├── codes │ │ ├── edit.html.erb │ │ └── index.html.erb │ ├── databases │ │ ├── output.html.erb │ │ ├── output_no_websocket.html.erb │ │ └── show.html.erb │ ├── editor │ │ ├── _editor.html.erb │ │ ├── index.js.erb │ │ └── save.js.erb │ ├── gemfiles │ │ ├── install.html.erb │ │ └── install_no_websocket.html.erb │ ├── mailers │ │ └── new.html.erb │ ├── migrations │ │ ├── index.html.erb │ │ └── rollback.html.erb │ ├── models │ │ └── new.html.erb │ ├── recorder │ │ ├── destroy.js.erb │ │ └── index.js.erb │ ├── resources │ │ └── new.html.erb │ ├── routes │ │ └── index.html.erb │ ├── scaffolds │ │ └── new.html.erb │ ├── statistics │ │ └── index.html.erb │ ├── tests │ │ ├── show.html.erb │ │ └── show_no_websocket.html.erb │ └── welcome │ │ └── index.html.erb │ └── layouts │ └── conductor │ └── application.html.erb ├── bin └── rails ├── conductor.gemspec ├── config └── routes.rb ├── lib ├── assets │ └── javascripts │ │ └── recorder.js.erb ├── conductor.rb └── conductor │ ├── config.rb │ ├── engine.rb │ ├── filter.rb │ ├── middleware.rb │ ├── middleware_util.rb │ └── version.rb ├── log └── .gitignore ├── test ├── conductor_test.rb ├── controllers │ └── conductor │ │ ├── databases_controller_test.rb │ │ ├── fixtures_controller_test.rb │ │ ├── gemfile_controller_test.rb │ │ ├── test_controller_test.rb │ │ └── welcome_controller_test.rb ├── dummy │ ├── Gemfile │ ├── README.rdoc │ ├── Rakefile │ ├── app │ │ ├── assets │ │ │ ├── images │ │ │ │ └── .keep │ │ │ ├── javascripts │ │ │ │ ├── application.js │ │ │ │ ├── posts.js │ │ │ │ └── usuarios.js │ │ │ └── stylesheets │ │ │ │ ├── application.css │ │ │ │ ├── posts.css │ │ │ │ ├── scaffold.css │ │ │ │ └── usuarios.css │ │ ├── controllers │ │ │ ├── application_controller.rb │ │ │ ├── concerns │ │ │ │ └── .keep │ │ │ ├── posts_controller.rb │ │ │ └── usuarios_controller.rb │ │ ├── helpers │ │ │ ├── application_helper.rb │ │ │ ├── posts_helper.rb │ │ │ └── usuarios_helper.rb │ │ ├── mailers │ │ │ ├── .keep │ │ │ └── person.rb │ │ ├── models │ │ │ ├── .keep │ │ │ ├── concerns │ │ │ │ └── .keep │ │ │ └── user.rb │ │ └── views │ │ │ ├── layouts │ │ │ └── application.html.erb │ │ │ ├── person │ │ │ └── name.text.erb │ │ │ ├── posts │ │ │ ├── _form.html.erb │ │ │ ├── edit.html.erb │ │ │ ├── index.html.erb │ │ │ ├── new.html.erb │ │ │ └── show.html.erb │ │ │ └── usuarios │ │ │ ├── _form.html.erb │ │ │ ├── edit.html.erb │ │ │ ├── index.html.erb │ │ │ ├── new.html.erb │ │ │ └── show.html.erb │ ├── bin │ │ ├── bundle │ │ ├── rails │ │ └── rake │ ├── config.ru │ ├── config │ │ ├── application.rb │ │ ├── boot.rb │ │ ├── database.yml │ │ ├── environment.rb │ │ ├── environments │ │ │ ├── development.rb │ │ │ ├── production.rb │ │ │ └── test.rb │ │ ├── initializers │ │ │ ├── backtrace_silencers.rb │ │ │ ├── filter_parameter_logging.rb │ │ │ ├── inflections.rb │ │ │ ├── mime_types.rb │ │ │ ├── secret_token.rb │ │ │ ├── session_store.rb │ │ │ └── wrap_parameters.rb │ │ ├── locales │ │ │ └── en.yml │ │ └── routes.rb │ ├── db │ │ ├── .gitkeep │ │ ├── migrate │ │ │ └── 20130827165249_create_users.rb │ │ └── schema.rb │ ├── lib │ │ └── assets │ │ │ └── .keep │ ├── log │ │ └── .keep │ ├── public │ │ ├── 404.html │ │ ├── 422.html │ │ ├── 500.html │ │ └── favicon.ico │ └── test │ │ └── fixtures │ │ └── users.yml ├── helpers │ └── conductor │ │ ├── test_helper_test.rb │ │ └── welcome_helper_test.rb ├── integration │ └── navigation_test.rb ├── models │ ├── code_statistics_test.rb │ ├── database_test.rb │ └── migrations_test.rb └── test_helper.rb └── vendor └── assets ├── javascripts └── ace │ ├── ace.js │ ├── ext-modelist.js │ ├── mode-coffee.js │ ├── mode-css.js │ ├── mode-haml.js │ ├── mode-html.js │ ├── mode-html_completions.js │ ├── mode-html_ruby.js │ ├── mode-javascript.js │ ├── mode-json.js │ ├── mode-ruby.js │ ├── mode-sass.js │ ├── mode-scss.js │ ├── mode-yaml.js │ └── theme-textmate.js └── stylesheets └── github.css /.gitignore: -------------------------------------------------------------------------------- 1 | .bundle/ 2 | Gemfile.lock 3 | pkg/ 4 | test/dummy/db/*.sqlite3 5 | test/dummy/db/*.sqlite3-journal 6 | test/dummy/log/*.log 7 | test/dummy/tmp/ 8 | test/dummy/.sass-cache 9 | .ruby-version 10 | .ruby-gemset 11 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | # Declare your gem's dependencies in conductor.gemspec. 4 | # Bundler will treat runtime dependencies like base dependencies, and 5 | # development dependencies will be added by default to the :development group. 6 | gemspec 7 | 8 | # Declare any dependencies that are still in development here instead of in 9 | # your gemspec. These might include edge Rails or gems from your path or 10 | # Git. Remember to move these dependencies to your gemspec before releasing 11 | # your gem to rubygems.org. 12 | 13 | # To use debugger 14 | # gem 'debugger' 15 | 16 | gem 'sdoc', require: false 17 | -------------------------------------------------------------------------------- /MIT-LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2013 YOURNAME 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Conductor 2 | 3 | Conductor is a Rails engine that lets you do through a web UI what you'd normally do with the rails shell command. 4 | 5 | ## Installation & Setup 6 | 7 | To install add the following line to the Gemfile in your Rails application : 8 | 9 | ```ruby 10 | group :development do 11 | gem 'conductor', github: 'rails/conductor' 12 | end 13 | ``` 14 | 15 | Conductor can now be accessed at /conductor when you're running off local host. 16 | 17 | ## Contributing 18 | 19 | 1. Fork it 20 | 2. Create your feature branch (`git checkout -b my-new-feature`) 21 | 3. Commit your changes (`git commit -am 'Add some feature'`) 22 | 4. Push to the branch (`git push origin my-new-feature`) 23 | 5. Create new Pull Request 24 | 25 | ## License 26 | 27 | Copyright © David Heinemeier Hansson 28 | 29 | Released under the [MIT License](http://www.opensource.org/licenses/MIT) 30 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env rake 2 | begin 3 | require 'bundler/setup' 4 | rescue LoadError 5 | puts 'You must `gem install bundler` and `bundle install` to run rake tasks' 6 | end 7 | begin 8 | require 'rdoc/task' 9 | rescue LoadError 10 | require 'rdoc/rdoc' 11 | require 'rake/rdoctask' 12 | RDoc::Task = Rake::RDocTask 13 | end 14 | 15 | RDoc::Task.new(:rdoc) do |rdoc| 16 | rdoc.rdoc_dir = 'rdoc' 17 | rdoc.title = 'Conductor' 18 | rdoc.options << '--line-numbers' 19 | rdoc.rdoc_files.include('README.rdoc') 20 | rdoc.rdoc_files.include('lib/**/*.rb') 21 | end 22 | 23 | APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__) 24 | load 'rails/tasks/engine.rake' 25 | 26 | 27 | 28 | Bundler::GemHelper.install_tasks 29 | 30 | require 'rake/testtask' 31 | 32 | Rake::TestTask.new(:test) do |t| 33 | t.libs << 'lib' 34 | t.libs << 'test' 35 | t.pattern = 'test/**/*_test.rb' 36 | t.verbose = false 37 | end 38 | 39 | 40 | task :default => :test 41 | -------------------------------------------------------------------------------- /app/assets/images/dir_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rails/conductor/03e46dd24116d7f3525d3e3445c44f98c004451b/app/assets/images/dir_icon.png -------------------------------------------------------------------------------- /app/assets/images/file_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rails/conductor/03e46dd24116d7f3525d3e3445c44f98c004451b/app/assets/images/file_icon.png -------------------------------------------------------------------------------- /app/assets/images/rails.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rails/conductor/03e46dd24116d7f3525d3e3445c44f98c004451b/app/assets/images/rails.png -------------------------------------------------------------------------------- /app/assets/javascripts/conductor.js: -------------------------------------------------------------------------------- 1 | //= require 'jquery' 2 | //= require 'jquery_ujs' -------------------------------------------------------------------------------- /app/assets/javascripts/conductor/codes.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function(){ 2 | var editor = ace.edit("editor"); 3 | var textarea = $('#code_content'); 4 | textarea.hide(); 5 | var filePath = $('#code_path').val(); 6 | var modelist = ace.require('ace/ext/modelist'); 7 | var mode = modelist.getModeForPath(filePath).mode; 8 | editor.setTheme("ace/theme/textmate"); 9 | editor.getSession().setMode(mode); 10 | editor.getSession().setValue(textarea.val()); 11 | editor.getSession().on('change', function(){ 12 | textarea.val(editor.getSession().getValue()); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /app/assets/javascripts/conductor/databases.js: -------------------------------------------------------------------------------- 1 | // Place all the behaviors and hooks related to the matching controller here. 2 | // All this logic will automatically be available in application.js. 3 | $(document).ready(function(){ 4 | var editor = ace.edit("editor"); 5 | var textarea = $('#database_content'); 6 | textarea.hide(); 7 | editor.setTheme("ace/theme/textmate"); 8 | editor.getSession().setMode("ace/mode/yaml"); 9 | editor.getSession().setValue(textarea.val()); 10 | editor.getSession().on('change', function(){ 11 | textarea.val(editor.getSession().getValue()); 12 | }); 13 | }); 14 | 15 | -------------------------------------------------------------------------------- /app/assets/javascripts/conductor/db_task.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function(){ 2 | var ws = new WebSocket("ws://" + location.host + "/conductor/database/websocket_database"); 3 | var editor = ace.edit("editor"); 4 | editor.renderer.setShowGutter(false); 5 | editor.setReadOnly(true); 6 | ws.onmessage = function(e) { 7 | editor.insert(e.data + "\n"); }; 8 | editor.setTheme("ace/theme/textmate"); 9 | editor.getSession().setMode("ace/mode/ruby"); 10 | }); -------------------------------------------------------------------------------- /app/assets/javascripts/conductor/editor.js: -------------------------------------------------------------------------------- 1 | //= require 'ace/ace' 2 | //= require 'ace/ext-modelist' 3 | //= require 'ace/theme-textmate' -------------------------------------------------------------------------------- /app/assets/javascripts/conductor/generators.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function(){ 2 | 3 | var tableBody = $('#fieldsTable tbody'); 4 | var trContent = $('.field').html(); 5 | 6 | $('#addField').click(function() { 7 | tableBody.append(""+trContent+""); 8 | return false; 9 | }); 10 | 11 | }) 12 | -------------------------------------------------------------------------------- /app/assets/javascripts/conductor/index_code.js: -------------------------------------------------------------------------------- 1 | $('#new_file').click(function(e) { 2 | $('#new_file_form').toggle(); 3 | }); -------------------------------------------------------------------------------- /app/assets/javascripts/conductor/installgems.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function(){ 2 | var ws = new WebSocket("ws://" + location.host + "/conductor/gemfile/check_install"); 3 | var editor = ace.edit("editor"); 4 | editor.renderer.setShowGutter(false); 5 | editor.setReadOnly(true); 6 | ws.onmessage = function(e) { 7 | editor.insert(e.data + "\n"); }; 8 | editor.setTheme("ace/theme/textmate"); 9 | editor.getSession().setMode("ace/mode/ruby"); 10 | }); -------------------------------------------------------------------------------- /app/assets/javascripts/conductor/recorder.js.erb: -------------------------------------------------------------------------------- 1 | $(document).on('submit', 'form', function() { 2 | var scenario = [" scenario 'GENERATED' do"]; 3 | scenario.push(" visit '" + window.location.pathname + "'"); 4 | $(this).find('input[type=text],input[type=email],input[type=url],input[type=number],input[type=search],textarea').each(function() { 5 | scenario.push(" fill_in '" + $(this).attr('id') + "', :with => '" + $(this).val() + "'"); 6 | }); 7 | $(this).find('select').each(function() { 8 | scenario.push(" select '" + $(this).children(':selected').text() + "', :from => '" + $(this).attr('id') + "'"); 9 | }); 10 | scenario.push(" click_button '" + $(this).find('input[type=submit]').val() + "'"); 11 | $(this).append('