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,49 @@
1
+ require_relative 'shell'
2
+ module Pineapples
3
+ module Actions
4
+ # Executes a ruby script (taking into account WIN32 platform quirks).
5
+ #
6
+ # ==== Parameters
7
+ # command<String>:: the command to be executed.
8
+ # options<Hash>:: give :verbose => false to not log the status.
9
+ #
10
+ def ruby(command, options = {})
11
+ return if behaviour != :inboke
12
+ shell(command, options.merge(with: ruby_command))
13
+ end
14
+
15
+ private
16
+ # Return the path to the ruby interpreter taking into account multiple
17
+ # installations and windows extensions.
18
+ #
19
+ def ruby_command # rubocop:disable MethodLength
20
+ @ruby_command ||= begin
21
+ ruby_name = RbConfig::CONFIG['ruby_install_name']
22
+ ruby = File.join(RbConfig::CONFIG['bindir'], ruby_name)
23
+ ruby << RbConfig::CONFIG['EXEEXT']
24
+
25
+ # avoid using different name than ruby (on platforms supporting links)
26
+ if ruby_name != 'ruby' && File.respond_to?(:readlink)
27
+ begin
28
+ alternate_ruby = File.join(RbConfig::CONFIG['bindir'], 'ruby')
29
+ alternate_ruby << RbConfig::CONFIG['EXEEXT']
30
+
31
+ # ruby is a symlink
32
+ if File.symlink? alternate_ruby
33
+ linked_ruby = File.readlink alternate_ruby
34
+
35
+ # symlink points to 'ruby_install_name'
36
+ ruby = alternate_ruby if linked_ruby == ruby_name || linked_ruby == ruby
37
+ end
38
+ rescue NotImplementedError # rubocop:disable HandleExceptions
39
+ # just ignore on windows
40
+ end
41
+ end
42
+
43
+ # escape string in case path to ruby executable contain spaces.
44
+ ruby.sub!(/.*\s.*/m, '"\&"')
45
+ ruby
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,40 @@
1
+ module Pineapples
2
+ module Actions
3
+ # Executes a command returning the contents of the command.
4
+ #
5
+ # ==== Parameters
6
+ # command<String>:: the command to be executed.
7
+ # options<Hash>:: give :verbose => false to not log the status, :capture => true to hide to output. Specify :with
8
+ # to append an executable to command execution.
9
+ #
10
+ # ==== Example
11
+ #
12
+ # inside 'vendor' do
13
+ # shell 'ln -s ~/edge rails'
14
+ # end
15
+ #
16
+ def shell(command, options = {})
17
+ return if behavior == :revoke
18
+
19
+ verbose = options.fetch(:verbose, verbose?)
20
+ execute = !options.fetch(:pretend, pretend?)
21
+
22
+ description = "#{command} from #{current_app_dir.inspect}"
23
+
24
+ executable = options[:with].to_s
25
+
26
+ if executable.present?
27
+ description = "#{File.basename(executable)} #{desc}"
28
+ command = "#{executable} #{command}"
29
+ end
30
+
31
+ say_action(:shell, description, verbose)
32
+
33
+ if execute
34
+ config[:capture] ? `#{command}` : system("#{command}")
35
+ raise Error, "#{command} failed with status #{$CHILD_STATUS.exitstatus}." if not $CHILD_STATUS.success?
36
+ end
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,35 @@
1
+ require 'erb'
2
+
3
+ module Pineapples
4
+ module Actions
5
+ # Gets an ERB template at the relative source, executes it and makes a copy
6
+ # at the relative destination. If the destination is not given it's assumed
7
+ # to be equal to the source removing .tt from the filename.
8
+ #
9
+ # ==== Parameters
10
+ # source<String>:: the relative path to the source root.
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
+ # template "README", "doc/README"
17
+ #
18
+ # template "doc/README"
19
+ #
20
+ def template(source, *args, &block)
21
+ options = args.last.is_a?(Hash) ? args.pop : {}
22
+ target = args.first || source.sub(/#{TEMPLATE_EXTNAME}$/, '')
23
+
24
+ source = File.expand_path(find_in_source_paths(source.to_s))
25
+ context = options.delete(:context) || binding #instance_eval('binding')
26
+
27
+ create_file(target, nil, options) do
28
+ template = File.binread(source)
29
+ content = ERB.new(template, nil, '-').result(context)
30
+ content = block.call(content) if block
31
+ content
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,39 +1,124 @@
1
- module Pineapples
2
- module Actions
3
- def replace_file(relative_path, *args)
4
- remove_file(relative_path)
5
- copy_file(relative_path, *args)
6
- end
7
-
8
- def replace_in_file(relative_path, find, replace)
9
- path = File.join(destination_root, relative_path)
10
- contents = IO.read(path)
11
- unless contents.gsub!(find, replace)
12
- raise "#{find.inspect} not found in #{relative_path}"
13
- end
14
- File.open(path, "w") { |file| file.write(contents) }
15
- end
16
-
17
- def action_mailer_host(rails_env, host)
18
- config = "config.action_mailer.default_url_options = {host: #{host}}"
19
- configure_environment(rails_env, config)
20
- end
21
-
22
- def configure_application_file(config)
23
- inject_into_file(
24
- "config/application.rb",
25
- "\n\n #{config}",
26
- before: "\n end"
27
- )
28
- end
29
-
30
- def configure_environment(rails_env, config)
31
- inject_into_file(
32
- "config/environments/#{rails_env}.rb",
33
- "\n\n #{config}",
34
- before: "\nend"
35
- )
36
- end
37
-
38
- end
39
- end
1
+ require 'fileutils'
2
+ require 'pathname'
3
+ require 'uri'
4
+ require 'pineapples/actions/base/action'
5
+ require 'pineapples/actions/base/target'
6
+ require 'pineapples/actions/apply'
7
+ require 'pineapples/actions/chmod'
8
+ require 'pineapples/actions/copy_file'
9
+ require 'pineapples/actions/create_file'
10
+ require 'pineapples/actions/directory'
11
+ require 'pineapples/actions/empty_directory'
12
+ require 'pineapples/actions/get'
13
+ require 'pineapples/actions/git'
14
+ require 'pineapples/actions/gsub_file'
15
+ require 'pineapples/actions/insert_into_file'
16
+ require 'pineapples/actions/inside'
17
+ require 'pineapples/actions/keep_file'
18
+ require 'pineapples/actions/prepend_to_class'
19
+ require 'pineapples/actions/remove_file'
20
+ require 'pineapples/actions/ruby'
21
+ require 'pineapples/actions/shell'
22
+ require 'pineapples/actions/template'
23
+
24
+ require 'pineapples/actions/rails/rails'
25
+
26
+ module Pineapples
27
+ module Actions
28
+ TEMPLATE_EXTNAME = '.tt'
29
+
30
+ DEFAULT_COLOR = :light_green
31
+
32
+ attr_reader :behaviour
33
+
34
+ def initialize(options)
35
+ super
36
+
37
+ @behaviour = options.behaviour || :invoke
38
+ end
39
+
40
+ # Executes instance of Action subclass depending on generator behaviour
41
+ def action(instance) #:nodoc:
42
+ return if instance.skip?
43
+ if behaviour == :invoke
44
+ instance.invoke!
45
+ else
46
+ instance.revoke!
47
+ end
48
+ end
49
+
50
+ def templates_root
51
+ @templates_root ||= File.join(__dir__, 'templates')
52
+ end
53
+
54
+ def source_paths
55
+ @source_paths ||= []
56
+ end
57
+
58
+ def source_paths_for_search
59
+ paths = []
60
+ paths += source_paths
61
+ paths << templates_root if templates_root
62
+ paths
63
+ end
64
+
65
+ # dir argument must me absolute path
66
+ def relative_to_app_root(dir)
67
+ @app_root_pathname ||= Pathname.new(app_root)
68
+ path = Pathname.new(dir)
69
+ path.relative_path_from(@app_root_pathname).to_s
70
+ end
71
+
72
+ def relative_to_current_app_dir(dir)
73
+ current_app_path = Pathname.new(current_app_dir)
74
+ path = Pathname.new(dir)
75
+ path.relative_path_from(current_app_path).to_s
76
+ end
77
+
78
+ def find_in_source_paths(file)
79
+ files_to_search = [file, file + TEMPLATE_EXTNAME]
80
+ sources = source_paths_for_search
81
+
82
+ sources.each do |source_path|
83
+ files_to_search.each do |file|
84
+ source_file = File.expand_path(file, source_path)
85
+ return source_file if File.exist?(source_file)
86
+ end
87
+ end
88
+
89
+ message = "Could not find #{file.inspect} in any of your source paths. "
90
+
91
+ unless self.templates_root
92
+ message << "Please set your generator instance template_root to PATH with the PATH containing your templates."
93
+ end
94
+
95
+ if sources.empty?
96
+ message << "Currently you have no source paths."
97
+ else
98
+ message << "Your current source paths are: \n#{sources.join("\n")}"
99
+ end
100
+
101
+ raise Error, message
102
+ end
103
+
104
+ def say_status(status, message, color = :light_green, log = true)
105
+ return if !log
106
+
107
+ spaces = ' ' * $terminal.indent_size * 2
108
+
109
+ status = status.to_s.rjust(12)
110
+ status = status.colorize(color)
111
+
112
+ output = "#{status}#{spaces}#{message}"
113
+
114
+ say(output)
115
+ end
116
+
117
+ def indent(verbose = true, level_increment = 1)
118
+ $terminal.indent_level += level_increment if verbose
119
+ yield
120
+ $terminal.indent_level -= level_increment if verbose
121
+ end
122
+
123
+ end
124
+ end
@@ -0,0 +1,70 @@
1
+ require 'pineapples/actions'
2
+ #require 'pineapples/build_tasks/root_files'
3
+
4
+ module Pineapples
5
+ class AppBuilder
6
+ include Pineapples::Actions
7
+
8
+ def root_files
9
+ create_file '.ruby-version', "#{Pineapples::RUBY_VERSION}\n"
10
+ create_file '.ruby-gemset', app_name
11
+
12
+ template 'config.ru'
13
+ template 'Gemfile'
14
+ copy_file 'Guardfile'
15
+ copy_file 'Procfile'
16
+ copy_file 'Rakefile'
17
+
18
+ copy_file '.gitignore'
19
+
20
+ template 'README.md.tt'
21
+ copy_file 'browserlist'
22
+ copy_file '.editor-config'
23
+
24
+ template '.example.env.tt'
25
+
26
+ if options.heroku?
27
+ copy_file '.buildpacks'
28
+ template 'Aptfile'
29
+ end
30
+
31
+ if !options.skip_test?
32
+ copy_file '.example.rspec'
33
+ end
34
+ end
35
+
36
+ def app_files
37
+ directory 'app', except: 'user.rb'
38
+
39
+ inside 'app' do
40
+ keep_file 'assets/fonts'
41
+ keep_file 'assets/images'
42
+ if create_user_model?
43
+ template 'models/user.rb.tt'
44
+ else
45
+ keep_file 'models'
46
+ end
47
+ keep_file 'mailers'
48
+
49
+ keep_file 'controllers/concerns'
50
+ keep_file 'models/concerns'
51
+ end
52
+
53
+ end
54
+
55
+ def bin_files
56
+ directory 'bin' do |content|
57
+ "#{shebang}\n" + content
58
+ end
59
+ chmod 'bin', 0755 & ~File.umask, verbose: false
60
+ end
61
+
62
+ def config_files
63
+ directory 'config'
64
+
65
+ inside 'config' do
66
+ end
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,187 @@
1
+ require 'pineapples/actions'
2
+ require 'pineapples/helpers'
3
+ require 'pineapples/settings'
4
+
5
+ module Pineapples
6
+ class AppGenerator
7
+ extend Pineapples::Settings
8
+ prepend Pineapples::Actions
9
+ include Pineapples::Actions::Rails
10
+ include Pineapples::Helpers
11
+
12
+ TEMPLATING_ENGINES = [:erb, :haml, :slim]
13
+
14
+ setting :heroku, type: :boolean, default: false,
15
+ prompt: 'Wanna use Heroku?'
16
+
17
+ setting :carrierwave, type: :boolean, default: false,
18
+ prompt: 'Wanna use Carrierwave for file uploads?'
19
+
20
+ setting :devise, type: :boolean, default: true,
21
+ prompt: 'Wanna use Devise for authentication?'
22
+
23
+ setting :ajax_login, type: :boolean, default: false,
24
+ prompt: 'Wanna login via ajax using devise?'
25
+
26
+ setting :pundit, type: :boolean, default: true,
27
+ prompt: 'Wanna use Pundit for authorization?'
28
+
29
+ setting :user_role_field, type: :boolean, default: true,
30
+ prompt: 'Wanna add role attribute to users model as simple user roles solution?'
31
+
32
+ setting :template_engine, type: :symbol, default: :erb, options: TEMPLATING_ENGINES,
33
+ prompt: 'Select templating engine to be used in the app'
34
+
35
+ setting :bootstrap, type: :boolean, default: false,
36
+ prompt: 'Wanna use Bootstrap on this project?'
37
+
38
+ attr_accessor :app_name,
39
+ :app_root,
40
+ :settings
41
+
42
+ def initialize(options)
43
+ @app_name = options.app_name.gsub(/\s+/, '-')
44
+ @app_root = options.app_root || File.expand_path(app_name)
45
+ @debug = options.debug || false
46
+ @pretend = options.pretend || false
47
+ @verbose = options.verbose || true
48
+
49
+ @settings = self.class.settings
50
+ end
51
+
52
+ def start!
53
+ valid_const! && check_target!
54
+ create_app_root
55
+
56
+ # ask_user_settings
57
+
58
+ create_root_files
59
+ create_app_files
60
+ create_bin_files
61
+ create_config_files
62
+ create_db_files
63
+ create_lib_files
64
+ create_public_files
65
+ create_spec_files
66
+
67
+ create_misc_folders
68
+
69
+ #run_after_bundle_callbacks
70
+ rescue Pineapples::Error => error
71
+ (debug? || ENV['PINEAPPLES_DEBUG'] == '1') ? (raise error) : say(error.message.light_red)
72
+ exit 1
73
+ end
74
+
75
+ def ask_user_settings
76
+ settings[:heroku].ask_setting
77
+ settings[:template_engine].ask_setting
78
+ end
79
+
80
+ def create_root_files
81
+ copy_file '.editor-config'
82
+ template '.example.env'
83
+ copy_file '.example.rspec'
84
+ copy_file '.gitignore'
85
+ copy_file 'browserlist'
86
+ template 'config.ru'
87
+ template 'Gemfile'
88
+ copy_file 'Guardfile'
89
+ copy_file 'Procfile'
90
+ copy_file 'Rakefile'
91
+ template 'README.md', 'README.md'
92
+ if heroku?
93
+ copy_file '.buildpacks'
94
+ copy_file 'Aptfile'
95
+ end
96
+ end
97
+
98
+ def create_app_files
99
+ directory 'app'
100
+ keep_file 'app/assets/fonts'
101
+ keep_file 'app/assets/images'
102
+
103
+ keep_file 'app/mailers'
104
+ keep_file 'app/models' if !needs_user_model?
105
+ end
106
+
107
+ def create_bin_files
108
+ directory 'bin'
109
+ # chmod 'bin', 0755 & ~File.umask, verbose: false
110
+ end
111
+
112
+ def create_config_files
113
+ directory 'config'
114
+ end
115
+
116
+ def create_db_files
117
+ empty_directory 'db/migrate'
118
+ copy_migration 'enable_postgres_extensions'
119
+ copy_migration 'create_data_migrations'
120
+ if devise?
121
+ copy_migration 'devise_create_users'
122
+ copy_migration 'add_role_field_to_users' if user_role_field?
123
+ end
124
+ end
125
+
126
+ def create_lib_files
127
+ directory 'lib'
128
+ keep_file 'lib/assets'
129
+ end
130
+
131
+ def create_public_files
132
+ directory 'public'
133
+ end
134
+
135
+ def create_spec_files
136
+ # directory 'spec'
137
+ end
138
+
139
+ def create_misc_folders
140
+ keep_file 'log'
141
+
142
+ empty_directory 'tmp/cache/assets'
143
+
144
+ inside 'vendor/assets' do
145
+ keep_file 'javascripts'
146
+ keep_file 'stylesheets'
147
+ end
148
+ end
149
+
150
+ def run_after_bundle_callbacks
151
+ @after_bundle_callbacks.each(&:call)
152
+ end
153
+
154
+
155
+
156
+ def debug?
157
+ @debug
158
+ end
159
+
160
+ def pretend?
161
+ @pretend
162
+ end
163
+
164
+ def execute?
165
+ !pretend?
166
+ end
167
+
168
+ def verbose?
169
+ @verbose
170
+ end
171
+
172
+ protected
173
+
174
+ def create_app_root
175
+ FileUtils::mkdir_p(app_root)
176
+ say_status :create_root, 'Created application root'
177
+ end
178
+
179
+ def check_target!
180
+ if Dir["#{app_root}/*"].present?
181
+ puts "I won't grow pineapples there, the target directory isn't empty."
182
+ exit 1
183
+ end
184
+ end
185
+
186
+ end
187
+ end
@@ -0,0 +1,23 @@
1
+ module Pineapples
2
+ module BuildTasks
3
+ module RootFiles
4
+ def readme
5
+ end
6
+
7
+ def rakefile
8
+ end
9
+
10
+ def configru
11
+ end
12
+
13
+ def gitignore
14
+ end
15
+
16
+ def gemfile
17
+ end
18
+
19
+ # build(:) if !options.skip_git?
20
+ # build(:gemfile) if !options.skip_gemfile?
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,7 @@
1
+ module Pineapples
2
+ class Error < StandardError
3
+ end
4
+
5
+ class SkipActionError < StandardError
6
+ end
7
+ end
@@ -0,0 +1,34 @@
1
+ module Pineapples
2
+ module Helpers
3
+ RESERVED_NAMES = %w[application destroy plugin runner test]
4
+
5
+ def needs_user_model?
6
+ user_role_field? || devise?
7
+ end
8
+
9
+ protected
10
+
11
+ def app_const_base
12
+ @app_const_base ||= app_name.gsub(/\W/, '_').squeeze('_').camelize
13
+ end
14
+
15
+ def app_const
16
+ @app_const ||= "#{app_const_base}::Application"
17
+ end
18
+
19
+ def valid_const!
20
+ if app_const =~ /^\d/
21
+ raise Error, "Invalid application name #{app_name}. Please give a name which does not start with numbers."
22
+ elsif RESERVED_NAMES.include?(app_name)
23
+ raise Error, "Invalid application name #{app_name}. Please give a name which does not match one of the reserved rails words."
24
+ elsif Object.const_defined?(app_const_base)
25
+ raise Error, "Invalid application name #{app_name}, constant #{app_const_base} is already in use. Please choose another application name."
26
+ end
27
+ end
28
+
29
+ def app_secret
30
+ SecureRandom.hex(64)
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,37 @@
1
+ module Pineapples
2
+ class Parser
3
+ def self.parse(args)
4
+ options = OpenStruct.new
5
+ options.app_name = nil
6
+
7
+ parser = OptionParser.new do |opts|
8
+ opts.banner = 'Usage: pineapples [options] NEW_APP_DIRECTORY'
9
+
10
+ opts.on('-h', '--help', 'Show pineapples usage') do
11
+ self.usage_and_exit(opts)
12
+ end
13
+
14
+ opts.on_tail('-v', '--version', 'Show version') do
15
+ puts Pineapples::VERSION
16
+ exit 1
17
+ end
18
+ end
19
+
20
+ begin
21
+ parser.parse!
22
+ options.app_name = ARGV.first
23
+
24
+ raise OptionParser::InvalidOption if options.app_name.nil?
25
+
26
+ options
27
+ rescue OptionParser::InvalidOption
28
+ self.usage_and_exit(parser)
29
+ end
30
+ end
31
+
32
+ def self.usage_and_exit(parser)
33
+ say parser
34
+ exit 1
35
+ end
36
+ end
37
+ end