phil_columns 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +257 -0
- data/Rakefile +6 -0
- data/bin/phil_columns +6 -0
- data/lib/phil_columns.rb +27 -0
- data/lib/phil_columns/archivist.rb +36 -0
- data/lib/phil_columns/cli.rb +162 -0
- data/lib/phil_columns/cli/generate.rb +43 -0
- data/lib/phil_columns/cli/list.rb +68 -0
- data/lib/phil_columns/command.rb +14 -0
- data/lib/phil_columns/command/base.rb +64 -0
- data/lib/phil_columns/command/empty.rb +30 -0
- data/lib/phil_columns/command/generate.rb +9 -0
- data/lib/phil_columns/command/generate/seed.rb +25 -0
- data/lib/phil_columns/command/generator.rb +45 -0
- data/lib/phil_columns/command/install.rb +65 -0
- data/lib/phil_columns/command/list.rb +10 -0
- data/lib/phil_columns/command/list/tagged_with.rb +27 -0
- data/lib/phil_columns/command/list/tags.rb +37 -0
- data/lib/phil_columns/command/mulligan.rb +22 -0
- data/lib/phil_columns/command/seed.rb +44 -0
- data/lib/phil_columns/configuration.rb +88 -0
- data/lib/phil_columns/error.rb +5 -0
- data/lib/phil_columns/filter.rb +66 -0
- data/lib/phil_columns/migrator.rb +80 -0
- data/lib/phil_columns/output.rb +29 -0
- data/lib/phil_columns/railtie.rb +18 -0
- data/lib/phil_columns/seed.rb +37 -0
- data/lib/phil_columns/seed_utils.rb +59 -0
- data/lib/phil_columns/seeder.rb +58 -0
- data/lib/phil_columns/version.rb +3 -0
- data/lib/phil_columns/with_backend.rb +21 -0
- data/phil_columns.gemspec +30 -0
- data/spec/spec_helper.rb +2 -0
- data/templates/seed_class.erb +11 -0
- metadata +200 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
module PhilColumns
|
4
|
+
class Cli
|
5
|
+
class Generate < Thor
|
6
|
+
|
7
|
+
def self.banner( command, namespace=nil, subcommand=false )
|
8
|
+
return "#{basename} generate help [SUBCOMMAND]" if command.name == 'help'
|
9
|
+
"#{basename} #{command.usage}"
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "generate seed NAME", "Generate a seed class"
|
13
|
+
long_desc <<-LONGDESC
|
14
|
+
Generate a seed file with name NAME.
|
15
|
+
LONGDESC
|
16
|
+
def seed( name )
|
17
|
+
PhilColumns::Command::Generate::Seed.new( options.merge( seed_name: name )).execute
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.handle_argument_error( command, error, _, __ )
|
21
|
+
method = "handle_argument_error_for_#{command.name}"
|
22
|
+
|
23
|
+
if respond_to?( method )
|
24
|
+
send( method, command, error )
|
25
|
+
else
|
26
|
+
handle_argument_error_default( command, error )
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.handle_argument_error_default( command, error )
|
31
|
+
$stdout.puts "Incorrect usage of generate subcommand: #{command.name}"
|
32
|
+
$stdout.puts " #{error.message}", ''
|
33
|
+
$stdout.puts "For correct usage:"
|
34
|
+
$stdout.puts " phil_columns generate help #{command.name}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.handle_no_command_error( name )
|
38
|
+
$stdout.puts "Unrecognized command: #{name}"
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
module PhilColumns
|
4
|
+
class Cli
|
5
|
+
class List < Thor
|
6
|
+
|
7
|
+
def self.banner( command, namespace=nil, subcommand=false )
|
8
|
+
return "#{basename} list help [SUBCOMMAND]" if command.name == 'help'
|
9
|
+
"#{basename} #{command.usage}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.env_option
|
13
|
+
option :env, type: :string, aliases: '-e', desc: "The environment to execute in", default: 'development'
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.operation_option
|
17
|
+
option :operation, type: :string, aliases: '-o', desc: "The operation: all or any", default: 'any'
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "list tagged-with TAGS", "List all seeds tagged with tag(s)"
|
21
|
+
long_desc <<-LONGDESC
|
22
|
+
List all seeds tagged with tag(s) within specified environment.
|
23
|
+
|
24
|
+
With --env[-e] option, the environment is overridden. Default: development.
|
25
|
+
|
26
|
+
With --operation[-o] option, the tag filtering operation is overridden. Default: any.
|
27
|
+
LONGDESC
|
28
|
+
env_option
|
29
|
+
operation_option
|
30
|
+
def tagged_with( *tags )
|
31
|
+
PhilColumns::Command::List::TaggedWith.new( options.merge( tags: tags )).execute
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "list tags", "List all tags from all seeds."
|
35
|
+
long_desc <<-LONGDESC
|
36
|
+
List all tags from all seeds within specified environment.
|
37
|
+
|
38
|
+
With --env[-e] option, the environment is overridden. Default: development.
|
39
|
+
LONGDESC
|
40
|
+
env_option
|
41
|
+
def tags
|
42
|
+
PhilColumns::Command::List::Tags.new( options ).execute
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.handle_argument_error( command, error, _, __ )
|
46
|
+
method = "handle_argument_error_for_#{command.name}"
|
47
|
+
|
48
|
+
if respond_to?( method )
|
49
|
+
send( method, command, error )
|
50
|
+
else
|
51
|
+
handle_argument_error_default( command, error )
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.handle_argument_error_default( command, error )
|
56
|
+
$stdout.puts "Incorrect usage of list subcommand: #{command.name}"
|
57
|
+
$stdout.puts " #{error.message}", ''
|
58
|
+
$stdout.puts "For correct usage:"
|
59
|
+
$stdout.puts " phil_columns list help #{command.name}"
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.handle_no_command_error( name )
|
63
|
+
$stdout.puts "Unrecognized command: #{name}"
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module PhilColumns
|
2
|
+
module Command
|
3
|
+
|
4
|
+
autoload :Base, 'phil_columns/command/base'
|
5
|
+
autoload :Empty, 'phil_columns/command/empty'
|
6
|
+
autoload :Generate, 'phil_columns/command/generate'
|
7
|
+
autoload :Generator, 'phil_columns/command/generator'
|
8
|
+
autoload :Install, 'phil_columns/command/install'
|
9
|
+
autoload :Mulligan, 'phil_columns/command/mulligan'
|
10
|
+
autoload :List, 'phil_columns/command/list'
|
11
|
+
autoload :Seed, 'phil_columns/command/seed'
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module PhilColumns
|
2
|
+
module Command
|
3
|
+
class Base
|
4
|
+
|
5
|
+
include Thor::Actions
|
6
|
+
include PhilColumns::Output
|
7
|
+
|
8
|
+
def initialize( options )
|
9
|
+
@options = options
|
10
|
+
end
|
11
|
+
|
12
|
+
def execute
|
13
|
+
raise NotImplementedError, "You must implement #{self.class.name}#execute"
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
|
18
|
+
attr_reader :options
|
19
|
+
|
20
|
+
def archivist
|
21
|
+
@archivist ||= PhilColumns::Archivist.new
|
22
|
+
end
|
23
|
+
|
24
|
+
def migrator
|
25
|
+
@migrator ||= PhilColumns::Migrator.new( config )
|
26
|
+
end
|
27
|
+
|
28
|
+
def seeder
|
29
|
+
@seeder ||= PhilColumns::Seeder.new( config )
|
30
|
+
end
|
31
|
+
|
32
|
+
def dry_run?
|
33
|
+
config.dry_run
|
34
|
+
end
|
35
|
+
|
36
|
+
def config
|
37
|
+
@config = Configuration.new( options )
|
38
|
+
end
|
39
|
+
|
40
|
+
def config_file_path
|
41
|
+
'.phil_columns'
|
42
|
+
end
|
43
|
+
|
44
|
+
def base_path
|
45
|
+
Pathname.new( Dir.pwd )
|
46
|
+
end
|
47
|
+
|
48
|
+
def load_environment
|
49
|
+
return if env_files.nil? || env_files.empty?
|
50
|
+
|
51
|
+
say 'Loading environment ...'
|
52
|
+
|
53
|
+
env_files.each do |file|
|
54
|
+
require file.expand_path
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def env_files
|
59
|
+
@env_files ||= config.env_files.map { |f| Pathname.new f }
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module PhilColumns
|
2
|
+
module Command
|
3
|
+
class Empty < Base
|
4
|
+
|
5
|
+
def execute
|
6
|
+
load_environment
|
7
|
+
|
8
|
+
table_classes.each do |klass|
|
9
|
+
confirm "Deleting from #{klass.name.tableize} ... " do
|
10
|
+
klass.delete_all
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
archivist.clear_seeds
|
15
|
+
migrator.clear_migrations_table
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
def table_classes
|
21
|
+
tables.map { |t| t.classify.constantize }
|
22
|
+
end
|
23
|
+
|
24
|
+
def tables
|
25
|
+
migrator.tables.sort
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'ostruct'
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
module PhilColumns
|
6
|
+
module Command
|
7
|
+
module Generate
|
8
|
+
class Seed < Generator
|
9
|
+
|
10
|
+
def execute
|
11
|
+
write "Generating seed #{seed_filepath} ... "
|
12
|
+
erb_template_to_file( template_filepath, seed_filepath, class_name: seed_class_name )
|
13
|
+
say_ok
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
|
18
|
+
def template_filepath
|
19
|
+
'templates/seed_class.erb'
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'ostruct'
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
module PhilColumns
|
6
|
+
module Command
|
7
|
+
class Generator < Base
|
8
|
+
|
9
|
+
protected
|
10
|
+
|
11
|
+
def template_filepath
|
12
|
+
raise NotImplementedError
|
13
|
+
end
|
14
|
+
|
15
|
+
def erb_template_to_file( template_filepath, dest_filepath, namespace )
|
16
|
+
template_filepath = template_filepath.is_a?( Pathname ) ?
|
17
|
+
template_filepath :
|
18
|
+
Pathname.new( template_filepath )
|
19
|
+
namespace = OpenStruct.new( namespace )
|
20
|
+
|
21
|
+
File.open( dest_filepath, 'w' ) do |f|
|
22
|
+
result = ERB.new( template_filepath.read ).result( namespace.instance_eval { binding } )
|
23
|
+
f.write( result )
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def seed_filepath
|
28
|
+
@seed_filepath ||= File.join( config.seeds_path, seed_name )
|
29
|
+
end
|
30
|
+
|
31
|
+
def seed_class_name
|
32
|
+
@seed_class_name ||= config.seed_name.camelize
|
33
|
+
end
|
34
|
+
|
35
|
+
def seed_name
|
36
|
+
@seed_name ||= "#{timestamp}_#{config.seed_name}.rb"
|
37
|
+
end
|
38
|
+
|
39
|
+
def timestamp
|
40
|
+
@timestamp ||= Time.now.strftime( '%Y%m%d%H%M%S' )
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'pathname'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
|
6
|
+
module PhilColumns
|
7
|
+
module Command
|
8
|
+
class Install < Base
|
9
|
+
|
10
|
+
def execute
|
11
|
+
say "Installing phil columns", :cyan
|
12
|
+
write "Creating seeds directory: #{seeds_path} ... "
|
13
|
+
make_seeds_directory
|
14
|
+
say_ok
|
15
|
+
write "Writing config file: #{config_file_path} ... "
|
16
|
+
write_config_file
|
17
|
+
say_ok
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def make_seeds_directory
|
23
|
+
FileUtils.mkdir_p( seeds_path )
|
24
|
+
end
|
25
|
+
|
26
|
+
def write_config_file
|
27
|
+
config.save_to_file
|
28
|
+
end
|
29
|
+
|
30
|
+
def config
|
31
|
+
@config = Configuration.new( config_defaults )
|
32
|
+
end
|
33
|
+
|
34
|
+
def config_defaults
|
35
|
+
defaults = rails? ? rails_default_settings : {}
|
36
|
+
defaults.merge(
|
37
|
+
default_tags: [
|
38
|
+
'default'
|
39
|
+
],
|
40
|
+
schema_load_strategy: 'load',
|
41
|
+
schema_unload_strategy: 'drop',
|
42
|
+
seeds_path: seeds_path.to_s,
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
def seeds_path
|
47
|
+
rel = rails? ? 'db/seeds' : options[:seeds_path]
|
48
|
+
Pathname.new( rel )
|
49
|
+
end
|
50
|
+
|
51
|
+
def rails?
|
52
|
+
options[:rails]
|
53
|
+
end
|
54
|
+
|
55
|
+
def rails_default_settings
|
56
|
+
{
|
57
|
+
'env_files' => [
|
58
|
+
'config/environment'
|
59
|
+
]
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module PhilColumns
|
2
|
+
module Command
|
3
|
+
module List
|
4
|
+
class TaggedWith < Base
|
5
|
+
|
6
|
+
include SeedUtils
|
7
|
+
|
8
|
+
def execute
|
9
|
+
load_seeds
|
10
|
+
|
11
|
+
say "#{config.env.titlecase} seeds tagged with #{config.operation} #{config.tags.inspect}:", :cyan
|
12
|
+
|
13
|
+
filter.send( "calculate_seed_set_#{config.operation}" ).each do |seed_meta|
|
14
|
+
say seed_meta.filepath
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
def filter
|
21
|
+
@filter ||= Filter.new( config )
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'ostruct'
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
module PhilColumns
|
6
|
+
module Command
|
7
|
+
module List
|
8
|
+
class Tags < Base
|
9
|
+
|
10
|
+
include SeedUtils
|
11
|
+
|
12
|
+
def execute
|
13
|
+
load_seeds
|
14
|
+
|
15
|
+
each_seed_meta_for_current_env do |seed_meta|
|
16
|
+
tags << seed_meta.tags
|
17
|
+
end
|
18
|
+
|
19
|
+
say "#{config.env.titlecase} environment seeds use tags:", :cyan
|
20
|
+
|
21
|
+
tags.flatten.uniq.sort.each do |tag|
|
22
|
+
say tag
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
attr_reader :tags
|
29
|
+
|
30
|
+
def tags
|
31
|
+
@tags ||= []
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|