phil_columns 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +3 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +257 -0
  10. data/Rakefile +6 -0
  11. data/bin/phil_columns +6 -0
  12. data/lib/phil_columns.rb +27 -0
  13. data/lib/phil_columns/archivist.rb +36 -0
  14. data/lib/phil_columns/cli.rb +162 -0
  15. data/lib/phil_columns/cli/generate.rb +43 -0
  16. data/lib/phil_columns/cli/list.rb +68 -0
  17. data/lib/phil_columns/command.rb +14 -0
  18. data/lib/phil_columns/command/base.rb +64 -0
  19. data/lib/phil_columns/command/empty.rb +30 -0
  20. data/lib/phil_columns/command/generate.rb +9 -0
  21. data/lib/phil_columns/command/generate/seed.rb +25 -0
  22. data/lib/phil_columns/command/generator.rb +45 -0
  23. data/lib/phil_columns/command/install.rb +65 -0
  24. data/lib/phil_columns/command/list.rb +10 -0
  25. data/lib/phil_columns/command/list/tagged_with.rb +27 -0
  26. data/lib/phil_columns/command/list/tags.rb +37 -0
  27. data/lib/phil_columns/command/mulligan.rb +22 -0
  28. data/lib/phil_columns/command/seed.rb +44 -0
  29. data/lib/phil_columns/configuration.rb +88 -0
  30. data/lib/phil_columns/error.rb +5 -0
  31. data/lib/phil_columns/filter.rb +66 -0
  32. data/lib/phil_columns/migrator.rb +80 -0
  33. data/lib/phil_columns/output.rb +29 -0
  34. data/lib/phil_columns/railtie.rb +18 -0
  35. data/lib/phil_columns/seed.rb +37 -0
  36. data/lib/phil_columns/seed_utils.rb +59 -0
  37. data/lib/phil_columns/seeder.rb +58 -0
  38. data/lib/phil_columns/version.rb +3 -0
  39. data/lib/phil_columns/with_backend.rb +21 -0
  40. data/phil_columns.gemspec +30 -0
  41. data/spec/spec_helper.rb +2 -0
  42. data/templates/seed_class.erb +11 -0
  43. 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,9 @@
1
+ module PhilColumns
2
+ module Command
3
+ module Generate
4
+
5
+ autoload :Seed, 'phil_columns/command/generate/seed'
6
+
7
+ end
8
+ end
9
+ 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,10 @@
1
+ module PhilColumns
2
+ module Command
3
+ module List
4
+
5
+ autoload :TaggedWith, 'phil_columns/command/list/tagged_with'
6
+ autoload :Tags, 'phil_columns/command/list/tags'
7
+
8
+ end
9
+ end
10
+ 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