pineapples 0.3.34 → 0.3.345

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