pineapples 0.1.0 → 0.3.34

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 (117) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rspec +1 -0
  4. data/.ruby-gemset +1 -0
  5. data/bin/pineapples +4 -9
  6. data/lib/pineapples/actions/apply.rb +34 -0
  7. data/lib/pineapples/actions/base/action.rb +72 -0
  8. data/lib/pineapples/actions/base/target.rb +136 -0
  9. data/lib/pineapples/actions/chmod.rb +28 -0
  10. data/lib/pineapples/actions/copy_file.rb +48 -0
  11. data/lib/pineapples/actions/create_file.rb +114 -0
  12. data/lib/pineapples/actions/directory.rb +115 -0
  13. data/lib/pineapples/actions/empty_directory.rb +71 -0
  14. data/lib/pineapples/actions/get.rb +38 -0
  15. data/lib/pineapples/actions/git.rb +17 -0
  16. data/lib/pineapples/actions/gsub_file.rb +36 -0
  17. data/lib/pineapples/actions/insert_into_file.rb +131 -0
  18. data/lib/pineapples/actions/inside.rb +69 -0
  19. data/lib/pineapples/actions/keep_file.rb +15 -0
  20. data/lib/pineapples/actions/prepend_to_class.rb +26 -0
  21. data/lib/pineapples/actions/rails/copy_migration.rb +67 -0
  22. data/lib/pineapples/actions/rails/erb_converters.rb +37 -0
  23. data/lib/pineapples/actions/rails/rails.rb +186 -0
  24. data/lib/pineapples/actions/remove_file.rb +28 -0
  25. data/lib/pineapples/actions/ruby.rb +49 -0
  26. data/lib/pineapples/actions/shell.rb +40 -0
  27. data/lib/pineapples/actions/template.rb +35 -0
  28. data/lib/pineapples/actions.rb +124 -39
  29. data/lib/pineapples/app_builder.rb +70 -0
  30. data/lib/pineapples/app_generator.rb +187 -0
  31. data/lib/pineapples/build_tasks/root_files.rb +23 -0
  32. data/lib/pineapples/error.rb +7 -0
  33. data/lib/pineapples/helpers.rb +34 -0
  34. data/lib/pineapples/parser.rb +37 -0
  35. data/lib/pineapples/setting.rb +155 -0
  36. data/lib/pineapples/settings.rb +31 -0
  37. data/lib/pineapples/templates/.buildpacks +2 -0
  38. data/lib/pineapples/templates/.editor-config +11 -0
  39. data/lib/pineapples/templates/.example.env.tt +11 -0
  40. data/lib/pineapples/templates/.example.rspec +3 -0
  41. data/lib/pineapples/templates/.gitignore +23 -0
  42. data/lib/pineapples/templates/Aptfile +0 -0
  43. data/lib/pineapples/templates/Gemfile.tt +89 -0
  44. data/lib/pineapples/templates/Guardfile +27 -0
  45. data/lib/pineapples/templates/Procfile +1 -0
  46. data/lib/pineapples/templates/README.md.tt +32 -0
  47. data/lib/pineapples/templates/Rakefile +6 -0
  48. data/lib/pineapples/templates/app/assets/javascripts/application.js +1 -0
  49. data/lib/pineapples/templates/app/assets/javascripts/libs.js +2 -0
  50. data/lib/pineapples/templates/app/assets/stylesheets/application.scss +1 -0
  51. data/lib/pineapples/templates/app/controllers/application_controller.rb.tt +48 -0
  52. data/lib/pineapples/templates/app/controllers/auth/confirmations_controller.rb +2 -0
  53. data/lib/pineapples/templates/app/controllers/pages_controller.rb +6 -0
  54. data/lib/pineapples/templates/app/helpers/application_helper.rb +59 -0
  55. data/lib/pineapples/templates/app/helpers/title_helper.rb +77 -0
  56. data/lib/pineapples/templates/app/models/user!=needs_user_model!.rb.tt +28 -0
  57. data/lib/pineapples/templates/app/views/common/_flashes.html.erb +16 -0
  58. data/lib/pineapples/templates/app/views/common/_footer.html.erb +3 -0
  59. data/lib/pineapples/templates/app/views/common/_header.html.erb +5 -0
  60. data/lib/pineapples/templates/app/views/layouts/application.html.erb.tt +33 -0
  61. data/lib/pineapples/templates/app/views/pages/home.html.erb +4 -0
  62. data/lib/pineapples/templates/bin/bundle +3 -0
  63. data/lib/pineapples/templates/bin/rails +8 -0
  64. data/lib/pineapples/templates/bin/rake +8 -0
  65. data/lib/pineapples/templates/bin/setup +33 -0
  66. data/lib/pineapples/templates/bin/spring +15 -0
  67. data/lib/pineapples/templates/browserlist +4 -0
  68. data/lib/pineapples/templates/config/application.rb.tt +43 -0
  69. data/lib/pineapples/templates/config/boot.rb +5 -0
  70. data/lib/pineapples/templates/config/database.yml.tt +20 -0
  71. data/lib/pineapples/templates/config/environment.rb +5 -0
  72. data/lib/pineapples/templates/config/environments/development.rb +64 -0
  73. data/lib/pineapples/templates/config/environments/production.rb +77 -0
  74. data/lib/pineapples/templates/config/environments/test.rb +34 -0
  75. data/lib/pineapples/templates/config/i18n-tasks.yml +13 -0
  76. data/lib/pineapples/templates/config/initializers/assets.rb +11 -0
  77. data/lib/pineapples/templates/config/initializers/backtrace_silencers.rb +7 -0
  78. data/lib/pineapples/templates/config/initializers/carrierwave.rb +22 -0
  79. data/lib/pineapples/templates/config/initializers/cookies_serializer.rb +3 -0
  80. data/lib/pineapples/templates/config/initializers/filter_parameters_logging.rb +4 -0
  81. data/lib/pineapples/templates/config/initializers/inflections.rb +16 -0
  82. data/lib/pineapples/templates/config/initializers/mime_types.rb +4 -0
  83. data/lib/pineapples/templates/config/initializers/pry.rb +10 -0
  84. data/lib/pineapples/templates/config/initializers/redis.rb +3 -0
  85. data/lib/pineapples/templates/config/initializers/session_store.rb.tt +3 -0
  86. data/lib/pineapples/templates/config/initializers/wrap_parameters.rb +14 -0
  87. data/lib/pineapples/templates/config/locales/en.yml +19 -0
  88. data/lib/pineapples/templates/config/puma.rb +21 -0
  89. data/lib/pineapples/templates/config/routes.rb.tt +10 -0
  90. data/lib/pineapples/templates/config/secrets.yml +11 -0
  91. data/lib/pineapples/templates/config/smtp.rb +11 -0
  92. data/lib/pineapples/templates/config.ru.tt +7 -0
  93. data/lib/pineapples/templates/db/migrate/01_enable_postgres_extensions.rb +15 -0
  94. data/lib/pineapples/templates/db/migrate/02_create_data_migrations.rb +14 -0
  95. data/lib/pineapples/templates/db/migrate/03_devise_create_users.rb +41 -0
  96. data/lib/pineapples/templates/db/migrate/04_add_role_field_to_users.rb +7 -0
  97. data/lib/pineapples/templates/lib/devise!=devise!/ajax_failure.rb +11 -0
  98. data/lib/pineapples/templates/lib/extensions/form_builder.rb +24 -0
  99. data/lib/pineapples/templates/lib/extensions/http_errors.rb +34 -0
  100. data/lib/pineapples/templates/lib/extensions/to_boolean.rb +45 -0
  101. data/lib/pineapples/templates/lib/logging/custom_rack_logger.rb +11 -0
  102. data/lib/pineapples/templates/lib/logging/custom_request_logger.rb +65 -0
  103. data/lib/pineapples/templates/lib/simple_form/components/append.rb +15 -0
  104. data/lib/pineapples/templates/lib/simple_form/components/prepend.rb +15 -0
  105. data/lib/pineapples/templates/lib/tasks/admin!=user_role_field!.rake +52 -0
  106. data/lib/pineapples/templates/lib/tasks/auto_annotate_models.rake +37 -0
  107. data/lib/pineapples/templates/lib/templates/erb/scaffold/_form.html.erb +14 -0
  108. data/lib/pineapples/templates/lib/virtus/virtus.rb +23 -0
  109. data/lib/pineapples/templates/public/404.html +67 -0
  110. data/lib/pineapples/templates/public/422.html +67 -0
  111. data/lib/pineapples/templates/public/500.html +66 -0
  112. data/lib/pineapples/templates/public/favicon.ico +0 -0
  113. data/lib/pineapples/templates/public/robots.txt +5 -0
  114. data/lib/pineapples/version.rb +1 -1
  115. data/lib/pineapples.rb +17 -2
  116. data/pineapples.gemspec +16 -15
  117. metadata +208 -2
@@ -0,0 +1,38 @@
1
+ require 'open-uri'
2
+
3
+ module Pineapples
4
+ module Actions
5
+ # Gets the content at the given address and places it at the given relative
6
+ # destination. If a block is given instead of destination, the content of
7
+ # the url is yielded and used as location.
8
+ #
9
+ # ==== Parameters
10
+ # source<String>:: the address of the given content.
11
+ # target<String>:: the relative path to the destination root.
12
+ # options<Hash>:: give :verbose => false to not log the status.
13
+ #
14
+ # ==== Examples
15
+ #
16
+ # get "http://gist.github.com/103208", "doc/README"
17
+ #
18
+ # get "http://gist.github.com/103208" do |content|
19
+ # content.split("\n").first
20
+ # end
21
+ #
22
+ def get(source, *args, &block)
23
+ options = args.last.is_a?(Hash) ? args.pop : {}
24
+ target = args.first
25
+
26
+ source = File.expand_path(find_in_source_paths(source.to_s)) unless source =~ %r{^https?\://}
27
+ render = open(source) { |input| input.binmode.read }
28
+
29
+ target ||= if block
30
+ block.arity == 1 ? block.call(render) : block.call
31
+ else
32
+ File.basename(source)
33
+ end
34
+
35
+ create_file(target, render, options)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,17 @@
1
+ module Pineapples
2
+ module Actions
3
+ # Run a command in git.
4
+ #
5
+ # git :init
6
+ # git add: "this.file that.rb"
7
+ # git add: "onefile.rb", rm: "badfile.cxx"
8
+ def git(commands = {})
9
+ if commands.is_a?(Symbol)
10
+ shell "git #{commands}"
11
+ else
12
+ commands.each { |cmd, options| shell "git #{cmd} #{options}" }
13
+ end
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,36 @@
1
+ module Pineapples
2
+ module Actions
3
+ # Run a regular expression replacement on a file.
4
+ #
5
+ # ==== Parameters
6
+ # path<String>:: path of the file to be changed
7
+ # flag<Regexp|String>:: the regexp or string to be replaced
8
+ # replacement<String>:: the replacement, can be also given as a block
9
+ # config<Hash>:: give :verbose => false to not log the status.
10
+ #
11
+ # ==== Example
12
+ #
13
+ # gsub_file 'app/controllers/application_controller.rb', /#\s*(filter_parameter_logging :password)/, '\1'
14
+ #
15
+ # gsub_file 'README', /rake/, :green do |match|
16
+ # match << " no more. Use thor!"
17
+ # end
18
+ #
19
+ def gsub_file(path, flag, *args, &block)
20
+ return unless behaviour == :invoke
21
+ options = args.last.is_a?(Hash) ? args.pop : {}
22
+
23
+ verbose = options.fetch(:verbose, verbose?)
24
+ execute = options.fetch(:pretend, execute?)
25
+
26
+ path = File.expand_path(path, app_root)
27
+ say_status :gsub, relative_to_app_root(path), :light_yellow, verbose
28
+
29
+ if execute
30
+ content = File.binread(path)
31
+ content.gsub!(flag, *args, &block)
32
+ File.open(path, 'wb') { |file| file.write(content) }
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,131 @@
1
+ module Pineapples
2
+ module Actions
3
+ def insert_into_file(target, *args, &block)
4
+ content = block_given? ? block : args.shift
5
+ options = args.shift
6
+ action InsertIntoFile.new(self, target, content, options)
7
+ end
8
+
9
+ # Append text to a file. Since it depends on insert_into_file, it's reversible.
10
+ #
11
+ # ==== Parameters
12
+ # path<String>:: path of the file to be changed
13
+ # data<String>:: the data to append to the file, can be also given as a block.
14
+ # config<Hash>:: give :verbose => false to not log the status.
15
+ #
16
+ # ==== Example
17
+ #
18
+ # append_to_file 'config/environments/test.rb', 'config.gem "rspec"'
19
+ #
20
+ # append_to_file 'config/environments/test.rb' do
21
+ # 'config.gem "rspec"'
22
+ # end
23
+ #
24
+ def append_to_file(path, *args, &block)
25
+ options = args.last.is_a?(Hash) ? args.pop : {}
26
+ options.merge!(before: /\z/)
27
+ insert_into_file(path, *(args << options), &block)
28
+ end
29
+ alias_method :append_file, :append_to_file
30
+
31
+ # Prepend text to a file. Since it depends on insert_into_file, it's reversible.
32
+ #
33
+ # ==== Parameters
34
+ # path<String>:: path of the file to be changed
35
+ # content<String>:: the content to prepend to the file, can be also given as a block.
36
+ # options<Hash>:: give :verbose => false to not log the status.
37
+ #
38
+ # ==== Example
39
+ #
40
+ # prepend_to_file 'config/environments/test.rb', 'config.gem "rspec"'
41
+ #
42
+ # prepend_to_file 'config/environments/test.rb' do
43
+ # 'config.gem "rspec"'
44
+ # end
45
+ #
46
+ def prepend_to_file(path, *args, &block)
47
+ options = args.last.is_a?(Hash) ? args.pop : {}
48
+ options.merge!(after: /\A/)
49
+ insert_into_file(path, *(args << options), &block)
50
+ end
51
+ alias_method :prepend_file, :prepend_to_file
52
+
53
+ class InsertIntoFile < EmptyDirectory
54
+ attr_reader :new_content,
55
+ :flag,
56
+ :behaviour
57
+
58
+ status_color :prepend, :creative
59
+ status_color :append, :creative
60
+ status_color :insert, :creative
61
+ status_color :substract, :destructive
62
+
63
+ def initialize(generator, target, new_content, options)
64
+ super(generator, target, {verbose: true}.merge(options))
65
+
66
+ @behaviour = @options.key?(:after) ? :after : :before
67
+ @flag = @options.delete(@behaviour)
68
+
69
+ @new_content = new_content.is_a?(Proc) ? new_content.call : new_content
70
+ @flag = Regexp.escape(@flag) if !@flag.is_a?(Regexp)
71
+ end
72
+
73
+ def invoke!
74
+ say_status status(:invoke)
75
+
76
+ content = if @behavior == :after
77
+ '\0' + replacement
78
+ else
79
+ replacement + '\0'
80
+ end
81
+
82
+ regexp = /#{flag}/
83
+
84
+ replace!(regexp, content, options[:force])
85
+ end
86
+
87
+ def revoke!
88
+ say_status status(:revoke)
89
+
90
+ if @behavior == :after
91
+ content = '\1\2'
92
+ regexp = /(#{flag})(.*)(#{Regexp.escape(new_content)})/m
93
+ else
94
+ content = '\2\3'
95
+ regexp = /(#{Regexp.escape(new_content)})(.*)(#{flag})/m
96
+ end
97
+
98
+ replace!(regexp, content, true)
99
+ end
100
+
101
+
102
+
103
+ protected
104
+
105
+ def status(execution_style)
106
+ if execution_style == :invoke
107
+ if flag == /\A/
108
+ :prepend
109
+ elsif flag == /\z/
110
+ :append
111
+ else
112
+ :insert
113
+ end
114
+ else
115
+ :subtract
116
+ end
117
+ end
118
+
119
+ def replace!(regexp, string, force)
120
+ if execute?
121
+ content = File.binread(target.fullpath)
122
+ if force || !content.include?(new_content)
123
+ content.gsub!(regexp, string)
124
+ File.open(target.fullpath, 'wb') { |file| file.write(content) }
125
+ end
126
+ end
127
+ end
128
+
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,69 @@
1
+ module Pineapples
2
+ module Actions
3
+ def dir_stack
4
+ @dir_stack ||= []
5
+ end
6
+
7
+ def current_app_dir
8
+ File.expand_path(File.join(*dir_stack), app_root)
9
+ end
10
+
11
+ # Do something in the root or on a provided subfolder. The full path to
12
+ # the directory is yielded to the block you provide.
13
+ # The path is set back to the previous path when the method exits.
14
+ #
15
+ # ==== Parameters
16
+ # dir<String>:: the directory to move to, relative to the app root
17
+ # config<Hash>:: give :verbose => true to log and use padding.
18
+ #
19
+ def inside(dir = :root, options = {}, &block)
20
+ verbose = options.fetch(:verbose, verbose?)
21
+ color = options.fetch(:color, :light_green)
22
+
23
+ status_dir = if dir == :root
24
+ relative_to_app_root(app_root)
25
+ else
26
+ relative_to_app_root(File.join(current_app_dir, dir))
27
+ end
28
+
29
+ say_status(:inside, status_dir, color, verbose)
30
+
31
+ indent(verbose) do
32
+ with_directory(dir) do |target_dir|
33
+ if !File.exist?(target_dir) && !pretend?
34
+ FileUtils.mkdir_p(target_dir)
35
+ end
36
+
37
+ if pretend?
38
+ block.arity == 1 ? yield(target_dir) : yield
39
+ else
40
+ FileUtils.cd(target_dir) do
41
+ block.arity == 1 ? yield(target_dir) : yield
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ # Convenience method to call inside in_root
49
+ def in_root(options = {})
50
+ inside(:root, options) { yield }
51
+ end
52
+
53
+ private
54
+
55
+ # helper method to abstract directory stack management in the "inside" action
56
+ def with_directory(dir)
57
+ not_in_root = (dir != :root)
58
+
59
+ dir_stack.push(dir) if not_in_root
60
+
61
+ target_dir = not_in_root ? current_app_dir : app_root
62
+
63
+ yield target_dir
64
+
65
+ dir_stack.pop if not_in_root
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,15 @@
1
+ require_relative 'empty_directory'
2
+
3
+ module Pineapples
4
+ module Actions
5
+ def empty_directory_with_keep_file(target, options = {})
6
+ empty_directory(target, options)
7
+ keep_file(target)
8
+ end
9
+
10
+ def keep_file(target)
11
+ create_file("#{target}/.keep")
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,26 @@
1
+ module Pineapples
2
+ module Actions
3
+ # Injects text right after the class definition. Since it depends on
4
+ # insert_into_file, it's reversible.
5
+ #
6
+ # ==== Parameters
7
+ # path<String>:: path of the file to be changed
8
+ # klass<String|Class>:: the class to be manipulated
9
+ # data<String>:: the data to append to the class, can be also given as a block.
10
+ # config<Hash>:: give :verbose => false to not log the status.
11
+ #
12
+ # ==== Examples
13
+ #
14
+ # prepend_to_class "app/controllers/application_controller.rb", ApplicationController, " filter_parameter :password\n"
15
+ #
16
+ # prepend_to_class "app/controllers/application_controller.rb", ApplicationController do
17
+ # " filter_parameter :password\n"
18
+ # end
19
+ #
20
+ def prepend_to_class(path, klass, *args, &block)
21
+ options = args.last.is_a?(Hash) ? args.pop : {}
22
+ options.merge!(after: /class #{klass}\n|class #{klass} .*\n/)
23
+ insert_into_file(path, *(args << options), &block)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,67 @@
1
+ require 'pineapples/actions/copy_file'
2
+
3
+ module Pineapples
4
+ module Actions
5
+ module Rails
6
+ def copy_migration(migration_name, options = {})
7
+ # TODO: find migration file
8
+ action CopyMigration.new(self, migration_name, options)
9
+ end
10
+
11
+ class CopyMigration < CopyFile
12
+ attr_reader :migration_name
13
+
14
+ def self.time
15
+ @time ||= Time.now
16
+ end
17
+
18
+ def self.time=(value)
19
+ @time = value
20
+ end
21
+
22
+ def initialize(generator, migration_name, options)
23
+ @generator = generator
24
+ @migration_name = File.basename(migration_name, File.extname(migration_name))
25
+
26
+ set_source_for_migration!
27
+ @target = target_for_migration
28
+
29
+ super(generator, @source, @target, options)
30
+ end
31
+
32
+ def invoke!
33
+ super
34
+ self.class.time = self.class.time + 2
35
+ end
36
+
37
+ private
38
+
39
+ def set_source_for_migration!
40
+ sources = generator.source_paths_for_search
41
+
42
+ sources.each do |source_path|
43
+ migration_dir = File.join(source_path, relative_migration_dir)
44
+ Dir.glob("#{migration_dir}/*.rb").each do |filename|
45
+ @source = filename if filename.include?(migration_name)
46
+ end
47
+ end
48
+
49
+ raise ArgumentError, "Failed to find migration by name #{migration_name}" if @source.nil?
50
+ end
51
+
52
+ def target_for_migration
53
+ File.join(relative_migration_dir, "#{migration_timestamp}_#{migration_name}.rb")
54
+ end
55
+
56
+ def relative_migration_dir
57
+ 'db/migrate'
58
+ end
59
+
60
+ def migration_timestamp
61
+ self.class.time.strftime('%Y%m%d%H%M%S')
62
+ end
63
+ end
64
+
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,37 @@
1
+ module Pineapples
2
+ module Actions
3
+ module Rails
4
+ def erb2haml(target, options = {})
5
+ recursive = options.fetch(:recursive, true)
6
+ verbose = options.fetch(:verbose, verbose?)
7
+ execute = !options.fetch(:pretend, pretend?)
8
+
9
+ description = 'Convert ERB views to HAML'
10
+ say_action(:erb2haml, description, verbose)
11
+
12
+ if execute
13
+ target_path = File.expand_path(target, app_root)
14
+ target_path = File.join(target_path, recursive_mask) if recursive
15
+ shell "find #{target_path} -name \\*.erb -print | sed 'p;s/.erb$/.haml/' | xargs -n2 html2haml",
16
+ verbose: false
17
+ end
18
+ end
19
+
20
+ def erb2slim(target, options = {})
21
+ recursive = options.fetch(:recursive, true)
22
+ verbose = options.fetch(:verbose, verbose?)
23
+ execute = !options.fetch(:pretend, pretend?)
24
+
25
+ description = 'Convert ERB views to SLIM'
26
+ say_action(:erb2slim, description, verbose)
27
+
28
+ if execute
29
+ erb2haml(target, options)
30
+ target_path = File.expand_path(target, app_root)
31
+ target_path = File.join(target_path, '**') if recursive
32
+ shell "haml2slim #{target_path} --delete --trace", verbose: false
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,186 @@
1
+ require_relative 'erb_converters'
2
+ require_relative 'copy_migration'
3
+
4
+ module Pineapples
5
+ module Actions
6
+ module Rails
7
+ # Adds a line inside the Application class for <tt>config/application.rb</tt>.
8
+ #
9
+ # If options <tt>:env</tt> is specified, the line is appended to the corresponding
10
+ # file in <tt>config/environments</tt>.
11
+ #
12
+ # environment do
13
+ # "config.autoload_paths += %W(#{config.root}/extras)"
14
+ # end
15
+ #
16
+ # environment(nil, env: "development") do
17
+ # "config.autoload_paths += %W(#{config.root}/extras)"
18
+ # end
19
+ def environment(content = nil, options = {})
20
+ sentinel = /class [a-z_:]+ < Rails::Application/i
21
+ env_file_sentinel = /Rails\.application\.configure do/
22
+ content = yield if !content && block_given?
23
+
24
+ in_root do
25
+ if options[:env].nil?
26
+ insert_into_file 'config/application.rb', "\n #{content}",
27
+ after: sentinel, verbose: false
28
+ else
29
+ Array(options[:env]).each do |env|
30
+ insert_into_file "config/environments/#{env}.rb", "\n #{content}",
31
+ after: env_file_sentinel, verbose: false
32
+ end
33
+ end
34
+ end
35
+ end
36
+ alias :application :environment
37
+
38
+ # Create a new file in the <tt>vendor/</tt> directory. Code can be specified
39
+ # in a block or a data string can be given.
40
+ #
41
+ # vendor("sekrit.rb") do
42
+ # sekrit_salt = "#{Time.now}--#{3.years.ago}--#{rand}--"
43
+ # "salt = '#{sekrit_salt}'"
44
+ # end
45
+ #
46
+ # vendor("foreign.rb", "# Foreign code is fun")
47
+ def vendor(filename, content = nil, &block)
48
+ log :vendor, filename
49
+ create_file("vendor/#{filename}", content, verbose: false, &block)
50
+ end
51
+
52
+ # Create a new file in the lib/ directory. Code can be specified
53
+ # in a block or a data string can be given.
54
+ #
55
+ # lib("crypto.rb") do
56
+ # "crypted_special_value = '#{rand}--#{Time.now}--#{rand(1337)}--'"
57
+ # end
58
+ #
59
+ # lib("foreign.rb", "# Foreign code is fun")
60
+ def lib(filename, content = nil, &block)
61
+ say_status :lib, filename, color_from_behaviour
62
+ create_file("lib/#{filename}", content, verbose: false, &block)
63
+ end
64
+
65
+ # Create a new +Rakefile+ with the provided code (either in a block or a string).
66
+ #
67
+ # rakefile("bootstrap.rake") do
68
+ # project = ask("What is the UNIX name of your project?")
69
+ #
70
+ # <<-TASK
71
+ # namespace :#{project} do
72
+ # task :bootstrap do
73
+ # puts "I like boots!"
74
+ # end
75
+ # end
76
+ # TASK
77
+ # end
78
+ #
79
+ # rakefile('seed.rake', 'puts "Planting seeds"')
80
+ def rakefile(filename, content = nil, &block)
81
+ say_status :lib, filename, color_from_behaviour
82
+ rake_extention = File.extname(filename) == '.rake'
83
+ filename = rake_extention ? filename : "#{filename}.rake"
84
+ create_file("lib/tasks/#{filename}", content, verbose: false, &block)
85
+ end
86
+
87
+ # Create a new initializer with the provided code (either in a block or a string).
88
+ #
89
+ # initializer("globals.rb") do
90
+ # data = ""
91
+ #
92
+ # ['MY_WORK', 'ADMINS', 'BEST_COMPANY_EVAR'].each do |const|
93
+ # data << "#{const} = :entp\n"
94
+ # end
95
+ #
96
+ # data
97
+ # end
98
+ #
99
+ # initializer("api.rb", "API_KEY = '123456'")
100
+ def initializer(filename, content = nil, &block)
101
+ say_status :initializer, filename, color_from_behaviour
102
+ create_file("config/initializers/#{filename}", content, verbose: false, &block)
103
+ end
104
+
105
+ # Generate something using a generator from Rails or a plugin.
106
+ # The second parameter is the argument string that is passed to
107
+ # the generator or an Array that is joined.
108
+ #
109
+ # generate(:authenticated, "user session")
110
+ def generate(what, *args)
111
+ say_status :generate, what, color_from_behaviour
112
+ arguments = args.flat_map(&:to_s).join(' ')
113
+
114
+ in_root { ruby("bin/rails generate #{what} #{arguments}", verbose: false) }
115
+ end
116
+
117
+ # Runs the supplied rake task
118
+ #
119
+ # rake("db:migrate")
120
+ # rake("db:migrate", env: "production")
121
+ # rake("gems:install", sudo: true)
122
+ def rake(command, options = {})
123
+ say_status :rake, command, color_from_behaviour
124
+ env = options[:env] || ENV['RAILS_ENV'] || 'development'
125
+ sudo = options[:sudo] && RbConfig::CONFIG['host_os'] !~ /mswin|mingw/ ? 'sudo ' : ''
126
+ in_root { shell("#{sudo}rake #{command} RAILS_ENV=#{env}", verbose: false) }
127
+ end
128
+
129
+ # Make an entry in Rails routing file <tt>config/routes.rb</tt>
130
+ #
131
+ # route "root 'welcome#index'"
132
+ def route(routing_code)
133
+ say_status :route, routing_code, color_from_behaviour
134
+ sentinel = /\.routes\.draw do\s*\n/m
135
+
136
+ in_root do
137
+ insert_into_file 'config/routes.rb', " #{routing_code}\n", {after: sentinel, verbose: false, force: true}
138
+ end
139
+ end
140
+
141
+ # Registers a callback to be executed after bundle and spring binstubs
142
+ # have run.
143
+ #
144
+ # after_bundle do
145
+ # git add: '.'
146
+ # end
147
+ def after_bundle(&block)
148
+ @after_bundle_callbacks ||= []
149
+ @after_bundle_callbacks << block
150
+ end
151
+
152
+ protected
153
+
154
+ def color_from_behaviour
155
+ behaviour == :invoke ? :light_green : :light_red
156
+ end
157
+
158
+ # Surround string with single quotes if there is no quotes.
159
+ # Otherwise fall back to double quotes
160
+ def quote(value)
161
+ return value.inspect unless value.is_a? String
162
+
163
+ if value.include?("'")
164
+ value.inspect
165
+ else
166
+ "'#{value}'"
167
+ end
168
+ end
169
+
170
+ def comment_if(setting = nil)
171
+ return yield ? '# ' : '' if block_given?
172
+
173
+ raise ArgumentError, 'You should provide either setting key or block' if setting.nil?
174
+ settings[setting].value ? '# ' : ''
175
+ end
176
+
177
+ def comment_if_not(setting = nil)
178
+ return yield ? '' : '# ' if block_given?
179
+
180
+ raise ArgumentError, 'You should provide either setting key or block' if setting.nil?
181
+ settings[setting].value ? '' : '# '
182
+ end
183
+
184
+ end
185
+ end
186
+ end
@@ -0,0 +1,28 @@
1
+ module Pineapples
2
+ module Actions
3
+ # Removes a file at the given location.
4
+ #
5
+ # ==== Parameters
6
+ # path<String>:: path of the file to be changed
7
+ # options<Hash>:: give :verbose => false to not log the status.
8
+ #
9
+ # ==== Example
10
+ #
11
+ # remove_file 'README'
12
+ # remove_file 'app/controllers/application_controller.rb'
13
+ #
14
+ def remove_file(path, options = {})
15
+ return unless behaviour == :invoke
16
+ path = File.expand_path(path, destination_root)
17
+
18
+ message = relative_to_app_root(path)
19
+ verbose = options.fetch(:verbose, verbose?)
20
+ color = options.fetch(:color, :light_red)
21
+ execute = options[:pretend] || execute?
22
+
23
+ say_status :remove, message, color, verbose
24
+ ::FileUtils.rm_rf(path) if execute && File.exist?(path)
25
+ end
26
+ alias_method :remove_dir, :remove_file
27
+ end
28
+ end