Permalink
Browse files

first commit

  • Loading branch information...
0 parents commit 5e2b5094241ec5e414c6703fd40c6bf61733bf34 @lazylester committed Mar 12, 2013
Showing with 1,358 additions and 0 deletions.
  1. +8 −0 .gitignore
  2. +1 −0 .rspec
  3. +1 −0 .rvmrc
  4. +17 −0 Gemfile
  5. +126 −0 Gemfile.lock
  6. +20 −0 MIT-LICENSE
  7. +22 −0 README.rdoc
  8. +27 −0 Rakefile
  9. 0 app/assets/images/get_back/.gitkeep
  10. +15 −0 app/assets/javascripts/get_back/application.js
  11. +13 −0 app/assets/stylesheets/get_back/application.css
  12. +5 −0 app/controllers/get_back/application_controller.rb
  13. +80 −0 app/controllers/get_back/backups_controller.rb
  14. +4 −0 app/helpers/get_back/application_helper.rb
  15. +32 −0 app/models/application_database.rb
  16. +105 −0 app/models/backup_file.rb
  17. +9 −0 app/models/backup_mailer.rb
  18. +1 −0 app/views/get_back/backup_mailer/backup_file.html.erb
  19. +36 −0 app/views/get_back/backups/index.html.haml
  20. +2 −0 app/views/layouts/get_back/application.html.haml
  21. +3 −0 config/initializers/time_formats.rb
  22. +5 −0 config/routes.rb
  23. +24 −0 get_back.gemspec
  24. +4 −0 lib/get_back.rb
  25. +5 −0 lib/get_back/engine.rb
  26. +3 −0 lib/get_back/version.rb
  27. +20 −0 lib/tasks/backup.rake
  28. +6 −0 lib/tasks/email_backup.rake
  29. +4 −0 lib/tasks/get_back_tasks.rake
  30. +8 −0 script/rails
  31. +261 −0 spec/dummy/README.rdoc
  32. +7 −0 spec/dummy/Rakefile
  33. +15 −0 spec/dummy/app/assets/javascripts/application.js
  34. +13 −0 spec/dummy/app/assets/stylesheets/application.css
  35. +3 −0 spec/dummy/app/controllers/application_controller.rb
  36. +2 −0 spec/dummy/app/helpers/application_helper.rb
  37. 0 spec/dummy/app/mailers/.gitkeep
  38. 0 spec/dummy/app/models/.gitkeep
  39. +14 −0 spec/dummy/app/views/layouts/application.html.erb
  40. +4 −0 spec/dummy/config.ru
  41. +65 −0 spec/dummy/config/application.rb
  42. +10 −0 spec/dummy/config/boot.rb
  43. +7 −0 spec/dummy/config/database.yml
  44. +5 −0 spec/dummy/config/environment.rb
  45. +37 −0 spec/dummy/config/environments/development.rb
  46. +67 −0 spec/dummy/config/environments/production.rb
  47. +37 −0 spec/dummy/config/environments/test.rb
  48. +7 −0 spec/dummy/config/initializers/backtrace_silencers.rb
  49. +15 −0 spec/dummy/config/initializers/inflections.rb
  50. +5 −0 spec/dummy/config/initializers/mime_types.rb
  51. +7 −0 spec/dummy/config/initializers/secret_token.rb
  52. +8 −0 spec/dummy/config/initializers/session_store.rb
  53. +14 −0 spec/dummy/config/initializers/wrap_parameters.rb
  54. +5 −0 spec/dummy/config/locales/en.yml
  55. +4 −0 spec/dummy/config/routes.rb
  56. 0 spec/dummy/lib/assets/.gitkeep
  57. 0 spec/dummy/log/.gitkeep
  58. +26 −0 spec/dummy/public/404.html
  59. +26 −0 spec/dummy/public/422.html
  60. +25 −0 spec/dummy/public/500.html
  61. 0 spec/dummy/public/favicon.ico
  62. +6 −0 spec/dummy/script/rails
  63. +27 −0 spec/models/application_database_spec.rb
  64. +30 −0 spec/spec_helper.rb
@@ -0,0 +1,8 @@
+.bundle/
+log/*.log
+pkg/
+spec/dummy/db/*.sqlite3
+spec/dummy/log/*.log
+spec/dummy/tmp/
+spec/dummy/.sass-cache
+.DS_Store
1 .rspec
@@ -0,0 +1 @@
+--color
1 .rvmrc
@@ -0,0 +1 @@
+rvm ruby-1.9.3-p327
17 Gemfile
@@ -0,0 +1,17 @@
+source "http://rubygems.org"
+
+# Declare your gem's dependencies in get_back.gemspec.
+# Bundler will treat runtime dependencies like base dependencies, and
+# development dependencies will be added by default to the :development group.
+gemspec
+
+# jquery-rails is used by the dummy application
+gem "jquery-rails"
+
+# Declare any dependencies that are still in development here instead of in
+# your gemspec. These might include edge Rails or gems from your path or
+# Git. Remember to move these dependencies to your gemspec before releasing
+# your gem to rubygems.org.
+
+# To use debugger
+# gem 'debugger'
@@ -0,0 +1,126 @@
+PATH
+ remote: .
+ specs:
+ get_back (0.0.1)
+ rails (~> 3.2.12)
+
+GEM
+ remote: http://rubygems.org/
+ specs:
+ actionmailer (3.2.12)
+ actionpack (= 3.2.12)
+ mail (~> 2.4.4)
+ actionpack (3.2.12)
+ activemodel (= 3.2.12)
+ activesupport (= 3.2.12)
+ builder (~> 3.0.0)
+ erubis (~> 2.7.0)
+ journey (~> 1.0.4)
+ rack (~> 1.4.5)
+ rack-cache (~> 1.2)
+ rack-test (~> 0.6.1)
+ sprockets (~> 2.2.1)
+ activemodel (3.2.12)
+ activesupport (= 3.2.12)
+ builder (~> 3.0.0)
+ activerecord (3.2.12)
+ activemodel (= 3.2.12)
+ activesupport (= 3.2.12)
+ arel (~> 3.0.2)
+ tzinfo (~> 0.3.29)
+ activeresource (3.2.12)
+ activemodel (= 3.2.12)
+ activesupport (= 3.2.12)
+ activesupport (3.2.12)
+ i18n (~> 0.6)
+ multi_json (~> 1.0)
+ archive-tar-minitar (0.5.2)
+ arel (3.0.2)
+ builder (3.0.4)
+ columnize (0.3.6)
+ diff-lcs (1.2.1)
+ erubis (2.7.0)
+ hike (1.2.1)
+ i18n (0.6.4)
+ journey (1.0.4)
+ jquery-rails (2.2.1)
+ railties (>= 3.0, < 5.0)
+ thor (>= 0.14, < 2.0)
+ json (1.7.7)
+ linecache19 (0.5.13)
+ ruby_core_source (>= 0.1.4)
+ mail (2.4.4)
+ i18n (>= 0.4.0)
+ mime-types (~> 1.16)
+ treetop (~> 1.4.8)
+ mime-types (1.21)
+ multi_json (1.6.1)
+ mysql2 (0.3.11)
+ polyglot (0.3.3)
+ rack (1.4.5)
+ rack-cache (1.2)
+ rack (>= 0.4)
+ rack-ssl (1.3.3)
+ rack
+ rack-test (0.6.2)
+ rack (>= 1.0)
+ rails (3.2.12)
+ actionmailer (= 3.2.12)
+ actionpack (= 3.2.12)
+ activerecord (= 3.2.12)
+ activeresource (= 3.2.12)
+ activesupport (= 3.2.12)
+ bundler (~> 1.0)
+ railties (= 3.2.12)
+ railties (3.2.12)
+ actionpack (= 3.2.12)
+ activesupport (= 3.2.12)
+ rack-ssl (~> 1.3.2)
+ rake (>= 0.8.7)
+ rdoc (~> 3.4)
+ thor (>= 0.14.6, < 2.0)
+ rake (10.0.3)
+ rdoc (3.12.2)
+ json (~> 1.4)
+ rspec-core (2.13.0)
+ rspec-expectations (2.13.0)
+ diff-lcs (>= 1.1.3, < 2.0)
+ rspec-mocks (2.13.0)
+ rspec-rails (2.13.0)
+ actionpack (>= 3.0)
+ activesupport (>= 3.0)
+ railties (>= 3.0)
+ rspec-core (~> 2.13.0)
+ rspec-expectations (~> 2.13.0)
+ rspec-mocks (~> 2.13.0)
+ ruby-debug-base19 (0.11.26)
+ columnize (>= 0.3.1)
+ linecache19 (>= 0.5.11)
+ ruby_core_source (>= 0.1.4)
+ ruby-debug19 (0.11.6)
+ columnize (>= 0.3.1)
+ linecache19 (>= 0.5.11)
+ ruby-debug-base19 (>= 0.11.19)
+ ruby_core_source (0.1.5)
+ archive-tar-minitar (>= 0.5.2)
+ sprockets (2.2.2)
+ hike (~> 1.2)
+ multi_json (~> 1.0)
+ rack (~> 1.0)
+ tilt (~> 1.1, != 1.3.0)
+ thor (0.17.0)
+ tilt (1.3.5)
+ treetop (1.4.12)
+ polyglot
+ polyglot (>= 0.3.1)
+ tzinfo (0.3.36)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ get_back!
+ jquery-rails
+ mysql2
+ rspec-rails
+ ruby-debug19
@@ -0,0 +1,20 @@
+Copyright 2013 YOURNAME
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,22 @@
+= GetBack
+
+Rails engine with utilities for backup and restore of entire application database.
+Includes rake tasks that may be invoked by cron task to periodically backup the database and send it by email.
+
+Include this in your application Gemfile:
+
+gem 'get_back'
+
+Mount the get_back routes in your config.routes.rb with:
+
+mount GetBack::Engine => '/get_back', :as => 'get_back', and the following routes are added
+ backups_backups GET /backups/backups(.:format) backups/backups#index
+ POST /backups/backups(.:format) backups/backups#create
+ new_backups_backup GET /backups/backups/new(.:format) backups/backups#new
+edit_backups_backup GET /backups/backups/:id/edit(.:format) backups/backups#edit
+ backups_backup GET /backups/backups/:id(.:format) backups/backups#show
+ PUT /backups/backups/:id(.:format) backups/backups#update
+ DELETE /backups/backups/:id(.:format) backups/backups#destroy
+
+
+An admin page is provided at the url: '/get_back/index'
@@ -0,0 +1,27 @@
+#!/usr/bin/env rake
+begin
+ require 'bundler/setup'
+rescue LoadError
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
+end
+begin
+ require 'rdoc/task'
+rescue LoadError
+ require 'rdoc/rdoc'
+ require 'rake/rdoctask'
+ RDoc::Task = Rake::RDocTask
+end
+
+RDoc::Task.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'GetBack'
+ rdoc.options << '--line-numbers'
+ rdoc.rdoc_files.include('README.rdoc')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
+
+
+
+
+Bundler::GemHelper.install_tasks
+
No changes.
@@ -0,0 +1,15 @@
+// This is a manifest file that'll be compiled into application.js, which will include all the files
+// listed below.
+//
+// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
+// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
+//
+// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
+// the compiled file.
+//
+// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
+// GO AFTER THE REQUIRES BELOW.
+//
+//= require jquery
+//= require jquery_ujs
+//= require_tree .
@@ -0,0 +1,13 @@
+/*
+ * 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 vendor/assets/stylesheets of plugins, if any, 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 top of the
+ * compiled file, but it's generally better to create a new file per style scope.
+ *
+ *= require_self
+ *= require_tree .
+ */
@@ -0,0 +1,5 @@
+module GetBack
+ class ApplicationController < ::ApplicationController
+ layout 'layouts/application'
+ end
+end
@@ -0,0 +1,80 @@
+module GetBack
+ class BackupsController < ApplicationController
+ def index
+ @backups = BackupFile.find(:all).sort
+ end
+
+ # creates a new backup file from the database
+ def create
+ backup = BackupFile.new # creates new BackupFile object with current date/time
+ backup.save
+ redirect_to backups_path
+ end
+
+ # restores the selected backup file (denoted by the passed-in param[:id]) to be the active database
+ # the passed-in :id field is not the typical numeric table index but instead has the filename root, like:
+ # "backups_2009-08-16_07-50-26_development_dump"
+ def restore
+ backfile = BackupFile.find(params[:id])
+ if write_db(backfile)
+ flash[:notice] = "Database has been restored to backup version dated:<br/>#{backfile.date}"
+ else
+ flash[:error] ||= "Restore database failed<br/>file was probably corrupted."
+ end
+ redirect_to backups_path
+ end
+
+ def restore_from_upload
+ if params[:upload][:uploaded_file].blank?
+ flash[:error] = "Please click \"Browse\" to select a local database file to upload" # this should never be called, as the detection is now done in javascript at the client. Leave it here for posterity!
+ else
+ backfile = BackupFile.new(:filename=>uploaded_file_path)
+ if write_db(backfile)
+ flash[:notice] = "Database restored from uploaded file<br/>with date #{backfile.date}"
+ else
+ flash[:error] ||= "Database restore failed"
+ end
+ end
+ redirect_to backups_path
+ end
+
+ def destroy
+ backup_file = BackupFile.find(params[:id])
+ if backup_file.destroy
+ flash[:notice] = "Backup file was deleted"
+ else
+ flash[:error] = "Delete backup file failed"
+ end
+ redirect_to backups_path
+ end
+
+ # here "show" is used for REST conformance. Here we download the file instead of displaying it
+ def show
+ backup_file = BackupFile.find(params[:id])
+ send_file backup_file.filename
+ end
+
+ private
+
+ # overwrites the active database with the file passed in
+ def write_db(backfile)
+ if backfile.valid?
+ ApplicationDatabase.restore_from_file(backfile) # returns false if restore fails
+ else
+ flash[:error] = "File name does not have correct format.<br/>Are you sure it's a database backup file?<br/>Database was not restored."
+ false
+ end
+ end
+
+ def uploaded_file_path
+ # TODO should unzip after uploading
+ filename = params[:upload][:uploaded_file].original_filename
+ directory = "tmp/uploads"
+ path = File.join(directory, filename)
+ File.open(path,"wb"){|f| f.write(params[:upload][:uploaded_file].read)}
+ #File.join(RAILS_ROOT,path)
+ Rails.root.join(path)
+ end
+
+ end
+end
@@ -0,0 +1,4 @@
+module GetBack
+ module ApplicationHelper
+ end
+end
@@ -0,0 +1,32 @@
+require 'fileutils'
+
+class ApplicationDatabase
+ def initialize
+ @@db_config = ActiveRecord::Base.configurations[Rails.env]
+ @@password = @@db_config['password'].nil? ? '' : "--password=#{@@db_config['password']}"
+ end
+
+ def self.extract_contents
+ new
+ %x[#{@@db_config['path']}mysqldump -u #{@@db_config['username']} #{@@password} --single-transaction -Q --add-drop-table -O add-locks=FALSE -O lock-tables=FALSE --hex-blob #{@@db_config['database']}]
+ end
+
+ def self.save_to_file(file)
+ # TODO instead of creating a copy of the db in memory and writing to the file,
+ # should try command output redirection (>) in the unix shell directly to the file, in the ApplicationController.extract_contents
+ # method. This might avoid the memory problems that are causing the backups to fail.
+ # see http://blog.craigambrose.com/articles/2007/03/01/a-rake-task-for-database-backups
+ new
+ %x[#{@@db_config['path']}mysqldump -u #{@@db_config['username']} #{@@password} --single-transaction -Q --add-drop-table -O add-locks=FALSE -O lock-tables=FALSE --hex-blob #{@@db_config['database']} > #{file} ]
+ end
+
+ def self.restore_from_file(backfile)
+ # when it has been tested in production mode, replace the next two lines with new
+ new_back = backfile.filename
+ @db_config = ActiveRecord::Base.configurations["development"] # TODO hard coded here... MUST CHANGE THIS AFTER TESTING
+ password = @db_config['password'].nil? ? '' : "--password=#{@db_config['password']}"
+ %x[#{@db_config['path']}mysql --database #{@db_config['database']} --host=#{@db_config['host']} --user=#{@db_config['username']} #{password} -e \"source #{new_back}\";]
+ $?.exitstatus.zero?
+ end
+
+end
Oops, something went wrong.

0 comments on commit 5e2b509

Please sign in to comment.