seed_dump_citus 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 589295ccb53fca1a66f410a15a6fce7c179be89a0ab6ce311967bd6a130b12e0
4
+ data.tar.gz: 6649359765019a7faf1ee7f1655565841fd011a8b98ad3714f2d23dd4ff2afed
5
+ SHA512:
6
+ metadata.gz: 3598300d5a6b4f61465ba26708ffc4ce24ac7088a32ff1c329ba3c15f292c80f9f01c80a3545d01b938affe83b826605cf36b40dd3b24a97511c2e0df4f1dda8
7
+ data.tar.gz: be3d6452a2ea1f69cbda6cd48f51d349d3f155d5787db34f4f7e7c6681abbf34d378372a76a762b45a496e051eaefd2fd26037976d34a8cc575674d626106ebe
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,20 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'activesupport', '>= 4'
4
+ gem 'activerecord', '>= 4'
5
+
6
+ group :development, :test do
7
+ gem 'byebug', '~> 2.0'
8
+ gem 'factory_bot', '~> 4.8.2'
9
+ gem 'activerecord-import', '~> 0.4'
10
+ end
11
+
12
+ group :development do
13
+ gem 'jeweler', '~> 2.0'
14
+ end
15
+
16
+ group :test do
17
+ gem 'rspec', '~> 3.7.0'
18
+ gem 'sqlite3', '~> 1.0'
19
+ gem 'database_cleaner', '~> 1.0'
20
+ end
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013 Ryan Oblak
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,131 @@
1
+ Seed Dump
2
+ ========
3
+
4
+ Seed Dump is a Rails 4 and 5 plugin that adds a rake task named `db:seed:dump`.
5
+
6
+ It allows you to create seed data files from the existing data in your database.
7
+
8
+ You can also use Seed Dump from the Rails console. See below for usage examples.
9
+
10
+ Note: if you want to use Seed Dump with Rails 3 or earlier, use [version 0.5.3](http://rubygems.org/gems/seed_dump/versions/0.5.3).
11
+
12
+ Installation
13
+ ------------
14
+
15
+ Add it to your Gemfile with:
16
+ ```ruby
17
+ gem 'seed_dump_citus'
18
+ ```
19
+ Or install it by hand:
20
+ ```sh
21
+ $ gem install seed_dump
22
+ ```
23
+ Examples
24
+ --------
25
+
26
+ ### Rake task
27
+
28
+ Dump all data directly to `db/seeds.rb`:
29
+ ```sh
30
+ $ rake db:seed:dump
31
+ ```
32
+ Result:
33
+ ```ruby
34
+ Product.create!([
35
+ { category_id: 1, description: "Long Sleeve Shirt", name: "Long Sleeve Shirt" },
36
+ { category_id: 3, description: "Plain White Tee Shirt", name: "Plain T-Shirt" }
37
+ ])
38
+ User.create!([
39
+ { password: "123456", username: "test_1" },
40
+ { password: "234567", username: "test_2" }
41
+ ])
42
+ ```
43
+
44
+ Dump only data from the users table and dump a maximum of 1 record:
45
+ ```sh
46
+ $ rake db:seed:dump MODELS=User LIMIT=1
47
+ ```
48
+
49
+ Result:
50
+ ```ruby
51
+ User.create!([
52
+ { password: "123456", username: "test_1" }
53
+ ])
54
+ ```
55
+
56
+ Append to `db/seeds.rb` instead of overwriting it:
57
+ ```sh
58
+ rake db:seed:dump APPEND=true
59
+ ```
60
+
61
+ Use another output file instead of `db/seeds.rb`:
62
+ ```sh
63
+ rake db:seed:dump FILE=db/seeds/users.rb
64
+ ```
65
+
66
+ Exclude `name` and `age` from the dump:
67
+ ```sh
68
+ rake db:seed:dump EXCLUDE=name,age
69
+ ```
70
+
71
+ There are more options that can be set— see below for all of them.
72
+
73
+ ### Console
74
+
75
+ Output a dump of all User records:
76
+ ```ruby
77
+ irb(main):001:0> puts SeedDump.dump(User)
78
+ User.create!([
79
+ { password: "123456", username: "test_1" },
80
+ { password: "234567", username: "test_2" }
81
+ ])
82
+ ```
83
+
84
+ Write the dump to a file:
85
+ ```ruby
86
+ irb(main):002:0> SeedDump.dump(User, file: 'db/seeds.rb')
87
+ ```
88
+
89
+ Append the dump to a file:
90
+ ```ruby
91
+ irb(main):003:0> SeedDump.dump(User, file: 'db/seeds.rb', append: true)
92
+ ```
93
+
94
+ Exclude `name` and `age` from the dump:
95
+ ```ruby
96
+ irb(main):004:0> SeedDump.dump(User, exclude: [:name, :age])
97
+ ```
98
+
99
+ Options are specified as a Hash for the second argument.
100
+
101
+ In the console, any relation of ActiveRecord rows can be dumped (not individual objects though)
102
+ ```ruby
103
+ irb(main):001:0> puts SeedDump.dump(User.where(is_admin: false))
104
+ User.create!([
105
+ { password: "123456", username: "test_1", is_admin: false },
106
+ { password: "234567", username: "test_2", is_admin: false }
107
+ ])
108
+ ```
109
+
110
+ Options
111
+ -------
112
+
113
+ Options are common to both the Rake task and the console, except where noted.
114
+
115
+ `append`: If set to `true`, append the data to the file instead of overwriting it. Default: `false`.
116
+
117
+ `batch_size`: Controls the number of records that are written to file at a given time. Default: 1000. If you're running out of memory when dumping, try decreasing this. If things are dumping too slow, trying increasing this.
118
+
119
+ `exclude`: Attributes to be excluded from the dump. Pass a comma-separated list to the Rake task (i.e. `name,age`) and an array on the console (i.e. `[:name, :age]`). Default: `[:id, :created_at, :updated_at]`.
120
+
121
+ `file`: Write to the specified output file. The Rake task default is `db/seeds.rb`. The console returns the dump as a string by default.
122
+
123
+ `import`: If `true`, output will be in the format needed by the [activerecord-import](https://github.com/zdennis/activerecord-import) gem, rather than the default format. Default: `false`.
124
+
125
+ `limit`: Dump no more than this amount of data. Default: no limit. Rake task only. In the console just pass in an ActiveRecord::Relation with the appropriate limit (e.g. `SeedDump.dump(User.limit(5))`).
126
+
127
+ `conditions`: Dump only specific records. In the console just pass in an ActiveRecord::Relation with the appropriate conditions (e.g. `SeedDump.dump(User.where(state: :active))`).
128
+
129
+ `model[s]`: Restrict the dump to the specified comma-separated list of models. Default: all models. If you are using a Rails engine you can dump a specific model by passing "EngineName::ModelName". Rake task only. Example: `rake db:seed:dump MODELS="User, Position, Function"`
130
+
131
+ `models_exclude`: Exclude the specified comma-separated list of models from the dump. Default: no models excluded. Rake task only. Example: `rake db:seed:dump MODELS_EXCLUDE="User"`
data/Rakefile ADDED
@@ -0,0 +1,32 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "seed_dump_citus"
8
+ gem.summary = "{Seed Dumper for Rails}"
9
+ gem.description = %Q{Dump (parts) of your database to db/seeds.rb to get a headstart creating a meaningful seeds.rb file}
10
+ gem.email = 'rroblak@gmail.com'
11
+ gem.homepage = 'https://github.com/rroblak/seed_dump_citus'
12
+ gem.authors = ['Rob Halff', 'Ryan Oblak']
13
+ gem.license = 'MIT'
14
+ end
15
+ Jeweler::GemcutterTasks.new
16
+ rescue LoadError
17
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
18
+ end
19
+
20
+ require 'rdoc/task'
21
+ Rake::RDocTask.new do |rdoc|
22
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
23
+
24
+ rdoc.rdoc_dir = 'rdoc'
25
+ rdoc.title = "seed_dump_citus #{version}"
26
+ rdoc.rdoc_files.include('README*')
27
+ rdoc.rdoc_files.include('lib/**/*.rb')
28
+ end
29
+
30
+ require 'rspec/core/rake_task'
31
+ RSpec::Core::RakeTask.new(:spec)
32
+ task :default => :spec
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 3.3.2
@@ -0,0 +1,11 @@
1
+ require 'ipaddr'
2
+ require 'seed_dump_citus/dump_methods/enumeration'
3
+ require 'seed_dump_citus/dump_methods'
4
+ require 'seed_dump_citus/environment'
5
+
6
+ class SeedDumpCitus
7
+ extend Environment
8
+ extend DumpMethods
9
+
10
+ require 'seed_dump_citus/railtie' if defined?(Rails)
11
+ end
@@ -0,0 +1,129 @@
1
+ class SeedDumpCitus
2
+ module DumpMethods
3
+ include Enumeration
4
+
5
+ def dump(records, options = {})
6
+ return nil if records.count == 0
7
+
8
+ io = open_io(options)
9
+
10
+ write_records_to_io(records, io, options)
11
+
12
+ ensure
13
+ io.close if io.present?
14
+ end
15
+
16
+ private
17
+
18
+ def dump_record(record, options)
19
+ attribute_strings = []
20
+
21
+ # We select only string attribute names to avoid conflict
22
+ # with the composite_primary_keys gem (it returns composite
23
+ # primary key attribute names as hashes).
24
+ record.attributes.select {|key| key.is_a?(String) || key.is_a?(Symbol) }.each do |attribute, value|
25
+ attribute_strings << dump_attribute_new(attribute, value, options) unless options[:exclude].include?(attribute.to_sym)
26
+ end
27
+
28
+ open_character, close_character = options[:import] ? ['[', ']'] : ['{', '}']
29
+
30
+ "#{open_character}#{attribute_strings.join(", ")}#{close_character}"
31
+ end
32
+
33
+ def dump_attribute_new(attribute, value, options)
34
+ options[:import] ? value_to_s(value) : "#{attribute}: #{value_to_s(value)}"
35
+ end
36
+
37
+ def value_to_s(value)
38
+ value = case value
39
+ when BigDecimal, IPAddr
40
+ value.to_s
41
+ when Date, Time, DateTime
42
+ value.to_s(:db)
43
+ when Range
44
+ range_to_string(value)
45
+ when ->(v) { v.class.ancestors.map(&:to_s).include?('RGeo::Feature::Instance') }
46
+ value.to_s
47
+ else
48
+ value
49
+ end
50
+
51
+ value.inspect
52
+ end
53
+
54
+ def range_to_string(object)
55
+ from = object.begin.respond_to?(:infinite?) && object.begin.infinite? ? '' : object.begin
56
+ to = object.end.respond_to?(:infinite?) && object.end.infinite? ? '' : object.end
57
+ "[#{from},#{to}#{object.exclude_end? ? ')' : ']'}"
58
+ end
59
+
60
+ def open_io(options)
61
+ if options[:file].present?
62
+ mode = options[:append] ? 'a+' : 'w+'
63
+
64
+ File.open(options[:file], mode)
65
+ else
66
+ StringIO.new('', 'w+')
67
+ end
68
+ end
69
+
70
+ def write_records_to_io(records, io, options)
71
+ options[:exclude] ||= [:id, :created_at, :updated_at]
72
+
73
+ method = options[:import] ? 'import' : 'create!'
74
+ io.write("#{model_for(records)}.#{method}(")
75
+ if options[:import]
76
+ io.write("[#{attribute_names(records, options).map {|name| name.to_sym.inspect}.join(', ')}], ")
77
+ end
78
+ io.write("[\n ")
79
+
80
+ enumeration_method = if records.is_a?(ActiveRecord::Relation) || records.is_a?(Class)
81
+ :active_record_enumeration
82
+ else
83
+ :enumerable_enumeration
84
+ end
85
+
86
+ send(enumeration_method, records, io, options) do |record_strings, last_batch|
87
+ io.write(record_strings.join(",\n "))
88
+
89
+ io.write(",\n ") unless last_batch
90
+ end
91
+
92
+ io.write("\n]#{active_record_import_options(options)})\n")
93
+
94
+ if options[:file].present?
95
+ nil
96
+ else
97
+ io.rewind
98
+ io.read
99
+ end
100
+ end
101
+
102
+ def active_record_import_options(options)
103
+ return unless options[:import] && options[:import].is_a?(Hash)
104
+
105
+ ', ' + options[:import].map { |key, value| "#{key}: #{value}" }.join(', ')
106
+ end
107
+
108
+ def attribute_names(records, options)
109
+ attribute_names = if records.is_a?(ActiveRecord::Relation) || records.is_a?(Class)
110
+ records.attribute_names
111
+ else
112
+ records[0].attribute_names
113
+ end
114
+
115
+ attribute_names.select {|name| !options[:exclude].include?(name.to_sym)}
116
+ end
117
+
118
+ def model_for(records)
119
+ if records.is_a?(Class)
120
+ records
121
+ elsif records.respond_to?(:model)
122
+ records.model
123
+ else
124
+ records[0].class
125
+ end
126
+ end
127
+
128
+ end
129
+ end
@@ -0,0 +1,78 @@
1
+ class SeedDumpCitus
2
+ module DumpMethods
3
+ module Enumeration
4
+ def active_record_enumeration(records, io, options)
5
+ # If the records don't already have an order,
6
+ # order them by primary key ascending.
7
+ if !records.respond_to?(:arel) || records.arel.orders.blank?
8
+ records.order("#{records.quoted_table_name}.#{records.quoted_primary_key} ASC")
9
+ end
10
+
11
+ num_of_batches, batch_size, last_batch_size = batch_params_from(records, options)
12
+
13
+ # Loop through each batch
14
+ TransactionAccessor.acceptable_non_sharded_read do
15
+
16
+ (1..num_of_batches).each do |batch_number|
17
+
18
+ record_strings = []
19
+
20
+ last_batch = (batch_number == num_of_batches)
21
+
22
+ cur_batch_size = if last_batch
23
+ last_batch_size
24
+ else
25
+ batch_size
26
+ end
27
+
28
+ # Loop through the records of the current batch
29
+ records.offset((batch_number - 1) * batch_size).limit(cur_batch_size).each do |record|
30
+ record_strings << dump_record(record, options)
31
+ end
32
+
33
+ yield record_strings, last_batch
34
+ end
35
+ end
36
+ end
37
+
38
+ def enumerable_enumeration(records, io, options)
39
+ num_of_batches, batch_size = batch_params_from(records, options)
40
+
41
+ record_strings = []
42
+
43
+ batch_number = 1
44
+
45
+ records.each_with_index do |record, i|
46
+ record_strings << dump_record(record, options)
47
+
48
+ last_batch = (i == records.length - 1)
49
+
50
+ if (record_strings.length == batch_size) || last_batch
51
+ yield record_strings, last_batch
52
+
53
+ record_strings = []
54
+ batch_number += 1
55
+ end
56
+ end
57
+ end
58
+
59
+ def batch_params_from(records, options)
60
+ batch_size = batch_size_from(records, options)
61
+
62
+ count = records.count
63
+
64
+ remainder = count % batch_size
65
+
66
+ [((count.to_f / batch_size).ceil), batch_size, (remainder == 0 ? batch_size : remainder)]
67
+ end
68
+
69
+ def batch_size_from(records, options)
70
+ if options[:batch_size].present?
71
+ options[:batch_size].to_i
72
+ else
73
+ 1000
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end