siringa 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/MIT-LICENSE +20 -0
- data/README.md +169 -0
- data/Rakefile +39 -0
- data/app/controllers/siringa/application_controller.rb +4 -0
- data/app/controllers/siringa/siringa_controller.rb +49 -0
- data/app/helpers/siringa/application_helper.rb +4 -0
- data/config/routes.rb +5 -0
- data/lib/generators/siringa/install_generator.rb +18 -0
- data/lib/generators/templates/siringa_initializer.rb +9 -0
- data/lib/siringa.rb +4 -0
- data/lib/siringa/configuration.rb +26 -0
- data/lib/siringa/definitions.rb +38 -0
- data/lib/siringa/dumps.rb +66 -0
- data/lib/siringa/engine.rb +5 -0
- data/lib/siringa/version.rb +3 -0
- data/lib/tasks/siringa_tasks.rake +11 -0
- data/test/controllers/siringa_controller_test.rb +23 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +9 -0
- data/test/dummy/app/assets/stylesheets/application.css +7 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/models/user.rb +3 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +45 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +30 -0
- data/test/dummy/config/environments/production.rb +60 -0
- data/test/dummy/config/environments/test.rb +39 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +10 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/siringa.rb +5 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +4 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/migrate/20130927161308_create_user.rb +7 -0
- data/test/dummy/db/schema.rb +20 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +1069 -0
- data/test/dummy/log/test.log +1471 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +26 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/dummy/test/factories.rb +7 -0
- data/test/dummy/test/siringa/definitions.rb +6 -0
- data/test/dummy/tmp/dumps/db_20130927191400.dump +0 -0
- data/test/integration/navigation_test.rb +10 -0
- data/test/siringa_test.rb +7 -0
- data/test/test_helper.rb +10 -0
- metadata +158 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ZGIxNzZkYjA3ZmM5MmU2MTM1OTVmOTNmM2NiNDhmNmI2M2UxMzgzMw==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NWZiYWE3MTIzMjI1NTE0YzJjZjhiYzJmNGRiMzlhYjQyOTA4MGZjMw==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
YjM1NDczYWU5N2JjMjA1YTY0MTIwMjQzZjljMjZlNzBkMDQ3NjYxZDYwOGQw
|
10
|
+
ZTBlZTc2ZDRiMjhkNTI1N2QwNmY2YWYwNzQ4NzVlYTliMmQxNmJjNThmNjI2
|
11
|
+
YmM1MGRlMjQ0MWEyMTIzN2E2OTBjYWIwNDU1YTU3MTViOWRkZmM=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
NDdmYzI2ZmRjOGQ2MWRiMDE0NDc2MGZiYTA5MTEyNWIxNGIxMzc1MTgwZjg0
|
14
|
+
NmEyMzNhNzgyMmE3ZjcyZmJmOWIzNWYwYTE0Y2JmZTUyYTRmNWRlNTcyOTJk
|
15
|
+
MmVhYmU3YjA1MmYwNDNhYzdjOTMxMTcwMTk2NzM0ZGNmNmY0MDQ=
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2013 Enrico Stano
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
# Siringa :syringe:
|
2
|
+
This gem was born working on pure client acceptance testing in [Teambox](http://www.teambox.com).
|
3
|
+
## The problem
|
4
|
+
|
5
|
+
You have a Rails based API and you need to write some acceptance tests using your Javascript/iOS/Android/whatever client.
|
6
|
+
|
7
|
+
Probably you'll have three basic needs:
|
8
|
+
|
9
|
+
1. Pre-populate the DB with some (maybe massive) data (a.k.a. seed data)
|
10
|
+
2. Your seed data files have to be easily maintainable, you don't want to touch them too much when a model change and so on
|
11
|
+
3. Populate your DB while executing some specific acceptance test and then clean up the DB restoring the initial situation
|
12
|
+
|
13
|
+
## The solution
|
14
|
+
|
15
|
+
1. Write your seed data and use Siringa's rake recipes to pre-populate the DB just after you deploy your API
|
16
|
+
2. I suggest to use factories to create your seed data in order to take advantage of factories maybe you've already written for unit tests. But you could use whatever other way to keep your seed data maintainable and you still could use Siringa
|
17
|
+
3. Use Siringa's extra API endpoints in order to dump your inital DB situation, load some factories and then restore the initial status when you're done
|
18
|
+
|
19
|
+
**Why you don't just use your app's API to do the same thing, maybe storing JSON/XML objects in some fixture?**
|
20
|
+
|
21
|
+
Well, because mantaining those huge JSON/XML fixture files will be a nightmare.
|
22
|
+
|
23
|
+
## Install Siringa
|
24
|
+
|
25
|
+
Add the following to your `Gemfile`:
|
26
|
+
```ruby
|
27
|
+
group :test do
|
28
|
+
gem 'siringa'
|
29
|
+
end
|
30
|
+
```
|
31
|
+
For security reasons, I suggest to add it under the `test` group. In that way you'll have Siringa available only running the app in `test` environment.
|
32
|
+
|
33
|
+
Run the bundle command to install it.
|
34
|
+
|
35
|
+
Run the generator:
|
36
|
+
```console
|
37
|
+
rails generate siringa:install
|
38
|
+
```
|
39
|
+
This will add the Siringa initializer in `config/initializers/siringa.rb` and create an empty directory in `tmp/dumps`.
|
40
|
+
|
41
|
+
Add the following to your `config/routes.rb`:
|
42
|
+
```ruby
|
43
|
+
mount Siringa::Engine, :at => '/siringa'
|
44
|
+
```
|
45
|
+
Make sure that you add it in the correct environment. For instance if you want it available only in `test` environment put it inside a condition statement like `if Rails.env.test? .. end`.
|
46
|
+
## Create definitions
|
47
|
+
|
48
|
+
In order to create a new Siringa definition just create a new file in the `test/siringa` directory like the following:
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
# test/siringa/definitions.rb
|
52
|
+
require 'siringa'
|
53
|
+
require File.expand_path('../../factories', __FILE__)
|
54
|
+
|
55
|
+
Siringa.add_definition :initial do
|
56
|
+
FactoryGirl.create :user,
|
57
|
+
name: 'Jesse Pinkman'
|
58
|
+
end
|
59
|
+
|
60
|
+
Siringa.add_definition :specific do
|
61
|
+
FactoryGirl.create :user,
|
62
|
+
name: 'Hank Schrader'
|
63
|
+
FactoryGirl.create :project,
|
64
|
+
name: 'Pollos Hermanos'
|
65
|
+
end
|
66
|
+
```
|
67
|
+
|
68
|
+
I'm using [FactoryGirl](https://github.com/thoughtbot/factory_girl) gem here but in a definition you could write whatever kind of Ruby code and Siringa will execute it when you call the definition.
|
69
|
+
|
70
|
+
## Load definitions
|
71
|
+
Now that we've created our definitions we could use them in our two cases:
|
72
|
+
### As seed data
|
73
|
+
You could just load the `initial` definition running the following rake recipe after your deploy:
|
74
|
+
```console
|
75
|
+
rake siringa:load
|
76
|
+
```
|
77
|
+
`initial` is the default definition this Rake task recipe will try to load, if you want to load another definition instead you could pass its name as argument:
|
78
|
+
```console
|
79
|
+
rake 'siringa:load[another_definition]'
|
80
|
+
```
|
81
|
+
This will load a definition named `:another_definition`. Please note that if you use Zsh shell you'll need to use quotes, more info [here](http://robots.thoughtbot.com/post/18129303042/how-to-use-arguments-in-a-rake-task).
|
82
|
+
|
83
|
+
If you want to force a Rails environment you could just run the Sriringa recipe specifing the `RAILS_ENV` environmental variable:
|
84
|
+
```console
|
85
|
+
RAILS_ENV=development rake siringa:load
|
86
|
+
```
|
87
|
+
|
88
|
+
### During an acceptance test
|
89
|
+
As you can see running `rake routes`, Siringa added 3 new routes to your API:
|
90
|
+
```console
|
91
|
+
Routes for Siringa::Engine:
|
92
|
+
POST /load/:definition(.:format) siringa/siringa#load
|
93
|
+
dump POST /dump(.:format) siringa/siringa#dump
|
94
|
+
restore POST /restore(.:format) siringa/siringa#restore
|
95
|
+
```
|
96
|
+
|
97
|
+
The workflow I propose here is:
|
98
|
+
|
99
|
+
1. Create a dump of your DB performing a `POST` request to `YOURHOST/siringa/dump`
|
100
|
+
|
101
|
+
This will create a `.dump` file in the `tmp/dumps` directory created during the install process. You could create as many dump files as you want but Siringa will keep only the latest 5 dumps created.
|
102
|
+
|
103
|
+
2. Load a Siringa definition performing a `POST` request to `YOURHOST/siringa/load/specific`
|
104
|
+
|
105
|
+
This will run the code defined in a definition named `specific` on the server.
|
106
|
+
|
107
|
+
3. Go ahead with your acceptance test
|
108
|
+
|
109
|
+
4. Restore the DB status performing a `POST` request to `YOURHOST/siringa/restore`
|
110
|
+
|
111
|
+
This will bring back your DB at the initial status using the dump file you created in step 1.
|
112
|
+
|
113
|
+
Please note that the `Siringa::restore` method only use the latest dump file created, older dump files in the `tmp/dumps` folder will be ignored.
|
114
|
+
|
115
|
+
## Customize Siringa
|
116
|
+
You could customize Siringa changing the configuration stored in the initializer:
|
117
|
+
```ruby
|
118
|
+
# config/initializers/siringa.rb
|
119
|
+
Siringa.configure do |config|
|
120
|
+
# customize the path where the definitions are stored
|
121
|
+
config.definitions_path = 'test/siringa'
|
122
|
+
# customize the path where the DB dumps are stored
|
123
|
+
config.dumps_path = 'tmp/dumps'
|
124
|
+
end
|
125
|
+
|
126
|
+
Siringa.load_definitions
|
127
|
+
```
|
128
|
+
## Acceptance test example
|
129
|
+
Just to get the idea, the following script will show you how to use Siringa in a acceptance test using Selenium, [rest-client](https://github.com/rest-client/rest-client) and RSpec:
|
130
|
+
```ruby
|
131
|
+
require 'selenium-webdriver'dd
|
132
|
+
require 'rspec'
|
133
|
+
require 'rest_client'
|
134
|
+
|
135
|
+
describe "Acceptance test using Siringa" do
|
136
|
+
before(:all) do
|
137
|
+
# Dump your DB
|
138
|
+
RestClient.post 'YOURHOST/siringa/dump'
|
139
|
+
end
|
140
|
+
|
141
|
+
before(:each) do
|
142
|
+
@driver = Selenium::WebDriver.for :firefox
|
143
|
+
end
|
144
|
+
|
145
|
+
after(:each) do
|
146
|
+
@driver.quit
|
147
|
+
end
|
148
|
+
|
149
|
+
it "Load a definition and test something" do
|
150
|
+
# Load a definition named 'specific'
|
151
|
+
RestClient.post 'YOURHOST/siringa/load', { :definition => :specific }
|
152
|
+
|
153
|
+
# Here goes your test
|
154
|
+
|
155
|
+
# Restore your DB
|
156
|
+
RestClient.post 'YOURHOST/siringa/restore'
|
157
|
+
end
|
158
|
+
end
|
159
|
+
```
|
160
|
+
## To Do
|
161
|
+
* Write more tests
|
162
|
+
* Add Postgres adaptor compatibility for dumps and restores
|
163
|
+
* Add more customizations
|
164
|
+
|
165
|
+
## How to collaborate
|
166
|
+
* Fork the repo and send a pull request, thanks!
|
167
|
+
|
168
|
+
# Licence
|
169
|
+
MIT-LICENSE 2013 Enrico Stano
|
data/Rakefile
ADDED
@@ -0,0 +1,39 @@
|
|
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 = 'Siringa'
|
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
|
+
Bundler::GemHelper.install_tasks
|
28
|
+
|
29
|
+
require 'rake/testtask'
|
30
|
+
|
31
|
+
Rake::TestTask.new(:test) do |t|
|
32
|
+
t.libs << 'lib'
|
33
|
+
t.libs << 'test'
|
34
|
+
t.pattern = 'test/**/*_test.rb'
|
35
|
+
t.verbose = false
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
task :default => :test
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Siringa
|
2
|
+
class SiringaController < ApplicationController
|
3
|
+
|
4
|
+
def load
|
5
|
+
Siringa.load_definition(params['definition'].to_sym)
|
6
|
+
resp = { :text => "Definition #{params['definition']} loaded.", :status => :created }
|
7
|
+
rescue ArgumentError => exception
|
8
|
+
resp = { :text => exception.to_s, :status => :method_not_allowed }
|
9
|
+
rescue => exception
|
10
|
+
resp = { :text => exception.to_s, :status => :internal_server_error }
|
11
|
+
ensure
|
12
|
+
render resp
|
13
|
+
end
|
14
|
+
|
15
|
+
def dump
|
16
|
+
result = Siringa.dump_to(Siringa.dump_file_name)
|
17
|
+
if result[:success]
|
18
|
+
Siringa.keep_five_dumps(Siringa.ordered_dumps)
|
19
|
+
resp = { :text => "DB dumped at #{result[:file_name]}",
|
20
|
+
:status => :created }
|
21
|
+
else
|
22
|
+
resp = { :text => "DB dump FAILED!\nError:\n#{result[:output]}",
|
23
|
+
:status => :internal_server_error }
|
24
|
+
end
|
25
|
+
|
26
|
+
render resp
|
27
|
+
end
|
28
|
+
|
29
|
+
def restore
|
30
|
+
last_dump = Siringa.ordered_dumps.last
|
31
|
+
if last_dump
|
32
|
+
result = Siringa.restore_from(last_dump)
|
33
|
+
if result[:success]
|
34
|
+
resp = { :text => "DB restored from #{result[:file_name]}",
|
35
|
+
:status => :accepted }
|
36
|
+
else
|
37
|
+
resp = { :text => "DB restore FAILED!\nError:\n#{result[:output]}",
|
38
|
+
:status => :internal_server_error }
|
39
|
+
end
|
40
|
+
else
|
41
|
+
resp = { :text => "DB restore FAILED!\nThere is no dump to restore from.",
|
42
|
+
:status => :method_not_allowed }
|
43
|
+
end
|
44
|
+
|
45
|
+
render resp
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module Siringa
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
source_root File.expand_path("../../templates", __FILE__)
|
5
|
+
desc "Creates Siringa initializer for your application"
|
6
|
+
|
7
|
+
def copy_initializer
|
8
|
+
template "siringa_initializer.rb", "config/initializers/siringa.rb"
|
9
|
+
|
10
|
+
puts "Install complete!"
|
11
|
+
end
|
12
|
+
|
13
|
+
def create_dumps_folder
|
14
|
+
empty_directory "tmp/dumps"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# config/initializers/siringa.rb
|
2
|
+
Siringa.configure do |config|
|
3
|
+
# customize the path where the definitions are stored
|
4
|
+
# config.definitions_path = 'test/siringa'
|
5
|
+
# customize the path where the dumps are stored
|
6
|
+
# config.dumps_path = 'tmp/dumps'
|
7
|
+
end
|
8
|
+
|
9
|
+
Siringa.load_definitions
|
data/lib/siringa.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module Siringa
|
2
|
+
|
3
|
+
@definitions = {}
|
4
|
+
|
5
|
+
class << self
|
6
|
+
attr_accessor :configuration
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.configuration
|
10
|
+
@configuration ||= Configuration.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.configure
|
14
|
+
yield(configuration)
|
15
|
+
end
|
16
|
+
|
17
|
+
class Configuration
|
18
|
+
attr_accessor :definitions_path, :dumps_path
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
@definitions_path = "spec/siringa"
|
22
|
+
@dumps_path = 'tmp/dumps'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Siringa
|
2
|
+
|
3
|
+
# Load definitions from files
|
4
|
+
def self.load_definitions
|
5
|
+
Dir[Rails.root.join("#{self.configuration.definitions_path}/**/*.rb")].each { |f| require f }
|
6
|
+
end
|
7
|
+
|
8
|
+
# Load a definition and run its code
|
9
|
+
#
|
10
|
+
# @param [Symbol] name of the definition
|
11
|
+
def self.load_definition(name)
|
12
|
+
if exists_definition?(name)
|
13
|
+
@definitions[name].call
|
14
|
+
else
|
15
|
+
raise ArgumentError, "Definition #{name.to_s} does not exist.", caller
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Add a definition
|
20
|
+
#
|
21
|
+
# @param [Symbol] name of the definition
|
22
|
+
# @param [Proc] code to run
|
23
|
+
def self.add_definition(name, &block)
|
24
|
+
if !exists_definition?(name)
|
25
|
+
@definitions[name] = Proc.new(&block)
|
26
|
+
else
|
27
|
+
raise ArgumentError, "Definition #{name.to_s} already exists."
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Check if a definition already exists
|
32
|
+
#
|
33
|
+
# @param [Symbol] name of the definition
|
34
|
+
# @return [Boolean]
|
35
|
+
def self.exists_definition?(name)
|
36
|
+
!@definitions[name].nil?
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Siringa
|
2
|
+
|
3
|
+
# Generate dump file name
|
4
|
+
#
|
5
|
+
# @return [String]
|
6
|
+
def self.dump_file_name
|
7
|
+
"#{Siringa.configuration.dumps_path}/db_#{Time.now.strftime('%Y%m%d%H%M%S')}.dump"
|
8
|
+
end
|
9
|
+
|
10
|
+
# Create a DB dump
|
11
|
+
#
|
12
|
+
# @param [String] dump path
|
13
|
+
# @return [Object]
|
14
|
+
def self.dump_to(dump_path)
|
15
|
+
adapter_config = ActiveRecord::Base.connection.instance_values["config"]
|
16
|
+
case adapter_config[:adapter]
|
17
|
+
when "mysql", "mysql2"
|
18
|
+
output = %x(/usr/bin/env mysqldump -uroot #{adapter_config[:database]} > #{dump_path})
|
19
|
+
when "sqlite3"
|
20
|
+
output = %x(/usr/bin/env sqlite3 #{adapter_config[:database]} '.backup #{dump_path}')
|
21
|
+
else
|
22
|
+
raise NotImplementedError, "Unknown adapter type '#{adapter_config[:adapter]}'"
|
23
|
+
end
|
24
|
+
|
25
|
+
{ :success => $?.success?, :output => output, :dump_path => dump_path }
|
26
|
+
end
|
27
|
+
|
28
|
+
# Restore from a DB dump
|
29
|
+
#
|
30
|
+
# @param [String] dump path
|
31
|
+
# @return [Object]
|
32
|
+
def self.restore_from(dump_path)
|
33
|
+
adapter_config = ActiveRecord::Base.connection.instance_values["config"]
|
34
|
+
case adapter_config[:adapter]
|
35
|
+
when "mysql", "mysql2"
|
36
|
+
output = %x(/usr/bin/env mysql -uroot #{adapter_config[:database]} < #{dump_path})
|
37
|
+
when "sqlite3"
|
38
|
+
output = %x(/usr/bin/env sqlite3 #{adapter_config[:database]} '.restore #{dump_path}')
|
39
|
+
else
|
40
|
+
raise NotImplementedError, "Unknown adapter type '#{adapter_config[:adapter]}'"
|
41
|
+
end
|
42
|
+
|
43
|
+
{ :success => $?.success?, :output => output, :dump_path => dump_path }
|
44
|
+
end
|
45
|
+
|
46
|
+
# Delete oldest dump files, keep 5 dump files
|
47
|
+
#
|
48
|
+
# @param [Array] file names
|
49
|
+
# @return [Boolean]
|
50
|
+
def self.keep_five_dumps(dump_files)
|
51
|
+
if dump_files.length > 5
|
52
|
+
dump_files.first(dump_files.length - 5).each { |f| File.delete(f) }
|
53
|
+
return true
|
54
|
+
else
|
55
|
+
return false
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Retrieve a collection of dump files sorted by creation date
|
60
|
+
#
|
61
|
+
# @return [Array]
|
62
|
+
def self.ordered_dumps
|
63
|
+
Dir.glob("#{Siringa.configuration.dumps_path}/db_*.dump").sort_by { |f| File.mtime(f) }
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|