pineapples 0.3.34 → 0.3.345

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 (93) hide show
  1. checksums.yaml +4 -4
  2. data/bin/pineapples +13 -13
  3. data/lib/pineapples.rb +3 -1
  4. data/lib/pineapples/actions.rb +6 -0
  5. data/lib/pineapples/actions/base/target.rb +41 -91
  6. data/lib/pineapples/actions/bundle.rb +16 -0
  7. data/lib/pineapples/actions/chmod.rb +3 -2
  8. data/lib/pineapples/actions/copy_file.rb +1 -1
  9. data/lib/pineapples/actions/empty_directory.rb +1 -1
  10. data/lib/pineapples/actions/gsub_file.rb +5 -3
  11. data/lib/pineapples/actions/inside.rb +5 -1
  12. data/lib/pineapples/actions/rails/erb_converters.rb +11 -4
  13. data/lib/pineapples/actions/rails/new_hash_syntax_converter.rb +36 -0
  14. data/lib/pineapples/actions/rails/rails.rb +1 -0
  15. data/lib/pineapples/actions/remove_file.rb +28 -28
  16. data/lib/pineapples/actions/shell.rb +43 -9
  17. data/lib/pineapples/app_generator.rb +154 -38
  18. data/lib/pineapples/helpers.rb +31 -0
  19. data/lib/pineapples/parser.rb +42 -37
  20. data/lib/pineapples/setting.rb +155 -155
  21. data/lib/pineapples/settings.rb +31 -31
  22. data/lib/pineapples/templates/.example.env.tt +15 -0
  23. data/lib/pineapples/templates/.gitignore +3 -0
  24. data/lib/pineapples/templates/.simplecov.tt +11 -0
  25. data/lib/pineapples/templates/Gemfile.tt +23 -5
  26. data/lib/pineapples/templates/Procfile +1 -1
  27. data/lib/pineapples/templates/Procfile.dev.tt +2 -0
  28. data/lib/pineapples/templates/app/assets/javascripts/libs.js +4 -2
  29. data/lib/pineapples/templates/app/assets/stylesheets/application.scss +4 -1
  30. data/lib/pineapples/templates/app/controllers/application_controller.rb.tt +0 -2
  31. data/lib/pineapples/templates/app/controllers/auth!=devise!/confirmations_controller.rb +11 -0
  32. data/lib/pineapples/templates/app/controllers/auth!=devise!/passwords_controller.rb.tt +12 -0
  33. data/lib/pineapples/templates/app/controllers/auth!=devise!/registrations_controller.rb.tt +25 -0
  34. data/lib/pineapples/templates/app/controllers/auth!=devise!/sessions_controller.rb.tt +59 -0
  35. data/lib/pineapples/templates/app/models/user!=needs_user_model!.rb.tt +7 -4
  36. data/lib/pineapples/templates/app/policies!=pundit!/application_policy.rb +49 -0
  37. data/lib/pineapples/templates/app/presenters/base_presenter.rb.tt +24 -0
  38. data/lib/pineapples/templates/app/responders/application_responder.rb +9 -0
  39. data/lib/pineapples/templates/app/services/service.rb +7 -0
  40. data/lib/pineapples/templates/app/views/common/_footer.html.erb +3 -3
  41. data/lib/pineapples/templates/app/views/common/_header.html.erb +5 -5
  42. data/lib/pineapples/templates/app/views/layouts/application.html.erb.tt +0 -1
  43. data/lib/pineapples/templates/app/views/pages/home.html.erb +0 -1
  44. data/lib/pineapples/templates/bin/nginx +4 -0
  45. data/lib/pineapples/templates/bin/rails +1 -0
  46. data/lib/pineapples/templates/bin/rspec +19 -0
  47. data/lib/pineapples/templates/bin/setup +111 -21
  48. data/lib/pineapples/templates/config.ru.tt +3 -0
  49. data/lib/pineapples/templates/config/application.rb.tt +3 -3
  50. data/lib/pineapples/templates/config/boot.rb +5 -5
  51. data/lib/pineapples/templates/config/database.yml.tt +1 -1
  52. data/lib/pineapples/templates/config/environments/{development.rb → development.rb.tt} +6 -1
  53. data/lib/pineapples/templates/config/environments/production.rb +1 -1
  54. data/lib/pineapples/templates/config/environments/test.rb +2 -2
  55. data/lib/pineapples/templates/config/i18n-tasks.yml +2 -0
  56. data/lib/pineapples/templates/config/initializers/{carrierwave.rb → carrierwave!=carrierwave!.rb} +22 -22
  57. data/lib/pineapples/templates/config/initializers/devise!=devise!.rb.tt +262 -0
  58. data/lib/pineapples/templates/config/initializers/kaminari.rb +10 -0
  59. data/lib/pineapples/templates/config/initializers/seed_migrations.rb +15 -0
  60. data/lib/pineapples/templates/config/initializers/simple_form.rb +165 -0
  61. data/lib/pineapples/templates/config/locales/devise.en.yml +60 -0
  62. data/lib/pineapples/templates/config/locales/{en.yml → en.yml.tt} +2 -0
  63. data/lib/pineapples/templates/config/locales/kaminari.en.yml +17 -0
  64. data/lib/pineapples/templates/config/locales/simple_form.en.yml +31 -0
  65. data/lib/pineapples/templates/config/nginx.conf.tt +147 -0
  66. data/lib/pineapples/templates/config/puma/development.rb.tt +27 -0
  67. data/lib/pineapples/templates/config/{puma.rb → puma/production.rb} +5 -5
  68. data/lib/pineapples/templates/config/routes.rb.tt +4 -0
  69. data/lib/pineapples/templates/config/spring.rb +4 -0
  70. data/lib/pineapples/templates/lib/devise!=devise!/{ajax_failure.rb → ajax_failure!=ajax_login!.rb} +0 -0
  71. data/lib/pineapples/templates/lib/logging/custom_rack_logger.rb +7 -9
  72. data/lib/pineapples/templates/lib/logging/custom_request_logger.rb +46 -48
  73. data/lib/pineapples/templates/lib/tasks/admin!=user_role_field!.rake +18 -19
  74. data/lib/pineapples/templates/lib/templates/{erb → erb!=erb!}/scaffold/_form.html.erb +0 -0
  75. data/lib/pineapples/templates/lib/templates/haml!=haml!/scaffold/_form.html.haml +9 -0
  76. data/lib/pineapples/templates/lib/templates/slim!=slim!/scaffold/_form.html.slim +9 -0
  77. data/lib/pineapples/templates/spec/i18n_spec.rb +17 -0
  78. data/lib/pineapples/templates/spec/rails_helper.rb +30 -0
  79. data/lib/pineapples/templates/spec/spec_helper.rb +44 -0
  80. data/lib/pineapples/templates/spec/support/capybara.rb +4 -0
  81. data/lib/pineapples/templates/spec/support/database_cleaner.rb +27 -0
  82. data/lib/pineapples/templates/spec/support/email_matchers.rb +17 -0
  83. data/lib/pineapples/templates/spec/support/factory_girl.rb +14 -0
  84. data/lib/pineapples/templates/spec/support/job_helpers.rb +8 -0
  85. data/lib/pineapples/templates/spec/support/matchers.rb +10 -0
  86. data/lib/pineapples/templates/spec/support/rake_tasks.rb +8 -0
  87. data/lib/pineapples/templates/spec/support/shoulda_matchers.rb +24 -0
  88. data/lib/pineapples/version.rb +2 -2
  89. data/pineapples.gemspec +1 -3
  90. metadata +46 -12
  91. data/lib/pineapples/app_builder.rb +0 -70
  92. data/lib/pineapples/build_tasks/root_files.rb +0 -23
  93. data/lib/pineapples/templates/app/controllers/auth/confirmations_controller.rb +0 -2
@@ -14,27 +14,61 @@ module Pineapples
14
14
  # end
15
15
  #
16
16
  def shell(command, options = {})
17
- return if behavior == :revoke
17
+ return if behaviour == :revoke
18
18
 
19
19
  verbose = options.fetch(:verbose, verbose?)
20
20
  execute = !options.fetch(:pretend, pretend?)
21
21
 
22
- description = "#{command} from #{current_app_dir.inspect}"
23
-
24
22
  executable = options[:with].to_s
25
23
 
26
- if executable.present?
27
- description = "#{File.basename(executable)} #{desc}"
28
- command = "#{executable} #{command}"
29
- end
24
+ command = "#{executable} #{command}" if executable.present?
30
25
 
31
- say_action(:shell, description, verbose)
26
+ say_status(:shell, command, DEFAULT_COLOR, verbose)
32
27
 
33
28
  if execute
34
- config[:capture] ? `#{command}` : system("#{command}")
29
+ options[:capture] ? `#{command}` : system("#{command}")
35
30
  raise Error, "#{command} failed with status #{$CHILD_STATUS.exitstatus}." if not $CHILD_STATUS.success?
36
31
  end
37
32
  end
38
33
 
34
+ def shell_with_clean_bundler_env(command, options = {})
35
+ return shell(command, options) if !defined?(Bundler)
36
+ Bundler.with_clean_env do
37
+ shell(command, options)
38
+ end
39
+ end
40
+
41
+ def shell_with_app_gemset(command, options = {})
42
+ # we have to use PTY pseudo terminal to able to read shell subprocess output asynchronously.
43
+ # Backticks and Kernel#system buffer output, and since bundle install takes forever to complete
44
+ # it's not very user-friendly and program would seem to hang.
45
+ # We just cd into project directory and invoke RVM in binary mode ('do' command)
46
+
47
+ # TODO: add support for rbenv gemsets
48
+ return if behaviour == :revoke
49
+ verbose = options.fetch(:verbose, verbose?)
50
+ execute = !options.fetch(:pretend, pretend?)
51
+
52
+ full_command = "export DISABLE_SPRING=0; cd #{File.basename(app_root)}; rvm . do #{command}"
53
+ say_status :shell, full_command, DEFAULT_COLOR, verbose
54
+
55
+ if execute
56
+ begin
57
+ PTY.spawn(full_command) do |reader, writer, pid|
58
+ loop do
59
+ line = reader.gets
60
+ break if !line
61
+ puts line
62
+ end
63
+ Process.wait(pid)
64
+ end
65
+ rescue Errno::EIO => error
66
+ nil
67
+ rescue PTY::ChildExited => error
68
+ puts 'The child process exited!'
69
+ end
70
+ end
71
+ end
72
+
39
73
  end
40
74
  end
@@ -11,8 +11,8 @@ module Pineapples
11
11
 
12
12
  TEMPLATING_ENGINES = [:erb, :haml, :slim]
13
13
 
14
- setting :heroku, type: :boolean, default: false,
15
- prompt: 'Wanna use Heroku?'
14
+ setting :template_engine, type: :symbol, default: :erb, options: TEMPLATING_ENGINES,
15
+ prompt: 'Select templating engine to be used in the app'
16
16
 
17
17
  setting :carrierwave, type: :boolean, default: false,
18
18
  prompt: 'Wanna use Carrierwave for file uploads?'
@@ -20,7 +20,7 @@ module Pineapples
20
20
  setting :devise, type: :boolean, default: true,
21
21
  prompt: 'Wanna use Devise for authentication?'
22
22
 
23
- setting :ajax_login, type: :boolean, default: false,
23
+ setting :ajax_login, type: :boolean, default: true,
24
24
  prompt: 'Wanna login via ajax using devise?'
25
25
 
26
26
  setting :pundit, type: :boolean, default: true,
@@ -29,12 +29,27 @@ module Pineapples
29
29
  setting :user_role_field, type: :boolean, default: true,
30
30
  prompt: 'Wanna add role attribute to users model as simple user roles solution?'
31
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
32
  setting :bootstrap, type: :boolean, default: false,
36
33
  prompt: 'Wanna use Bootstrap on this project?'
37
34
 
35
+ setting :use_rvm, type: :boolean, default: true,
36
+ prompt: 'Want to create new RVM gemset for the app?'
37
+
38
+ setting :heroku, type: :boolean, default: false,
39
+ prompt: 'Wanna use Heroku?'
40
+
41
+ setting :git_repo_url, type: :string, default: '',
42
+ prompt: 'What is the git remote URL for this project?'
43
+
44
+ setting :production_hostname, type: :string, default: '',
45
+ prompt: 'Enter hostname for production site'
46
+
47
+ setting :staging_hostname, type: :string, default: '',
48
+ prompt: 'Enter hostname for staging site'
49
+
50
+ setting :web_console, type: :boolean, default: false,
51
+ prompt: 'Do you want to use web-console gem?'
52
+
38
53
  attr_accessor :app_name,
39
54
  :app_root,
40
55
  :settings
@@ -45,6 +60,7 @@ module Pineapples
45
60
  @debug = options.debug || false
46
61
  @pretend = options.pretend || false
47
62
  @verbose = options.verbose || true
63
+ @testing = options.testing || false
48
64
 
49
65
  @settings = self.class.settings
50
66
  end
@@ -55,18 +71,9 @@ module Pineapples
55
71
 
56
72
  # ask_user_settings
57
73
 
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
74
+ create_files
66
75
 
67
- create_misc_folders
68
-
69
- #run_after_bundle_callbacks
76
+ setup_app
70
77
  rescue Pineapples::Error => error
71
78
  (debug? || ENV['PINEAPPLES_DEBUG'] == '1') ? (raise error) : say(error.message.light_red)
72
79
  exit 1
@@ -77,18 +84,35 @@ module Pineapples
77
84
  settings[:template_engine].ask_setting
78
85
  end
79
86
 
87
+ def create_files
88
+ create_root_files
89
+ create_app_files
90
+ create_bin_files
91
+ create_config_files
92
+ create_db_files
93
+ create_lib_files
94
+ create_public_files
95
+ create_spec_files
96
+ create_misc_folders
97
+ copy_example_files
98
+ end
99
+
80
100
  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'
101
+ create_file '.ruby-version', Pineapples::RUBY_VERSION
102
+ create_file '.ruby-gemset', app_name
103
+ copy_file '.editor-config'
104
+ template '.example.env'
105
+ copy_file '.example.rspec'
106
+ copy_file '.gitignore'
107
+ template '.simplecov'
108
+ copy_file 'browserlist'
109
+ template 'config.ru'
110
+ template 'Gemfile'
111
+ copy_file 'Guardfile'
112
+ copy_file 'Procfile'
113
+ template 'Procfile.dev'
114
+ copy_file 'Rakefile'
115
+ template 'README.md'
92
116
  if heroku?
93
117
  copy_file '.buildpacks'
94
118
  copy_file 'Aptfile'
@@ -97,16 +121,19 @@ module Pineapples
97
121
 
98
122
  def create_app_files
99
123
  directory 'app'
100
- keep_file 'app/assets/fonts'
101
- keep_file 'app/assets/images'
124
+ empty_directory_with_keep_file 'app/assets/fonts'
125
+ empty_directory_with_keep_file 'app/assets/images'
102
126
 
103
- keep_file 'app/mailers'
104
- keep_file 'app/models' if !needs_user_model?
127
+ empty_directory_with_keep_file 'app/mailers'
128
+ empty_directory_with_keep_file 'app/models' if !needs_user_model?
105
129
  end
106
130
 
107
131
  def create_bin_files
108
132
  directory 'bin'
109
- # chmod 'bin', 0755 & ~File.umask, verbose: false
133
+ in_app_root do
134
+ shell 'chmod -v 755 bin'
135
+ shell 'chmod -v 644 bin/*'
136
+ end
110
137
  end
111
138
 
112
139
  def create_config_files
@@ -133,17 +160,102 @@ module Pineapples
133
160
  end
134
161
 
135
162
  def create_spec_files
136
- # directory 'spec'
163
+ directory 'spec'
164
+ inside 'spec' do
165
+ empty_directory_with_keep_file 'controllers'
166
+ empty_directory_with_keep_file 'features'
167
+ empty_directory_with_keep_file 'factories'
168
+ empty_directory_with_keep_file 'helpers'
169
+ empty_directory_with_keep_file 'jobs'
170
+ empty_directory_with_keep_file 'mailers'
171
+ empty_directory_with_keep_file 'models'
172
+ empty_directory_with_keep_file 'policies' if pundit?
173
+ empty_directory_with_keep_file 'presenters'
174
+ empty_directory_with_keep_file 'services'
175
+ empty_directory_with_keep_file 'lib'
176
+
177
+ empty_directory_with_keep_file 'support/features'
178
+ empty_directory_with_keep_file 'support/matchers'
179
+ empty_directory_with_keep_file 'support/mixins'
180
+ empty_directory_with_keep_file 'support/shared_examples'
181
+ end
137
182
  end
138
183
 
139
184
  def create_misc_folders
140
- keep_file 'log'
185
+ empty_directory_with_keep_file 'log'
141
186
 
142
- empty_directory 'tmp/cache/assets'
187
+ empty_directory 'tmp/pids'
143
188
 
144
189
  inside 'vendor/assets' do
145
- keep_file 'javascripts'
146
- keep_file 'stylesheets'
190
+ empty_directory_with_keep_file 'javascripts'
191
+ empty_directory_with_keep_file 'stylesheets'
192
+ end
193
+ end
194
+
195
+ def copy_example_files
196
+ say_title 'Copying sample files'
197
+ template '.example.env', '.env'
198
+ copy_file '.example.rspec', '.rspec'
199
+ end
200
+
201
+ def setup_app
202
+ create_rvm_gemset if rvm_installed? & use_rvm?
203
+ shell_with_app_gemset 'bundle install'
204
+
205
+ setup_database
206
+
207
+ setup_gems
208
+
209
+ to_new_hash_syntax!
210
+
211
+ setup_git
212
+ end
213
+
214
+ def create_rvm_gemset
215
+ say_title 'Creating project-specific RVM gemset'
216
+ shell "rvm gemset create #{app_name}"
217
+ end
218
+
219
+ def setup_database
220
+ say_title 'Preparing database'
221
+ shell_with_app_gemset 'bundle exec rake db:drop' if testing?
222
+ shell_with_app_gemset 'bundle exec rake db:setup'
223
+ shell_with_app_gemset 'bundle exec rake db:migrate'
224
+ end
225
+
226
+ def setup_gems
227
+ shell_with_app_gemset 'rails g kaminari:views default'
228
+ erb2haml 'app/views/kaminari'
229
+ end
230
+
231
+ def convert_views
232
+ if haml?
233
+ # TODO: convert all views to haml
234
+ elsif slim?
235
+ # TODO: convert all views to slim
236
+ end
237
+ end
238
+
239
+ def to_new_hash_syntax!
240
+ # Converting files generated by generators like kaminari to new hash syntax
241
+ say_title 'Converting Ruby hash rockets to new syntax'
242
+ convert_directory_to_new_hash_syntax 'app/views/kaminari'
243
+ end
244
+
245
+ def setup_git
246
+ if !preexisting_git_repo?
247
+ say_title 'Setting up git repo'
248
+ in_app_root do
249
+ git :init
250
+ git add: '-A .'
251
+ git commit: %(-n -m "Generated Rails #{RAILS_VERSION.gsub('~> ', '')} project via pineapples gem")
252
+ git checkout: '-b staging'
253
+ git checkout: '-b dev'
254
+ if git_repo_url?
255
+ git remote: "add origin #{git_repo_url.shellescape}"
256
+ git push: '-u origin --all'
257
+ end
258
+ end
147
259
  end
148
260
  end
149
261
 
@@ -169,6 +281,10 @@ module Pineapples
169
281
  @verbose
170
282
  end
171
283
 
284
+ def testing?
285
+ @testing
286
+ end
287
+
172
288
  protected
173
289
 
174
290
  def create_app_root
@@ -6,8 +6,24 @@ module Pineapples
6
6
  user_role_field? || devise?
7
7
  end
8
8
 
9
+ def erb?
10
+ template_engine == :erb
11
+ end
12
+
13
+ def haml?
14
+ template_engine == :haml
15
+ end
16
+
17
+ def slim?
18
+ template_engine == :slim
19
+ end
20
+
9
21
  protected
10
22
 
23
+ def humanized_application_name
24
+ app_name.underscore.humanize.gsub(/\S+/, &:capitalize)
25
+ end
26
+
11
27
  def app_const_base
12
28
  @app_const_base ||= app_name.gsub(/\W/, '_').squeeze('_').camelize
13
29
  end
@@ -30,5 +46,20 @@ module Pineapples
30
46
  SecureRandom.hex(64)
31
47
  end
32
48
 
49
+ def preexisting_git_repo?
50
+ git_path = File.expand_path('.git', app_root)
51
+ File.exist?(git_path)
52
+ end
53
+
54
+ def rbenv_installed?
55
+ @rbenv_installed = `which rbenv`.length > 0 if @rbenv_installed.nil?
56
+ @rbenv_installed
57
+ end
58
+
59
+ def rvm_installed?
60
+ @rvm_installed = `rvm -v`.length > 0 if @rvm_installed.nil?
61
+ @rvm_installed
62
+ end
63
+
33
64
  end
34
65
  end
@@ -1,37 +1,42 @@
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
1
+ module Pineapples
2
+ class Parser
3
+ def self.parse(args)
4
+ options = OpenStruct.new
5
+ options.app_name = nil
6
+ options.testing = false
7
+
8
+ parser = OptionParser.new do |opts|
9
+ opts.banner = 'Usage: pineapples [options] NEW_APP_DIRECTORY'
10
+
11
+ opts.on('-t', '--testing', 'Runs pineapples in testing mode, without git setup') do
12
+ options.testing = true
13
+ end
14
+
15
+ opts.on('-h', '--help', 'Show pineapples usage') do
16
+ self.usage_and_exit(opts)
17
+ end
18
+
19
+ opts.on_tail('-v', '--version', 'Show version') do
20
+ puts Pineapples::VERSION
21
+ exit 1
22
+ end
23
+ end
24
+
25
+ begin
26
+ parser.parse!
27
+ options.app_name = ARGV.first
28
+
29
+ raise OptionParser::InvalidOption if options.app_name.nil?
30
+
31
+ options
32
+ rescue OptionParser::InvalidOption
33
+ self.usage_and_exit(parser)
34
+ end
35
+ end
36
+
37
+ def self.usage_and_exit(parser)
38
+ say parser
39
+ exit 1
40
+ end
41
+ end
42
+ end