shoelaces 0.1.0

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 (68) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/.ruby-version +1 -0
  4. data/.travis.yml +11 -0
  5. data/CONTRIBUTING.md +37 -0
  6. data/Gemfile +3 -0
  7. data/Gemfile.lock +131 -0
  8. data/LICENSE +21 -0
  9. data/README.md +211 -0
  10. data/Rakefile +8 -0
  11. data/bin/rake +16 -0
  12. data/bin/rspec +16 -0
  13. data/bin/setup +13 -0
  14. data/bin/shoelaces +13 -0
  15. data/lib/shoelaces.rb +4 -0
  16. data/lib/shoelaces/actions.rb +29 -0
  17. data/lib/shoelaces/app_builder.rb +437 -0
  18. data/lib/shoelaces/generators/app_generator.rb +233 -0
  19. data/lib/shoelaces/version.rb +5 -0
  20. data/shoelaces.gemspec +53 -0
  21. data/spec/fakes/bin/heroku +5 -0
  22. data/spec/fakes/bin/hub +5 -0
  23. data/spec/features/github_spec.rb +10 -0
  24. data/spec/features/heroku_spec.rb +19 -0
  25. data/spec/features/new_project_spec.rb +77 -0
  26. data/spec/spec_helper.rb +24 -0
  27. data/spec/support/fake_github.rb +21 -0
  28. data/spec/support/fake_heroku.rb +38 -0
  29. data/spec/support/shoelaces.rb +49 -0
  30. data/templates/Gemfile.erb +63 -0
  31. data/templates/Guardfile +33 -0
  32. data/templates/Procfile +2 -0
  33. data/templates/README.md.erb +34 -0
  34. data/templates/_analytics.html.erb +7 -0
  35. data/templates/_flashes.html.erb +7 -0
  36. data/templates/_javascript.html.erb +12 -0
  37. data/templates/_variables.scss +2 -0
  38. data/templates/about.html.erb.erb +67 -0
  39. data/templates/action_mailer.rb +5 -0
  40. data/templates/application.css.scss +18 -0
  41. data/templates/background_jobs_rspec.rb +19 -0
  42. data/templates/bin_setup.erb +34 -0
  43. data/templates/config_locales_en.yml +16 -0
  44. data/templates/contact.html.erb.erb +67 -0
  45. data/templates/database_cleaner_rspec.rb +21 -0
  46. data/templates/development_seeds.rb +12 -0
  47. data/templates/disable_xml_params.rb +3 -0
  48. data/templates/errors.rb +34 -0
  49. data/templates/factory_girl_rspec.rb +3 -0
  50. data/templates/high_voltage.rb +3 -0
  51. data/templates/home.html.erb.erb +16 -0
  52. data/templates/i18n.rb +3 -0
  53. data/templates/newrelic.yml.erb +34 -0
  54. data/templates/noise.png +0 -0
  55. data/templates/postgresql_database.yml.erb +12 -0
  56. data/templates/rack_timeout.rb +1 -0
  57. data/templates/sample.env +3 -0
  58. data/templates/secrets.yml +14 -0
  59. data/templates/shoelaces_gitignore +13 -0
  60. data/templates/shoelaces_layout.html.erb.erb +25 -0
  61. data/templates/shoelaces_layout_footer.html.erb.erb +11 -0
  62. data/templates/shoelaces_layout_header.html.erb.erb +33 -0
  63. data/templates/smtp.rb +9 -0
  64. data/templates/spec_helper.rb +30 -0
  65. data/templates/staging.rb +5 -0
  66. data/templates/travis.yml.erb +24 -0
  67. data/templates/unicorn.rb +30 -0
  68. metadata +232 -0
@@ -0,0 +1,233 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/rails/app/app_generator'
3
+
4
+ module Shoelaces
5
+ class AppGenerator < Rails::Generators::AppGenerator
6
+ class_option :database, :type => :string, :aliases => '-d', :default => 'postgresql',
7
+ :desc => "Preconfigure for selected database (options: #{DATABASES.join('/')})"
8
+
9
+ class_option :heroku, :type => :boolean, :aliases => '-H', :default => false,
10
+ :desc => 'Create staging and production Heroku apps'
11
+
12
+ class_option :github, :type => :string, :aliases => '-G', :default => nil,
13
+ :desc => 'Create Github repository and add remote origin pointed to repo'
14
+
15
+ class_option :skip_test_unit, :type => :boolean, :aliases => '-T', :default => true,
16
+ :desc => 'Skip Test::Unit files'
17
+
18
+ class_option :port, :type => :string, :aliases => '-P', :default => nil,
19
+ :desc => 'port number'
20
+
21
+ def finish_template
22
+ invoke :shoelaces_customization
23
+ super
24
+ end
25
+
26
+ def shoelaces_customization
27
+ invoke :set_custom_port_number
28
+ invoke :customize_gemfile
29
+ invoke :setup_development_environment
30
+ invoke :setup_test_environment
31
+ invoke :setup_production_environment
32
+ invoke :setup_staging_environment
33
+ invoke :setup_secret_token
34
+ invoke :create_shoelaces_views
35
+ invoke :create_image_assets
36
+ invoke :create_static_pages
37
+ invoke :setup_coffeescript
38
+ invoke :configure_app
39
+ invoke :setup_stylesheets
40
+ invoke :copy_miscellaneous_files
41
+ invoke :customize_error_pages
42
+ invoke :remove_routes_comment_lines
43
+ invoke :setup_git
44
+ invoke :setup_database
45
+ invoke :create_heroku_apps
46
+ invoke :create_github_repo
47
+ invoke :setup_segment_io
48
+ invoke :outro
49
+ end
50
+
51
+ def set_custom_port_number
52
+ if options[:port]
53
+ get_builder_class.set_port_number(options[:port].to_i)
54
+ end
55
+ end
56
+
57
+ def customize_gemfile
58
+ build :replace_gemfile
59
+ build :set_ruby_to_version_being_used
60
+
61
+ if options[:heroku]
62
+ build :setup_heroku_specific_gems
63
+ end
64
+
65
+ bundle_command 'install'
66
+ end
67
+
68
+ def setup_database
69
+ say 'Setting up database'
70
+
71
+ if 'postgresql' == options[:database]
72
+ build :use_postgres_config_template
73
+ end
74
+
75
+ build :create_database
76
+ end
77
+
78
+ def setup_development_environment
79
+ say 'Setting up the development environment'
80
+ build :raise_on_delivery_errors
81
+ build :raise_on_unpermitted_parameters
82
+ build :provide_setup_script
83
+ build :provide_dev_prime_task
84
+ build :configure_generators
85
+ build :configure_i18n_for_development_environment
86
+ end
87
+
88
+ def setup_test_environment
89
+ say 'Setting up the test environment'
90
+ build :set_up_factory_girl_for_rspec
91
+ build :generate_rspec
92
+ build :configure_rspec
93
+ build :configure_background_jobs_for_rspec
94
+ build :enable_database_cleaner
95
+ build :configure_spec_support_features
96
+ build :configure_travis
97
+ build :configure_i18n_for_test_environment
98
+ build :configure_action_mailer_in_specs
99
+ end
100
+
101
+ def setup_production_environment
102
+ say 'Setting up the production environment'
103
+ build :configure_newrelic
104
+ build :configure_smtp
105
+ build :enable_rack_deflater
106
+ build :setup_asset_host
107
+ end
108
+
109
+ def setup_staging_environment
110
+ say 'Setting up the staging environment'
111
+ build :setup_staging_environment
112
+ end
113
+
114
+ def setup_secret_token
115
+ say 'Moving secret token out of version control'
116
+ build :setup_secret_token
117
+ end
118
+
119
+ def create_shoelaces_views
120
+ say 'Creating shoelaces views'
121
+ build :create_partials_directory
122
+ build :create_shared_flashes
123
+ build :create_application_layout
124
+ end
125
+
126
+ def create_image_assets
127
+ say 'Creating image assets'
128
+ build :add_images
129
+ end
130
+
131
+ def create_static_pages
132
+ say 'Creating static pages'
133
+ build :add_static_pages
134
+ end
135
+
136
+ def setup_coffeescript
137
+ say 'Setting up CoffeeScript defaults'
138
+ build :remove_turbolinks
139
+ build :setup_bootstrap_javascript
140
+ end
141
+
142
+ def configure_app
143
+ say 'Configuring app'
144
+ build :configure_action_mailer
145
+ build :configure_time_zone
146
+ build :configure_time_formats
147
+ build :configure_rack_timeout
148
+ build :disable_xml_params
149
+ build :fix_i18n_deprecation_warning
150
+ build :setup_default_rake_task
151
+ build :configure_unicorn
152
+ build :setup_foreman
153
+ build :setup_guard
154
+ build :generate_simple_form
155
+ build :use_high_voltage_config_template
156
+ end
157
+
158
+ def setup_stylesheets
159
+ say 'Set up stylesheets'
160
+ build :setup_stylesheets
161
+ end
162
+
163
+ def setup_git
164
+ if !options[:skip_git]
165
+ say 'Initializing git'
166
+ invoke :setup_gitignore
167
+ invoke :init_git
168
+ end
169
+ end
170
+
171
+ def create_heroku_apps
172
+ if options[:heroku]
173
+ say 'Creating Heroku apps'
174
+ build :create_heroku_apps
175
+ build :set_heroku_remotes
176
+ build :set_heroku_rails_secrets
177
+ end
178
+ end
179
+
180
+ def create_github_repo
181
+ if !options[:skip_git] && options[:github]
182
+ say 'Creating Github repo'
183
+ build :create_github_repo, options[:github]
184
+ end
185
+ end
186
+
187
+ def setup_segment_io
188
+ say 'Setting up Segment.io'
189
+ build :setup_segment_io
190
+ end
191
+
192
+ def setup_gitignore
193
+ build :gitignore_files
194
+ end
195
+
196
+ def init_git
197
+ build :init_git
198
+ end
199
+
200
+ def copy_miscellaneous_files
201
+ say 'Copying miscellaneous support files'
202
+ build :copy_miscellaneous_files
203
+ end
204
+
205
+ def customize_error_pages
206
+ say 'Customizing the 500/404/422 pages'
207
+ build :customize_error_pages
208
+ end
209
+
210
+ def remove_routes_comment_lines
211
+ build :remove_routes_comment_lines
212
+ end
213
+
214
+ def outro
215
+ say 'Congratulations! You just pulled our shoelaces.'
216
+ say "Remember to run 'rails generate airbrake' with your API key."
217
+ end
218
+
219
+ def run_bundle
220
+ # Let's not: We'll bundle manually at the right spot
221
+ end
222
+
223
+ protected
224
+
225
+ def get_builder_class
226
+ Shoelaces::AppBuilder
227
+ end
228
+
229
+ def using_active_record?
230
+ !options[:skip_active_record]
231
+ end
232
+ end
233
+ end
@@ -0,0 +1,5 @@
1
+ module Shoelaces
2
+ RAILS_VERSION = '4.1.4'
3
+ RUBY_VERSION = IO.read("#{File.dirname(__FILE__)}/../../.ruby-version").strip
4
+ VERSION = '0.1.0'
5
+ end
@@ -0,0 +1,53 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'shoelaces/version'
4
+ require 'date'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.required_ruby_version = ">= #{Shoelaces::RUBY_VERSION}"
8
+ s.authors = ['jonr22', 'thoughtbot']
9
+ s.date = Date.today.strftime('%Y-%m-%d')
10
+
11
+ s.description = <<-HERE
12
+ Shoelaces is a base Rails project that you can upgrade. It has been forked from
13
+ thoughtbot's Suspenders.
14
+
15
+ Use Shoelaces if you love Suspenders but want to use bootstrap instead of bourbon.
16
+
17
+ Modified to use bootstrap instead of bourbon.
18
+
19
+ Changes from Suspenders:
20
+ - added bootstrap
21
+ - added guard
22
+ - added default layout
23
+ - added simple form installation (w/ bootstrap)
24
+ - added pow to setup script
25
+ - added custom port configuration (use Sholeaces [app name] -P [port number])
26
+ - added paperclip
27
+ - removed shared javascripts
28
+ - removed bourbon, bitters, and neat
29
+ - removed flutie
30
+
31
+ HERE
32
+
33
+ s.email = 'jonr2219@gmail.com'
34
+ s.executables = ['shoelaces']
35
+ s.extra_rdoc_files = %w[README.md LICENSE]
36
+ s.files = `git ls-files`.split("\n")
37
+ s.homepage = 'http://github.com/jonr22/shoelaces'
38
+ s.license = 'MIT'
39
+ s.name = 'shoelaces'
40
+ s.rdoc_options = ['--charset=UTF-8']
41
+ s.require_paths = ['lib']
42
+ s.summary = "Generate a Rails app using best practices."
43
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
44
+ s.version = Shoelaces::VERSION
45
+
46
+ s.add_dependency 'bundler', '~> 1.3'
47
+ s.add_dependency 'rails', Shoelaces::RAILS_VERSION
48
+
49
+ s.add_development_dependency 'aruba', '~> 0.5'
50
+ s.add_development_dependency 'cucumber', '~> 1.2'
51
+ s.add_development_dependency 'rspec', '~> 2.0'
52
+ s.add_development_dependency 'capybara', '~> 2.2', '>= 2.2.0'
53
+ end
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path(File.join('..', '..', 'support', 'fake_heroku'), File.dirname(__FILE__))
4
+
5
+ FakeHeroku.new(ARGV).run!
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path(File.join('..', '..', 'support', 'fake_github'), File.dirname(__FILE__))
4
+
5
+ FakeGithub.new(ARGV).run!
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ feature 'GitHub' do
4
+ scenario 'Shoelaces a project with --github option' do
5
+ repo_name = 'test'
6
+ run_shoelaces("--github=#{repo_name}")
7
+
8
+ expect(FakeGithub).to have_created_repo(repo_name)
9
+ end
10
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ feature 'Heroku' do
4
+ scenario 'Shoelaces a project with --heroku=true' do
5
+ run_shoelaces('--heroku=true')
6
+
7
+ expect(FakeHeroku).to have_gem_included(project_path, 'rails_12factor')
8
+ expect(FakeHeroku).to have_created_app_for('staging')
9
+ expect(FakeHeroku).to have_created_app_for('production')
10
+ expect(FakeHeroku).to have_configured_vars('staging', 'SECRET_KEY_BASE')
11
+ expect(FakeHeroku).to have_configured_vars('production', 'SECRET_KEY_BASE')
12
+
13
+ bin_setup = IO.read("#{project_path}/bin/setup")
14
+ app_name = ShoelacesTestHelpers::APP_NAME
15
+
16
+ expect(bin_setup).to include("heroku join --app #{app_name}-staging")
17
+ expect(bin_setup).to include("heroku join --app #{app_name}-production")
18
+ end
19
+ end
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+
3
+ feature 'Shoelaces a new project with default configuration' do
4
+ scenario 'specs pass' do
5
+ run_shoelaces
6
+
7
+ Dir.chdir(project_path) do
8
+ Bundler.with_clean_env do
9
+ expect(`rake`).to include('0 failures')
10
+ end
11
+ end
12
+ end
13
+
14
+ scenario 'staging config is inherited from production' do
15
+ run_shoelaces
16
+
17
+ staging_file = IO.read("#{project_path}/config/environments/staging.rb")
18
+ config_stub = "Rails.application.configure do"
19
+
20
+ expect(staging_file).to match(/^require_relative "production"/)
21
+ expect(staging_file).to match(/#{config_stub}/), staging_file
22
+ end
23
+
24
+ scenario 'generated .ruby-version is pulled from Shoelaces .ruby-version' do
25
+ run_shoelaces
26
+
27
+ ruby_version_file = IO.read("#{project_path}/.ruby-version")
28
+
29
+ expect(ruby_version_file).to eq "#{RUBY_VERSION}\n"
30
+ end
31
+
32
+ scenario 'secrets.yml reads secret from env' do
33
+ run_shoelaces
34
+
35
+ secrets_file = IO.read("#{project_path}/config/secrets.yml")
36
+
37
+ expect(secrets_file).to match(/secret_key_base: <%= ENV\["SECRET_KEY_BASE"\] %>/)
38
+ end
39
+
40
+ scenario 'action mailer support file is added' do
41
+ run_shoelaces
42
+
43
+ expect(File).to exist("#{project_path}/spec/support/action_mailer.rb")
44
+ end
45
+
46
+ scenario 'newrelic.yml reads NewRelic license from env' do
47
+ run_shoelaces
48
+
49
+ newrelic_file = IO.read("#{project_path}/config/newrelic.yml")
50
+
51
+ expect(newrelic_file).to match(
52
+ /license_key: "<%= ENV\["NEW_RELIC_LICENSE_KEY"\] %>"/
53
+ )
54
+ end
55
+
56
+ scenario 'records pageviews through Segment.io if ENV variable set' do
57
+ run_shoelaces
58
+
59
+ expect(analytics_partial).
60
+ to include(%{<% if ENV["SEGMENT_IO_KEY"] %>})
61
+ expect(analytics_partial).
62
+ to include(%{window.analytics.load("<%= ENV["SEGMENT_IO_KEY"] %>");})
63
+ end
64
+
65
+ scenario "raises on missing translations in development/test" do
66
+ run_shoelaces
67
+
68
+ %w(test development).each do |environment|
69
+ environment_file = IO.read("#{project_path}/config/environments/#{environment}.rb")
70
+ expect(environment_file).to match /^ +config.action_view.raise_on_missing_translations = true$/
71
+ end
72
+ end
73
+
74
+ def analytics_partial
75
+ IO.read("#{project_path}/app/views/application/_analytics.html.erb")
76
+ end
77
+ end
@@ -0,0 +1,24 @@
1
+ require 'capybara/rspec'
2
+ require 'bundler/setup'
3
+
4
+ Bundler.require(:default, :test)
5
+
6
+ require (Pathname.new(__FILE__).dirname + '../lib/shoelaces').expand_path
7
+
8
+ Dir['./spec/support/**/*.rb'].each { |file| require file }
9
+
10
+ RSpec.configure do |config|
11
+ config.include ShoelacesTestHelpers
12
+
13
+ config.before(:all) do
14
+ create_tmp_directory
15
+ end
16
+
17
+ config.before(:each) do
18
+ drop_dummy_database
19
+ remove_project_directory
20
+
21
+ FakeHeroku.clear!
22
+ FakeGithub.clear!
23
+ end
24
+ end
@@ -0,0 +1,21 @@
1
+ class FakeGithub
2
+ RECORDER = File.expand_path(File.join('..', '..', 'tmp', 'hub_commands'), File.dirname(__FILE__))
3
+
4
+ def initialize(args)
5
+ @args = args
6
+ end
7
+
8
+ def run!
9
+ File.open(RECORDER, 'a') do |file|
10
+ file.write @args.join(' ')
11
+ end
12
+ end
13
+
14
+ def self.clear!
15
+ FileUtils.rm_rf RECORDER
16
+ end
17
+
18
+ def self.has_created_repo?(repo_name)
19
+ File.read(RECORDER) == "create #{repo_name}"
20
+ end
21
+ end