phil_columns 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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