fm_yaml_db 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
data/.Gemfile.swp ADDED
Binary file
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source "http://rubygems.org"
2
+
3
+ group :development do
4
+ gem 'rdoc', '~> 3.12'
5
+ gem 'bundler'
6
+ gem 'jeweler', '~> 1.8.4'
7
+ gem 'rspec'
8
+ end
9
+
10
+ gem 'rails'
11
+
12
+
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) Adam Wiggins, Orion Henry
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.markdown ADDED
@@ -0,0 +1,68 @@
1
+ # YamlDb
2
+
3
+ YamlDb is a database-independent format for dumping and restoring data. It complements the the database-independent schema format found in db/schema.rb. The data is saved into db/data.yml.
4
+
5
+ This can be used as a replacement for mysqldump or pg_dump, but only for the databases typically used by Rails apps. Users, permissions, schemas, triggers, and other advanced database features are not supported - by design.
6
+
7
+ Any database that has an ActiveRecord adapter should work. This gem is now Rails 3 only. For Rails 2, clone and checkout the Rails2 branch.
8
+
9
+ #Be awared. This is the fork
10
+ Look at the [Ludicast](https://github.com/ludicast/yaml_db/) fork and original Adam Wiggins [repo](https://github.com/adamwiggins/yaml_db)(which is not maintained for the moment)
11
+
12
+ #Travis Build Status
13
+
14
+ [![Build Status](https://secure.travis-ci.org/kalabiyau/yaml_db.png)](http://travis-ci.org/kalabiyau/yaml_db)
15
+
16
+ ## Installation
17
+
18
+ Simply add to your Gemfile:
19
+
20
+ gem 'fm_yaml_db', :require => 'yaml_db'
21
+
22
+ All rake tasks will then be available to you.
23
+
24
+ ## Usage
25
+
26
+ rake db:data:dump -> Dump contents of Rails database to db/data.yml
27
+ rake db:data:load -> Load contents of db/data.yml into the database
28
+
29
+ Further, there are tasks db:dump and db:load which do the entire database (the equivalent of running db:schema:dump followed by db:data:load). Also, there are other tasks recently added that allow the export of the database contents to/from multiple files (each one named after the table being dumped or loaded).
30
+
31
+ rake db:data:dump_dir -> Dump contents of database to curr_dir_name/tablename.extension (defaults to yaml)
32
+ rake db:data:load_dir -> Load contents of db/data_dir into database
33
+
34
+ Also, it is possible to dump only selected tables of your database:
35
+
36
+ rake db:data:dump_dir filter_tables=^table[0-5]$|other_table
37
+ rake db:data:dump filter_tables=^table[0-5]$|other_table
38
+
39
+ (Beware that the `filter_tables` paramater is evaluated as a regular expression
40
+ (with `Regexp.new(filter_tables)`), so:
41
+
42
+ rake db:data:dump_dir filter_tables=mytable
43
+
44
+ will dump `mytable`, but also `mytable_join_other_table`.
45
+
46
+
47
+ In addition, we have plugins whereby you can export your database to/from various formats. We only deal with yaml and csv right now, but you can easily write tools for your own formats (such as Excel or XML). To use another format, just load setting the "class" parameter to the class you are using. This defaults to "YamlDb::Helper" which is a refactoring of the old yaml_db code. We'll shorten this to use class nicknames in a little bit.
48
+
49
+ ## Examples
50
+
51
+ One common use would be to switch your data from one database backend to another. For example, let's say you wanted to switch from SQLite to MySQL. You might execute the following steps:
52
+
53
+ 1. rake db:dump
54
+
55
+ 2. Edit config/database.yml and change your adapter to mysql, set up database params
56
+
57
+ 3. mysqladmin create [database name]
58
+
59
+ 4. rake db:load
60
+
61
+ ## Credits
62
+
63
+ Created by Orion Henry and Adam Wiggins. Major updates by Ricardo Chimal, Jr.
64
+
65
+ Patches contributed by Michael Irwin, Tom Locke, and Tim Galeckas.
66
+
67
+ Send questions, feedback, or patches to the Heroku mailing list: http://groups.google.com/group/heroku
68
+
data/README.rdoc ADDED
@@ -0,0 +1,19 @@
1
+ = fm-yamldb
2
+
3
+ Description goes here.
4
+
5
+ == Contributing to fm-yamldb
6
+
7
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
8
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
9
+ * Fork the project.
10
+ * Start a feature/bugfix branch.
11
+ * Commit and push until you are happy with your contribution.
12
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2012 KalabiYau. See LICENSE.txt for
18
+ further details.
19
+
data/Rakefile ADDED
@@ -0,0 +1,44 @@
1
+ # encoding: utf-8
2
+ require 'rubygems'
3
+ require 'bundler'
4
+ require 'rake'
5
+ require 'rspec/core/rake_task'
6
+
7
+ begin
8
+ Bundler.setup(:default, :development)
9
+ rescue Bundler::BundlerError => e
10
+ $stderr.puts e.message
11
+ $stderr.puts "Run `bundle install` to install missing gems"
12
+ exit e.status_code
13
+ end
14
+
15
+
16
+ require 'jeweler'
17
+ Jeweler::Tasks.new do |gem|
18
+ gem.name = "fm_yaml_db"
19
+ gem.homepage = "http://github.com/kalabiyau/yaml_db"
20
+ gem.license = "MIT"
21
+ gem.summary = %Q{fork of a great yaml_db gem}
22
+ gem.description = %Q{Forked gem from yaml_db - the great DB independent dumper for rails devs}
23
+ gem.email = "skullzeek@gmail.com"
24
+ gem.authors = ["Adam Wiggins","Orion Henry"]
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ task :default => :spec
29
+
30
+ require 'rdoc/task'
31
+ Rake::RDocTask.new do |rdoc|
32
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
33
+
34
+ rdoc.rdoc_dir = 'rdoc'
35
+ rdoc.title = "fm-yamldb #{version}"
36
+ rdoc.rdoc_files.include('README*')
37
+ rdoc.rdoc_files.include('lib/**/*.rb')
38
+ end
39
+
40
+
41
+ RSpec::Core::RakeTask.new(:spec) do |spec|
42
+ spec.pattern = 'spec/*_spec.rb'
43
+ spec.rspec_opts = ['--backtrace']
44
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.4
data/about.yml ADDED
@@ -0,0 +1,5 @@
1
+ author: Orion Henry and Adam Wiggins of Heroku
2
+ summary: Dumps and loads a database-independent data dump format in db/data.yml.
3
+ homepage: http://opensource.heroku.com/
4
+ license: MIT
5
+ rails_version: 1.2+
@@ -0,0 +1,76 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "fm_yaml_db"
8
+ s.version = "0.2.4"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Adam Wiggins", "Orion Henry"]
12
+ s.date = "2012-09-19"
13
+ s.description = "Forked gem from yaml_db - the great DB independent dumper for rails devs"
14
+ s.email = "skullzeek@gmail.com"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.markdown",
18
+ "README.rdoc"
19
+ ]
20
+ s.files = [
21
+ ".Gemfile.swp",
22
+ ".document",
23
+ ".travis.yml",
24
+ "Gemfile",
25
+ "LICENSE.txt",
26
+ "README.markdown",
27
+ "README.rdoc",
28
+ "Rakefile",
29
+ "VERSION",
30
+ "about.yml",
31
+ "fm_yaml_db.gemspec",
32
+ "init.rb",
33
+ "lib/csv_db.rb",
34
+ "lib/serialization_helper.rb",
35
+ "lib/tasks/yaml_db_tasks.rake",
36
+ "lib/yaml_db.rb",
37
+ "spec/base.rb",
38
+ "spec/serialization_helper_base_spec.rb",
39
+ "spec/serialization_helper_dump_spec.rb",
40
+ "spec/serialization_helper_load_spec.rb",
41
+ "spec/serialization_utils_spec.rb",
42
+ "spec/yaml_dump_spec.rb",
43
+ "spec/yaml_load_spec.rb",
44
+ "spec/yaml_utils_spec.rb"
45
+ ]
46
+ s.homepage = "http://github.com/kalabiyau/yaml_db"
47
+ s.licenses = ["MIT"]
48
+ s.require_paths = ["lib"]
49
+ s.rubygems_version = "1.8.15"
50
+ s.summary = "fork of a great yaml_db gem"
51
+
52
+ if s.respond_to? :specification_version then
53
+ s.specification_version = 3
54
+
55
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
56
+ s.add_runtime_dependency(%q<rails>, [">= 0"])
57
+ s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
58
+ s.add_development_dependency(%q<bundler>, [">= 0"])
59
+ s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
60
+ s.add_development_dependency(%q<rspec>, [">= 0"])
61
+ else
62
+ s.add_dependency(%q<rails>, [">= 0"])
63
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
64
+ s.add_dependency(%q<bundler>, [">= 0"])
65
+ s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
66
+ s.add_dependency(%q<rspec>, [">= 0"])
67
+ end
68
+ else
69
+ s.add_dependency(%q<rails>, [">= 0"])
70
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
71
+ s.add_dependency(%q<bundler>, [">= 0"])
72
+ s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
73
+ s.add_dependency(%q<rspec>, [">= 0"])
74
+ end
75
+ end
76
+
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'yaml_db'
data/lib/csv_db.rb ADDED
@@ -0,0 +1,78 @@
1
+ #require 'FasterCSV'
2
+ module CsvDb
3
+ module Helper
4
+ def self.loader
5
+ Load
6
+ end
7
+
8
+ def self.dumper
9
+ Dump
10
+ end
11
+
12
+ def self.extension
13
+ "csv"
14
+ end
15
+ end
16
+
17
+ class Load < SerializationHelper::Load
18
+ def self.load_documents(io, truncate = true)
19
+ tables = {}
20
+ curr_table = nil
21
+ io.each do |line|
22
+ if /BEGIN_CSV_TABLE_DECLARATION(.+)END_CSV_TABLE_DECLARATION/ =~ line
23
+ curr_table = $1
24
+ tables[curr_table] = {}
25
+ else
26
+ if tables[curr_table]["columns"]
27
+ tables[curr_table]["records"] << FasterCSV.parse(line)[0]
28
+ else
29
+ tables[curr_table]["columns"] = FasterCSV.parse(line)[0]
30
+ tables[curr_table]["records"] = []
31
+ end
32
+ end
33
+ end
34
+
35
+ tables.each_pair do |table_name, contents|
36
+ load_table(table_name, contents, truncate)
37
+ end
38
+ end
39
+ end
40
+
41
+ class Dump < SerializationHelper::Dump
42
+
43
+ def self.before_table(io,table)
44
+ io.write "BEGIN_CSV_TABLE_DECLARATION#{table}END_CSV_TABLE_DECLARATION\n"
45
+ end
46
+
47
+ def self.dump(io)
48
+ tables.each do |table|
49
+ before_table(io, table)
50
+ dump_table(io, table)
51
+ after_table(io, table)
52
+ end
53
+ end
54
+
55
+ def self.after_table(io,table)
56
+ io.write ""
57
+ end
58
+
59
+ def self.dump_table_columns(io, table)
60
+ io.write(table_column_names(table).to_csv)
61
+ end
62
+
63
+ def self.dump_table_records(io, table)
64
+
65
+ column_names = table_column_names(table)
66
+
67
+ each_table_page(table) do |records|
68
+ rows = SerializationHelper::Utils.unhash_records(records, column_names)
69
+ records.each do |record|
70
+ io.write(record.to_csv)
71
+ end
72
+ end
73
+ end
74
+
75
+ end
76
+
77
+
78
+ end
@@ -0,0 +1,204 @@
1
+ module SerializationHelper
2
+
3
+ class Base
4
+ attr_reader :extension
5
+
6
+ def initialize(helper, filter_table_names = nil)
7
+ @dumper = helper.dumper
8
+ @loader = helper.loader
9
+ @extension = helper.extension
10
+ @dumper.filter_table_names = filter_table_names if filter_table_names
11
+ end
12
+
13
+ def dump(filename)
14
+ disable_logger
15
+ @dumper.dump(File.new(filename, "w"))
16
+ reenable_logger
17
+ end
18
+
19
+ def dump_to_dir(dirname)
20
+ Dir.mkdir(dirname)
21
+ tables = @dumper.tables
22
+ tables.each do |table|
23
+ io = File.new "#{dirname}/#{table}.#{@extension}", "w"
24
+ @dumper.before_table(io, table)
25
+ @dumper.dump_table io, table
26
+ @dumper.after_table(io, table)
27
+ end
28
+ end
29
+
30
+ def load(filename, truncate = true)
31
+ disable_logger
32
+ @loader.load(File.new(filename, "r"), truncate)
33
+ reenable_logger
34
+ end
35
+
36
+ def load_from_dir(dirname, truncate = true)
37
+ Dir.entries(dirname).each do |filename|
38
+ if filename =~ /^[.]/
39
+ next
40
+ end
41
+ @loader.load(File.new("#{dirname}/#{filename}", "r"), truncate)
42
+ end
43
+ end
44
+
45
+ def disable_logger
46
+ @@old_logger = ActiveRecord::Base.logger
47
+ ActiveRecord::Base.logger = nil
48
+ end
49
+
50
+ def reenable_logger
51
+ ActiveRecord::Base.logger = @@old_logger
52
+ end
53
+ end
54
+
55
+ class Load
56
+ def self.load(io, truncate = true)
57
+ ActiveRecord::Base.connection.transaction do
58
+ load_documents(io, truncate)
59
+ end
60
+ end
61
+
62
+ def self.truncate_table(table)
63
+ begin
64
+ ActiveRecord::Base.connection.execute("TRUNCATE #{SerializationHelper::Utils.quote_table(table)}")
65
+ rescue Exception
66
+ ActiveRecord::Base.connection.execute("DELETE FROM #{SerializationHelper::Utils.quote_table(table)}")
67
+ end
68
+ end
69
+
70
+ def self.load_table(table, data, truncate = true)
71
+ column_names = data['columns']
72
+ if truncate
73
+ truncate_table(table)
74
+ end
75
+ load_records(table, column_names, data['records'])
76
+ reset_pk_sequence!(table)
77
+ end
78
+
79
+ def self.load_records(table, column_names, records)
80
+ if column_names.nil?
81
+ return
82
+ end
83
+ columns = column_names.map{|cn| ActiveRecord::Base.connection.columns(table).detect{|c| c.name == cn}}
84
+ quoted_column_names = column_names.map { |column| ActiveRecord::Base.connection.quote_column_name(column) }.join(',')
85
+ quoted_table_name = SerializationHelper::Utils.quote_table(table)
86
+ records.each do |record|
87
+ quoted_values = record.zip(columns).map{|c| ActiveRecord::Base.connection.quote(c.first, c.last)}.join(',')
88
+ ActiveRecord::Base.connection.execute("INSERT INTO #{quoted_table_name} (#{quoted_column_names}) VALUES (#{quoted_values})")
89
+ end
90
+ end
91
+
92
+ def self.reset_pk_sequence!(table_name)
93
+ if ActiveRecord::Base.connection.respond_to?(:reset_pk_sequence!)
94
+ ActiveRecord::Base.connection.reset_pk_sequence!(table_name)
95
+ end
96
+ end
97
+
98
+
99
+ end
100
+
101
+ module Utils
102
+
103
+ def self.unhash(hash, keys)
104
+ keys.map { |key| hash[key] }
105
+ end
106
+
107
+ def self.unhash_records(records, keys)
108
+ records.each_with_index do |record, index|
109
+ records[index] = unhash(record, keys)
110
+ end
111
+
112
+ records
113
+ end
114
+
115
+ def self.convert_booleans(records, columns)
116
+ records.each do |record|
117
+ columns.each do |column|
118
+ next if is_boolean(record[column])
119
+ record[column] = convert_boolean(record[column])
120
+ end
121
+ end
122
+ records
123
+ end
124
+
125
+ def self.convert_boolean(value)
126
+ ['t', '1', true, 1].include?(value)
127
+ end
128
+
129
+ def self.boolean_columns(table)
130
+ columns = ActiveRecord::Base.connection.columns(table).reject { |c| silence_warnings { c.type != :boolean } }
131
+ columns.map { |c| c.name }
132
+ end
133
+
134
+ def self.is_boolean(value)
135
+ value.kind_of?(TrueClass) or value.kind_of?(FalseClass)
136
+ end
137
+
138
+ def self.quote_table(table)
139
+ ActiveRecord::Base.connection.quote_table_name(table)
140
+ end
141
+
142
+ end
143
+
144
+ class Dump
145
+ class << self
146
+ attr_accessor :filter_table_names
147
+ end
148
+
149
+ def self.before_table(io, table)
150
+
151
+ end
152
+
153
+ def self.dump(io)
154
+ tables.each do |table|
155
+ before_table(io, table)
156
+ dump_table(io, table)
157
+ after_table(io, table)
158
+ end
159
+ end
160
+
161
+ def self.after_table(io, table)
162
+
163
+ end
164
+
165
+ def self.tables
166
+ all_tables = ActiveRecord::Base.connection.tables.reject { |table| ['schema_info', 'schema_migrations'].include?(table) }
167
+
168
+ filter_table_names ? all_tables.grep(Regexp.new(filter_table_names)) : all_tables
169
+ end
170
+
171
+ def self.dump_table(io, table)
172
+ return if table_record_count(table).zero?
173
+
174
+ dump_table_columns(io, table)
175
+ dump_table_records(io, table)
176
+ end
177
+
178
+ def self.table_column_names(table)
179
+ ActiveRecord::Base.connection.columns(table).map { |c| c.name }
180
+ end
181
+
182
+
183
+ def self.each_table_page(table, records_per_page=1000)
184
+ total_count = table_record_count(table)
185
+ pages = (total_count.to_f / records_per_page).ceil - 1
186
+ id = table_column_names(table).first
187
+ boolean_columns = SerializationHelper::Utils.boolean_columns(table)
188
+ quoted_table_name = SerializationHelper::Utils.quote_table(table)
189
+
190
+ (0..pages).to_a.each do |page|
191
+ query = Arel::Table.new(table).order(id).skip(records_per_page*page).take(records_per_page).project(Arel.sql('*'))
192
+ records = ActiveRecord::Base.connection.select_all(query.to_sql)
193
+ records = SerializationHelper::Utils.convert_booleans(records, boolean_columns)
194
+ yield records
195
+ end
196
+ end
197
+
198
+ def self.table_record_count(table)
199
+ ActiveRecord::Base.connection.select_one("SELECT COUNT(*) FROM #{SerializationHelper::Utils.quote_table(table)}").values.first.to_i
200
+ end
201
+
202
+ end
203
+
204
+ end
@@ -0,0 +1,50 @@
1
+ namespace :db do
2
+ desc "Dump schema and data to db/schema.rb and db/data.yml"
3
+ task(:dump => [ "db:schema:dump", "db:data:dump" ])
4
+
5
+ desc "Load schema and data from db/schema.rb and db/data.yml"
6
+ task(:load => [ "db:schema:load", "db:data:load" ])
7
+
8
+ namespace :data do
9
+ def db_dump_data_file (extension = "yml")
10
+ "#{Rails.root}/db/data.#{extension}"
11
+ end
12
+
13
+ desc "Dump contents of database to db/data.extension (defaults to yaml)"
14
+ task :dump => :environment do
15
+ format_class = ENV['class'] || "YamlDb::Helper"
16
+ helper = format_class.constantize
17
+ filter = ENV['filter_tables']
18
+ SerializationHelper::Base.new(helper,filter).dump db_dump_data_file helper.extension
19
+ end
20
+
21
+ desc "Dump contents of database to curr_dir_name/tablename.extension (defaults to yaml)"
22
+ task :dump_dir => :environment do
23
+ format_class = ENV['class'] || "YamlDb::Helper"
24
+ dir = ENV['dir'] || "#{Time.now.to_s.gsub(/ /, '_')}"
25
+ filter = ENV['filter_tables']
26
+ SerializationHelper::Base.new(format_class.constantize, filter).dump_to_dir dump_dir("/#{dir}")
27
+ end
28
+
29
+ desc "Dump contents of database to curr_dir_name/tablename.extension (defaults to yaml)"
30
+ task :dump_dir => :environment do
31
+ format_class = ENV['class'] || "YamlDb::Helper"
32
+ dir = ENV['dir'] || "#{Time.now.to_s.gsub(/ /, '_')}"
33
+ SerializationHelper::Base.new(format_class.constantize).dump_to_dir dump_dir("/#{dir}")
34
+ end
35
+
36
+ desc "Load contents of db/data.extension (defaults to yaml) into database"
37
+ task :load => :environment do
38
+ format_class = ENV['class'] || "YamlDb::Helper"
39
+ helper = format_class.constantize
40
+ SerializationHelper::Base.new(helper).load(db_dump_data_file helper.extension)
41
+ end
42
+
43
+ desc "Load contents of db/data_dir into database"
44
+ task :load_dir => :environment do
45
+ dir = ENV['dir'] || "base"
46
+ format_class = ENV['class'] || "YamlDb::Helper"
47
+ SerializationHelper::Base.new(format_class.constantize).load_from_dir dump_dir("/#{dir}")
48
+ end
49
+ end
50
+ end
data/lib/yaml_db.rb ADDED
@@ -0,0 +1,76 @@
1
+ require 'rubygems'
2
+ require 'yaml'
3
+ require 'active_record'
4
+ require 'serialization_helper'
5
+ require 'active_support/core_ext/kernel/reporting'
6
+ require 'rails/railtie'
7
+
8
+ module YamlDb
9
+ module Helper
10
+ def self.loader
11
+ YamlDb::Load
12
+ end
13
+
14
+ def self.dumper
15
+ YamlDb::Dump
16
+ end
17
+
18
+ def self.extension
19
+ "yml"
20
+ end
21
+ end
22
+
23
+
24
+ module Utils
25
+ def self.chunk_records(records)
26
+ yaml = [ records ].to_yaml
27
+ yaml.sub!(/---\s\n|---\n/, '')
28
+ yaml.sub!('- - -', ' - -')
29
+ yaml
30
+ end
31
+
32
+ end
33
+
34
+ class Dump < SerializationHelper::Dump
35
+
36
+ def self.dump_table_columns(io, table)
37
+ io.write("\n")
38
+ io.write({ table => { 'columns' => table_column_names(table) } }.to_yaml)
39
+ end
40
+
41
+ def self.dump_table_records(io, table)
42
+ table_record_header(io)
43
+
44
+ column_names = table_column_names(table)
45
+
46
+ each_table_page(table) do |records|
47
+ rows = SerializationHelper::Utils.unhash_records(records, column_names)
48
+ io.write(YamlDb::Utils.chunk_records(records))
49
+ end
50
+ end
51
+
52
+ def self.table_record_header(io)
53
+ io.write(" records: \n")
54
+ end
55
+
56
+ end
57
+
58
+ class Load < SerializationHelper::Load
59
+ def self.load_documents(io, truncate = true)
60
+ YAML.load_documents(io) do |ydoc|
61
+ ydoc.keys.each do |table_name|
62
+ next if ydoc[table_name].nil?
63
+ load_table(table_name, ydoc[table_name], truncate)
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ class Railtie < Rails::Railtie
70
+ rake_tasks do
71
+ load File.expand_path('../tasks/yaml_db_tasks.rake',
72
+ __FILE__)
73
+ end
74
+ end
75
+
76
+ end
data/spec/base.rb ADDED
@@ -0,0 +1,4 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'rspec'
4
+ require 'yaml_db'
@@ -0,0 +1,61 @@
1
+ require File.dirname(__FILE__) + '/base'
2
+
3
+ describe SerializationHelper::Base do
4
+ def prestub_active_record
5
+
6
+ end
7
+
8
+ before do
9
+ @io = StringIO.new
10
+ silence_warnings { ActiveRecord::Base = mock('ActiveRecord::Base', :null_object => true) }
11
+ ActiveRecord::Base.stub(:connection).and_return(mock('connection'))
12
+ ActiveRecord::Base.connection.stub!(:tables).and_return([ 'mytable', 'schema_info', 'schema_migrations' ])
13
+ end
14
+
15
+ def stub_helper!
16
+ @helper = mock("MyHelper")
17
+ @dumper = mock("MyDumper");
18
+ @loader = mock("MyLoader");
19
+ @helper.stub!(:dumper).and_return(@dumper)
20
+ @helper.stub!(:loader).and_return(@loader)
21
+ @helper.stub!(:extension).and_return("yml")
22
+ @dumper.stub!(:tables).and_return([ActiveRecord::Base.connection.tables[0]])
23
+ @dumper.stub!(:before_table).and_return(nil)
24
+ @dumper.stub!(:after_table).and_return(nil)
25
+ end
26
+
27
+ context "for multi-file dumps" do
28
+ before do
29
+ File.should_receive(:new).once.with("dir_name/mytable.yml", "w").and_return(@io)
30
+ Dir.should_receive(:mkdir).once.with("dir_name")
31
+ stub_helper!
32
+ @dumper.should_receive(:dump_table).once.with(@io, "mytable")
33
+ end
34
+
35
+ it "should create the number of files that there are tables" do
36
+ SerializationHelper::Base.new(@helper).dump_to_dir "dir_name"
37
+ end
38
+
39
+ it "should be able to be configured such as it will dump only selected tables" do
40
+ @dumper.should_receive(:"filter_table_names=").with("table_filter")
41
+ SerializationHelper::Base.new(@helper, "table_filter").dump_to_dir "dir_name"
42
+ end
43
+
44
+ end
45
+
46
+ context "for multi-file loads" do
47
+
48
+ before do
49
+ stub_helper!
50
+ @loader.should_receive(:load).once.with(@io, true)
51
+ File.should_receive(:new).once.with("dir_name/mytable.yml", "r").and_return(@io)
52
+ Dir.stub!(:entries).and_return(["mytable.yml"])
53
+ end
54
+
55
+ it "should insert into then umber of tables that there are files" do
56
+ SerializationHelper::Base.new(@helper).load_from_dir "dir_name"
57
+ end
58
+
59
+ end
60
+
61
+ end
@@ -0,0 +1,111 @@
1
+ require File.dirname(__FILE__) + '/base'
2
+
3
+ describe SerializationHelper::Dump do
4
+
5
+ before(:each) do
6
+ silence_warnings { ActiveRecord::Base = mock('ActiveRecord::Base', :null_object => true) }
7
+ ActiveRecord::Base.stub(:connection).and_return(stub('connection').as_null_object)
8
+ ActiveRecord::Base.connection.stub!(:tables).and_return([ 'mytable', 'schema_info', 'schema_migrations' ])
9
+ ActiveRecord::Base.connection.stub!(:columns).with('mytable').and_return([ mock('a', :name => 'a', :type => :string), mock('b', :name => 'b', :type => :string) ])
10
+ ActiveRecord::Base.connection.stub!(:select_one).and_return({"count"=>"2"})
11
+ ActiveRecord::Base.connection.stub!(:select_all).and_return([ { 'a' => 1, 'b' => 2 }, { 'a' => 3, 'b' => 4 } ])
12
+ SerializationHelper::Utils.stub!(:quote_table).with('mytable').and_return('mytable')
13
+ SerializationHelper::Dump.stub!(:table_record_count).and_return(2)
14
+ Arel::SelectManager.any_instance.stub(:to_sql).and_return("SELECT * FROM mytable")
15
+ end
16
+
17
+ before(:each) do
18
+ File.stub!(:new).with('dump.yml', 'w').and_return(StringIO.new)
19
+ @io = StringIO.new
20
+ end
21
+
22
+ it "should return a list of column names" do
23
+ SerializationHelper::Dump.table_column_names('mytable').should == [ 'a', 'b' ]
24
+ end
25
+
26
+ it "should return a list of tables without the rails schema table" do
27
+ SerializationHelper::Dump.tables.should == ['mytable']
28
+ end
29
+
30
+ it "should return the total number of records in a table" do
31
+ SerializationHelper::Dump.table_record_count('mytable').should == 2
32
+ end
33
+
34
+ it "should return all records from the database and return them when there is only 1 page" do
35
+ SerializationHelper::Dump.each_table_page('mytable') do |records|
36
+ records.should == [ { 'a' => 1, 'b' => 2 }, { 'a' => 3, 'b' => 4 } ]
37
+ end
38
+ end
39
+
40
+ it "should paginate records from the database and return them" do
41
+ ActiveRecord::Base.connection.stub!(:select_all).and_return([ { 'a' => 1, 'b' => 2 } ], [ { 'a' => 3, 'b' => 4 } ])
42
+
43
+ records = [ ]
44
+ SerializationHelper::Dump.each_table_page('mytable', 1) do |page|
45
+ page.size.should == 1
46
+ records.concat(page)
47
+ end
48
+
49
+ records.should == [ { 'a' => 1, 'b' => 2 }, { 'a' => 3, 'b' => 4 } ]
50
+ end
51
+
52
+ it "should dump a table's contents to yaml" do
53
+ SerializationHelper::Dump.should_receive(:dump_table_columns)
54
+ SerializationHelper::Dump.should_receive(:dump_table_records)
55
+ SerializationHelper::Dump.dump_table(@io, 'mytable')
56
+ end
57
+
58
+ it "should not dump a table's contents when the record count is zero" do
59
+ SerializationHelper::Dump.stub!(:table_record_count).with('mytable').and_return(0)
60
+ SerializationHelper::Dump.should_not_receive(:dump_table_columns)
61
+ SerializationHelper::Dump.should_not_receive(:dump_table_records)
62
+ SerializationHelper::Dump.dump_table(@io, 'mytable')
63
+ end
64
+
65
+
66
+ context "when configured to only dump selected tables" do
67
+ before do
68
+ ActiveRecord::Base.connection.stub!(:tables).and_return([ 'mytable1', 'mytable2', 'mytable3', 'schema_info', 'schema_migrations' ])
69
+ end
70
+
71
+ after do
72
+ # Check expected tables to dump
73
+ SerializationHelper::Dump.tables.sort.should == @expected_tables
74
+
75
+ if @expected_tables.size > 0
76
+ @expected_tables.each do |table|
77
+ # Check actual calls to dump_table with expected tables
78
+ SerializationHelper::Dump.should_receive(:dump_table).with(nil, table)
79
+ end
80
+ else
81
+ SerializationHelper::Dump.should_not_receive(:dump_table).with(anything)
82
+ end
83
+
84
+ SerializationHelper::Dump.dump(nil)
85
+
86
+ # Restore default behaviour
87
+ SerializationHelper::Dump.filter_table_names = nil
88
+ end
89
+
90
+ it "should dump every table if filter not set" do
91
+ SerializationHelper::Dump.filter_table_names = nil
92
+ @expected_tables = ['mytable1', 'mytable2', 'mytable3']
93
+ end
94
+
95
+ it "should dump matching tables if filter is set as a matching string" do
96
+ SerializationHelper::Dump.filter_table_names = "mytable"
97
+ @expected_tables = ['mytable1', 'mytable2', 'mytable3']
98
+ end
99
+
100
+ it "should dump matching tables if filter is set as a regular expression string" do
101
+ SerializationHelper::Dump.filter_table_names = "mytable[1-2]"
102
+ @expected_tables = ['mytable1', 'mytable2']
103
+ end
104
+
105
+ it "should not dump any table if filter does not match any table" do
106
+ SerializationHelper::Dump.filter_table_names = "wadustable"
107
+ @expected_tables = []
108
+ end
109
+
110
+ end
111
+ end
@@ -0,0 +1,77 @@
1
+ require File.dirname(__FILE__) + '/base'
2
+
3
+ describe SerializationHelper::Load do
4
+ before do
5
+ SerializationHelper::Utils.stub!(:quote_table).with('mytable').and_return('mytable')
6
+
7
+ silence_warnings { ActiveRecord::Base = mock('ActiveRecord::Base', :null_object => true) }
8
+ ActiveRecord::Base.stub(:connection).and_return(stub('connection').as_null_object)
9
+ ActiveRecord::Base.connection.stub!(:transaction).and_yield
10
+ @io = StringIO.new
11
+ end
12
+
13
+ it "should truncate the table" do
14
+ ActiveRecord::Base.connection.stub!(:execute).with("TRUNCATE mytable").and_return(true)
15
+ ActiveRecord::Base.connection.should_not_receive(:execute).with("DELETE FROM mytable")
16
+ SerializationHelper::Load.truncate_table('mytable')
17
+ end
18
+
19
+ it "should delete the table if truncate throws an exception" do
20
+ ActiveRecord::Base.connection.should_receive(:execute).with("TRUNCATE mytable").and_raise()
21
+ ActiveRecord::Base.connection.should_receive(:execute).with("DELETE FROM mytable").and_return(true)
22
+ SerializationHelper::Load.truncate_table('mytable')
23
+ end
24
+
25
+
26
+ it "should call reset pk sequence if the connection adapter is postgres" do
27
+ ActiveRecord::Base.connection.should_receive(:respond_to?).with(:reset_pk_sequence!).and_return(true)
28
+ ActiveRecord::Base.connection.should_receive(:reset_pk_sequence!).with('mytable')
29
+ SerializationHelper::Load.reset_pk_sequence!('mytable')
30
+ end
31
+
32
+ it "should not call reset pk sequence for other adapters" do
33
+ ActiveRecord::Base.connection.should_receive(:respond_to?).with(:reset_pk_sequence!).and_return(false)
34
+ ActiveRecord::Base.connection.should_not_receive(:reset_pk_sequence!)
35
+ SerializationHelper::Load.reset_pk_sequence!('mytable')
36
+ end
37
+
38
+ it "should insert records into a table" do
39
+ mca = mock('a',:name => 'a')
40
+ mcb = mock('b', :name => 'b')
41
+ ActiveRecord::Base.connection.stub!(:columns).with('mytable').and_return([mca , mcb ])
42
+ ActiveRecord::Base.connection.stub!(:quote_column_name).with('a').and_return('a')
43
+ ActiveRecord::Base.connection.stub!(:quote_column_name).with('b').and_return('b')
44
+ ActiveRecord::Base.connection.stub!(:quote).with(1, mca).and_return("'1'")
45
+ ActiveRecord::Base.connection.stub!(:quote).with(2, mcb).and_return("'2'")
46
+ ActiveRecord::Base.connection.stub!(:quote).with(3, mca).and_return("'3'")
47
+ ActiveRecord::Base.connection.stub!(:quote).with(4, mcb).and_return("'4'")
48
+ ActiveRecord::Base.connection.should_receive(:execute).with("INSERT INTO mytable (a,b) VALUES ('1','2')")
49
+ ActiveRecord::Base.connection.should_receive(:execute).with("INSERT INTO mytable (a,b) VALUES ('3','4')")
50
+
51
+ SerializationHelper::Load.load_records('mytable', ['a', 'b'], [[1, 2], [3, 4]])
52
+ end
53
+
54
+ it "should quote column names that correspond to sql keywords" do
55
+ mca = mock('a',:name => 'a')
56
+ mccount = mock('count', :name => 'count')
57
+ ActiveRecord::Base.connection.stub!(:columns).with('mytable').and_return([mca , mccount ])
58
+ ActiveRecord::Base.connection.stub!(:quote_column_name).with('a').and_return('a')
59
+ ActiveRecord::Base.connection.stub!(:quote_column_name).with('count').and_return('"count"')
60
+ ActiveRecord::Base.connection.stub!(:quote).with(1, mca).and_return("'1'")
61
+ ActiveRecord::Base.connection.stub!(:quote).with(2, mccount).and_return("'2'")
62
+ ActiveRecord::Base.connection.stub!(:quote).with(3, mca).and_return("'3'")
63
+ ActiveRecord::Base.connection.stub!(:quote).with(4, mccount).and_return("'4'")
64
+ ActiveRecord::Base.connection.should_receive(:execute).with("INSERT INTO mytable (a,\"count\") VALUES ('1','2')")
65
+ ActiveRecord::Base.connection.should_receive(:execute).with("INSERT INTO mytable (a,\"count\") VALUES ('3','4')")
66
+
67
+ SerializationHelper::Load.load_records('mytable', ['a', 'count'], [[1, 2], [3, 4]])
68
+ end
69
+
70
+ it "should truncate the table and then load the records into the table" do
71
+ SerializationHelper::Load.should_receive(:truncate_table).with('mytable')
72
+ SerializationHelper::Load.should_receive(:load_records).with('mytable', ['a', 'b'], [[1, 2], [3, 4]])
73
+ SerializationHelper::Load.should_receive(:reset_pk_sequence!).with('mytable')
74
+
75
+ SerializationHelper::Load.load_table('mytable', { 'columns' => [ 'a', 'b' ], 'records' => [[1, 2], [3, 4]] })
76
+ end
77
+ end
@@ -0,0 +1,51 @@
1
+ require File.dirname(__FILE__) + '/base'
2
+
3
+ describe SerializationHelper::Utils, " convert records utility method" do
4
+ before do
5
+ silence_warnings { ActiveRecord::Base = mock('ActiveRecord::Base', :null_object => true) }
6
+ ActiveRecord::Base.stub(:connection).and_return(stub('connection').as_null_object)
7
+ end
8
+
9
+ it "returns an array of hash values using an array of ordered keys" do
10
+ SerializationHelper::Utils.unhash({ 'a' => 1, 'b' => 2 }, [ 'b', 'a' ]).should == [ 2, 1 ]
11
+ end
12
+
13
+ it "should unhash each hash an array using an array of ordered keys" do
14
+ SerializationHelper::Utils.unhash_records([ { 'a' => 1, 'b' => 2 }, { 'a' => 3, 'b' => 4 } ], [ 'b', 'a' ]).should == [ [ 2, 1 ], [ 4, 3 ] ]
15
+ end
16
+
17
+ it "should return true if it is a boolean type" do
18
+ SerializationHelper::Utils.is_boolean(true).should == true
19
+ SerializationHelper::Utils.is_boolean('true').should_not == true
20
+ end
21
+
22
+ it "should return an array of boolean columns" do
23
+ ActiveRecord::Base.connection.stub!(:columns).with('mytable').and_return([ mock('a',:name => 'a',:type => :string), mock('b', :name => 'b',:type => :boolean) ])
24
+ SerializationHelper::Utils.boolean_columns('mytable').should == ['b']
25
+ end
26
+
27
+ it "should quote the table name" do
28
+ ActiveRecord::Base.connection.should_receive(:quote_table_name).with('values').and_return('`values`')
29
+ SerializationHelper::Utils.quote_table('values').should == '`values`'
30
+ end
31
+
32
+ it "should convert ruby booleans to true and false" do
33
+ SerializationHelper::Utils.convert_boolean(true).should == true
34
+ SerializationHelper::Utils.convert_boolean(false).should == false
35
+ end
36
+
37
+ it "should convert ruby string t and f to true and false" do
38
+ SerializationHelper::Utils.convert_boolean('t').should == true
39
+ SerializationHelper::Utils.convert_boolean('f').should == false
40
+ end
41
+
42
+ it "should convert ruby string 1 and 0 to true and false" do
43
+ SerializationHelper::Utils.convert_boolean('1').should == true
44
+ SerializationHelper::Utils.convert_boolean('0').should == false
45
+ end
46
+
47
+ it "should convert ruby integer 1 and 0 to true and false" do
48
+ SerializationHelper::Utils.convert_boolean(1).should == true
49
+ SerializationHelper::Utils.convert_boolean(0).should == false
50
+ end
51
+ end
@@ -0,0 +1,60 @@
1
+ require File.dirname(__FILE__) + '/base'
2
+
3
+ describe YamlDb::Dump do
4
+
5
+ before do
6
+ silence_warnings { ActiveRecord::Base = mock('ActiveRecord::Base', :null_object => true) }
7
+ ActiveRecord::Base.stub(:connection).and_return(stub('connection').as_null_object)
8
+ ActiveRecord::Base.connection.stub!(:tables).and_return([ 'mytable', 'schema_info', 'schema_migrations' ])
9
+ ActiveRecord::Base.connection.stub!(:columns).with('mytable').and_return([ mock('a',:name => 'a', :type => :string), mock('b', :name => 'b', :type => :string) ])
10
+ ActiveRecord::Base.connection.stub!(:select_one).and_return({"count"=>"2"})
11
+ ActiveRecord::Base.connection.stub!(:select_all).and_return([ { 'a' => 1, 'b' => 2 }, { 'a' => 3, 'b' => 4 } ])
12
+ YamlDb::Utils.stub!(:quote_table).with('mytable').and_return('mytable')
13
+ end
14
+
15
+ before(:each) do
16
+ File.stub!(:new).with('dump.yml', 'w').and_return(StringIO.new)
17
+ @io = StringIO.new
18
+ end
19
+
20
+ it "should return a formatted string" do
21
+ YamlDb::Dump.table_record_header(@io)
22
+ @io.rewind
23
+ @io.read.should == " records: \n"
24
+ end
25
+
26
+
27
+ it "should return a yaml string that contains a table header and column names" do
28
+ if RUBY_VERSION.split(".")[1] == "9"
29
+
30
+ YAML::ENGINE.yamler = "syck"
31
+ end
32
+ YamlDb::Dump.stub!(:table_column_names).with('mytable').and_return([ 'a', 'b' ])
33
+ YamlDb::Dump.dump_table_columns(@io, 'mytable')
34
+ @io.rewind
35
+ @io.read.should == <<EOYAML
36
+
37
+ ---
38
+ mytable:
39
+ columns:
40
+ - a
41
+ - b
42
+ EOYAML
43
+ end
44
+
45
+ it "should return dump the records for a table in yaml to a given io stream" do
46
+ Arel::SelectManager.any_instance.stub(:to_sql).and_return("SELECT * FROM mytable")
47
+ YamlDb::Dump.dump_table_records(@io, 'mytable')
48
+ @io.rewind
49
+ @io.read.should == <<EOYAML
50
+ records:
51
+ - - 1
52
+ - 2
53
+ - - 3
54
+ - 4
55
+ EOYAML
56
+ end
57
+
58
+
59
+
60
+ end
@@ -0,0 +1,33 @@
1
+ require File.dirname(__FILE__) + '/base'
2
+ require 'active_support/core_ext/kernel/debugger'
3
+
4
+ describe YamlDb::Load do
5
+ before do
6
+ SerializationHelper::Utils.stub!(:quote_table).with('mytable').and_return('mytable')
7
+
8
+ silence_warnings { ActiveRecord::Base = mock('ActiveRecord::Base', :null_object => true) }
9
+ ActiveRecord::Base.stub(:connection).and_return(stub('connection').as_null_object)
10
+ ActiveRecord::Base.connection.stub!(:transaction).and_yield
11
+ end
12
+
13
+ before(:each) do
14
+ @io = StringIO.new
15
+ end
16
+
17
+
18
+ it "should call load structure for each document in the file" do
19
+ YAML.should_receive(:load_documents).with(@io).and_yield({ 'mytable' => {
20
+ 'columns' => [ 'a', 'b' ],
21
+ 'records' => [[1, 2], [3, 4]]
22
+ } } )
23
+ YamlDb::Load.should_receive(:load_table).with('mytable', { 'columns' => [ 'a', 'b' ], 'records' => [[1, 2], [3, 4]] },true)
24
+ YamlDb::Load.load(@io)
25
+ end
26
+
27
+ it "should not call load structure when the document in the file contains no records" do
28
+ YAML.should_receive(:load_documents).with(@io).and_yield({ 'mytable' => nil })
29
+ YamlDb::Load.should_not_receive(:load_table)
30
+ YamlDb::Load.load(@io)
31
+ end
32
+
33
+ end
@@ -0,0 +1,21 @@
1
+ require File.dirname(__FILE__) + '/base'
2
+
3
+ describe YamlDb::Utils, " convert records utility method" do
4
+
5
+ it "turns an array with one record into a yaml chunk" do
6
+ YamlDb::Utils.chunk_records([ %w(a b) ]).should == <<EOYAML
7
+ - - a
8
+ - b
9
+ EOYAML
10
+ end
11
+
12
+ it "turns an array with two records into a yaml chunk" do
13
+ YamlDb::Utils.chunk_records([ %w(a b), %w(x y) ]).should == <<EOYAML
14
+ - - a
15
+ - b
16
+ - - x
17
+ - y
18
+ EOYAML
19
+ end
20
+
21
+ end
metadata ADDED
@@ -0,0 +1,131 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fm_yaml_db
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.4
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Adam Wiggins
9
+ - Orion Henry
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-09-19 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rails
17
+ requirement: &25514740 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *25514740
26
+ - !ruby/object:Gem::Dependency
27
+ name: rdoc
28
+ requirement: &25513820 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '3.12'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: *25513820
37
+ - !ruby/object:Gem::Dependency
38
+ name: bundler
39
+ requirement: &25512300 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ type: :development
46
+ prerelease: false
47
+ version_requirements: *25512300
48
+ - !ruby/object:Gem::Dependency
49
+ name: jeweler
50
+ requirement: &25536080 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ~>
54
+ - !ruby/object:Gem::Version
55
+ version: 1.8.4
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: *25536080
59
+ - !ruby/object:Gem::Dependency
60
+ name: rspec
61
+ requirement: &25534820 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ type: :development
68
+ prerelease: false
69
+ version_requirements: *25534820
70
+ description: Forked gem from yaml_db - the great DB independent dumper for rails devs
71
+ email: skullzeek@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files:
75
+ - LICENSE.txt
76
+ - README.markdown
77
+ - README.rdoc
78
+ files:
79
+ - .Gemfile.swp
80
+ - .document
81
+ - .travis.yml
82
+ - Gemfile
83
+ - LICENSE.txt
84
+ - README.markdown
85
+ - README.rdoc
86
+ - Rakefile
87
+ - VERSION
88
+ - about.yml
89
+ - fm_yaml_db.gemspec
90
+ - init.rb
91
+ - lib/csv_db.rb
92
+ - lib/serialization_helper.rb
93
+ - lib/tasks/yaml_db_tasks.rake
94
+ - lib/yaml_db.rb
95
+ - spec/base.rb
96
+ - spec/serialization_helper_base_spec.rb
97
+ - spec/serialization_helper_dump_spec.rb
98
+ - spec/serialization_helper_load_spec.rb
99
+ - spec/serialization_utils_spec.rb
100
+ - spec/yaml_dump_spec.rb
101
+ - spec/yaml_load_spec.rb
102
+ - spec/yaml_utils_spec.rb
103
+ homepage: http://github.com/kalabiyau/yaml_db
104
+ licenses:
105
+ - MIT
106
+ post_install_message:
107
+ rdoc_options: []
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ none: false
112
+ requirements:
113
+ - - ! '>='
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ segments:
117
+ - 0
118
+ hash: -2128184371296655799
119
+ required_rubygems_version: !ruby/object:Gem::Requirement
120
+ none: false
121
+ requirements:
122
+ - - ! '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ requirements: []
126
+ rubyforge_project:
127
+ rubygems_version: 1.8.15
128
+ signing_key:
129
+ specification_version: 3
130
+ summary: fork of a great yaml_db gem
131
+ test_files: []