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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rspec +1 -0
- data/.ruby-gemset +1 -0
- data/bin/pineapples +4 -9
- data/lib/pineapples/actions/apply.rb +34 -0
- data/lib/pineapples/actions/base/action.rb +72 -0
- data/lib/pineapples/actions/base/target.rb +136 -0
- data/lib/pineapples/actions/chmod.rb +28 -0
- data/lib/pineapples/actions/copy_file.rb +48 -0
- data/lib/pineapples/actions/create_file.rb +114 -0
- data/lib/pineapples/actions/directory.rb +115 -0
- data/lib/pineapples/actions/empty_directory.rb +71 -0
- data/lib/pineapples/actions/get.rb +38 -0
- data/lib/pineapples/actions/git.rb +17 -0
- data/lib/pineapples/actions/gsub_file.rb +36 -0
- data/lib/pineapples/actions/insert_into_file.rb +131 -0
- data/lib/pineapples/actions/inside.rb +69 -0
- data/lib/pineapples/actions/keep_file.rb +15 -0
- data/lib/pineapples/actions/prepend_to_class.rb +26 -0
- data/lib/pineapples/actions/rails/copy_migration.rb +67 -0
- data/lib/pineapples/actions/rails/erb_converters.rb +37 -0
- data/lib/pineapples/actions/rails/rails.rb +186 -0
- data/lib/pineapples/actions/remove_file.rb +28 -0
- data/lib/pineapples/actions/ruby.rb +49 -0
- data/lib/pineapples/actions/shell.rb +40 -0
- data/lib/pineapples/actions/template.rb +35 -0
- data/lib/pineapples/actions.rb +124 -39
- data/lib/pineapples/app_builder.rb +70 -0
- data/lib/pineapples/app_generator.rb +187 -0
- data/lib/pineapples/build_tasks/root_files.rb +23 -0
- data/lib/pineapples/error.rb +7 -0
- data/lib/pineapples/helpers.rb +34 -0
- data/lib/pineapples/parser.rb +37 -0
- data/lib/pineapples/setting.rb +155 -0
- data/lib/pineapples/settings.rb +31 -0
- data/lib/pineapples/templates/.buildpacks +2 -0
- data/lib/pineapples/templates/.editor-config +11 -0
- data/lib/pineapples/templates/.example.env.tt +11 -0
- data/lib/pineapples/templates/.example.rspec +3 -0
- data/lib/pineapples/templates/.gitignore +23 -0
- data/lib/pineapples/templates/Aptfile +0 -0
- data/lib/pineapples/templates/Gemfile.tt +89 -0
- data/lib/pineapples/templates/Guardfile +27 -0
- data/lib/pineapples/templates/Procfile +1 -0
- data/lib/pineapples/templates/README.md.tt +32 -0
- data/lib/pineapples/templates/Rakefile +6 -0
- data/lib/pineapples/templates/app/assets/javascripts/application.js +1 -0
- data/lib/pineapples/templates/app/assets/javascripts/libs.js +2 -0
- data/lib/pineapples/templates/app/assets/stylesheets/application.scss +1 -0
- data/lib/pineapples/templates/app/controllers/application_controller.rb.tt +48 -0
- data/lib/pineapples/templates/app/controllers/auth/confirmations_controller.rb +2 -0
- data/lib/pineapples/templates/app/controllers/pages_controller.rb +6 -0
- data/lib/pineapples/templates/app/helpers/application_helper.rb +59 -0
- data/lib/pineapples/templates/app/helpers/title_helper.rb +77 -0
- data/lib/pineapples/templates/app/models/user!=needs_user_model!.rb.tt +28 -0
- data/lib/pineapples/templates/app/views/common/_flashes.html.erb +16 -0
- data/lib/pineapples/templates/app/views/common/_footer.html.erb +3 -0
- data/lib/pineapples/templates/app/views/common/_header.html.erb +5 -0
- data/lib/pineapples/templates/app/views/layouts/application.html.erb.tt +33 -0
- data/lib/pineapples/templates/app/views/pages/home.html.erb +4 -0
- data/lib/pineapples/templates/bin/bundle +3 -0
- data/lib/pineapples/templates/bin/rails +8 -0
- data/lib/pineapples/templates/bin/rake +8 -0
- data/lib/pineapples/templates/bin/setup +33 -0
- data/lib/pineapples/templates/bin/spring +15 -0
- data/lib/pineapples/templates/browserlist +4 -0
- data/lib/pineapples/templates/config/application.rb.tt +43 -0
- data/lib/pineapples/templates/config/boot.rb +5 -0
- data/lib/pineapples/templates/config/database.yml.tt +20 -0
- data/lib/pineapples/templates/config/environment.rb +5 -0
- data/lib/pineapples/templates/config/environments/development.rb +64 -0
- data/lib/pineapples/templates/config/environments/production.rb +77 -0
- data/lib/pineapples/templates/config/environments/test.rb +34 -0
- data/lib/pineapples/templates/config/i18n-tasks.yml +13 -0
- data/lib/pineapples/templates/config/initializers/assets.rb +11 -0
- data/lib/pineapples/templates/config/initializers/backtrace_silencers.rb +7 -0
- data/lib/pineapples/templates/config/initializers/carrierwave.rb +22 -0
- data/lib/pineapples/templates/config/initializers/cookies_serializer.rb +3 -0
- data/lib/pineapples/templates/config/initializers/filter_parameters_logging.rb +4 -0
- data/lib/pineapples/templates/config/initializers/inflections.rb +16 -0
- data/lib/pineapples/templates/config/initializers/mime_types.rb +4 -0
- data/lib/pineapples/templates/config/initializers/pry.rb +10 -0
- data/lib/pineapples/templates/config/initializers/redis.rb +3 -0
- data/lib/pineapples/templates/config/initializers/session_store.rb.tt +3 -0
- data/lib/pineapples/templates/config/initializers/wrap_parameters.rb +14 -0
- data/lib/pineapples/templates/config/locales/en.yml +19 -0
- data/lib/pineapples/templates/config/puma.rb +21 -0
- data/lib/pineapples/templates/config/routes.rb.tt +10 -0
- data/lib/pineapples/templates/config/secrets.yml +11 -0
- data/lib/pineapples/templates/config/smtp.rb +11 -0
- data/lib/pineapples/templates/config.ru.tt +7 -0
- data/lib/pineapples/templates/db/migrate/01_enable_postgres_extensions.rb +15 -0
- data/lib/pineapples/templates/db/migrate/02_create_data_migrations.rb +14 -0
- data/lib/pineapples/templates/db/migrate/03_devise_create_users.rb +41 -0
- data/lib/pineapples/templates/db/migrate/04_add_role_field_to_users.rb +7 -0
- data/lib/pineapples/templates/lib/devise!=devise!/ajax_failure.rb +11 -0
- data/lib/pineapples/templates/lib/extensions/form_builder.rb +24 -0
- data/lib/pineapples/templates/lib/extensions/http_errors.rb +34 -0
- data/lib/pineapples/templates/lib/extensions/to_boolean.rb +45 -0
- data/lib/pineapples/templates/lib/logging/custom_rack_logger.rb +11 -0
- data/lib/pineapples/templates/lib/logging/custom_request_logger.rb +65 -0
- data/lib/pineapples/templates/lib/simple_form/components/append.rb +15 -0
- data/lib/pineapples/templates/lib/simple_form/components/prepend.rb +15 -0
- data/lib/pineapples/templates/lib/tasks/admin!=user_role_field!.rake +52 -0
- data/lib/pineapples/templates/lib/tasks/auto_annotate_models.rake +37 -0
- data/lib/pineapples/templates/lib/templates/erb/scaffold/_form.html.erb +14 -0
- data/lib/pineapples/templates/lib/virtus/virtus.rb +23 -0
- data/lib/pineapples/templates/public/404.html +67 -0
- data/lib/pineapples/templates/public/422.html +67 -0
- data/lib/pineapples/templates/public/500.html +66 -0
- data/lib/pineapples/templates/public/favicon.ico +0 -0
- data/lib/pineapples/templates/public/robots.txt +5 -0
- data/lib/pineapples/version.rb +1 -1
- data/lib/pineapples.rb +17 -2
- data/pineapples.gemspec +16 -15
- 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
|