orats 0.2.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d6bad42dd6b612594bb115996f943c6343ed6aac
4
+ data.tar.gz: 39d518e79e1f5ab96f67c13989e969e83dd9372b
5
+ SHA512:
6
+ metadata.gz: c80b52eb4bc604a7841b5eabacc6ddba6ac1d12404b3a96bffadec0a3e164e044445d7fc61fd450a3815a3168007706afca8ca946aec27ded2c7ac0ee0409e3b
7
+ data.tar.gz: 3df85308dc2ec16d8fdf5a2838605fc45110a796c25c228c13bf59fdebe25fa978a60a6d41664e6484ef9bb2e2afc31687b672b904178f0495c0a1cfcf568650
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ .DS_Store
2
+ */**.DS_Store
3
+ ._*
4
+ .*.sw*
5
+ *~
6
+ .idea/
7
+ .gem
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,19 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ orats (0.2.0)
5
+ thor (~> 0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ rake (10.1.1)
11
+ thor (0.18.1)
12
+
13
+ PLATFORMS
14
+ ruby
15
+
16
+ DEPENDENCIES
17
+ bundler (~> 1.5)
18
+ orats!
19
+ rake
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Nick Janetakis <nick.janetakis@gmail.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ 'Software'), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,199 @@
1
+ ## What is orats and what problem does it solve?
2
+
3
+ It stands for opinionated rails application templates. This repository has a collection of opinionated templates
4
+ to get you up and going with a modern rails application stack. They are accessed through the [orats gem](#installation).
5
+
6
+ I noticed I kept making the same changes to every single rails app I made and it actually takes quite a bit of time to
7
+ setup all of this manually each time you make an app.
8
+
9
+ It is clearly a problem that can be automated so I sat down and started to create a few templates to do just that.
10
+
11
+ ## What version of Rails and Ruby are you targeting?
12
+
13
+ #### Rails 4.0.x and Ruby 2.1.x
14
+
15
+ I will be updating them as new versions come out and when the gems used are proven to work. All important gems in the Gemfile
16
+ are locked using the pessimistic operator `~>` so you can be sure that everything plays nice as long as rubygems.org is up!
17
+
18
+ ## System dependencies that apply to every template
19
+
20
+ - [The orats gem](#installation)
21
+ - To download each rails template and automate running certain tasks.
22
+ - Ruby 2.1.x
23
+ - Yep, you really need Ruby to run Ruby modules.
24
+ - Rails 4.0.x
25
+ - You also need Rails installed so that you can run the project generator.
26
+ - Git
27
+ - The weapon of choice for version control.
28
+ - Postgres
29
+ - All of the templates use postgres as a primary persistent database.
30
+ - Redis
31
+ - Used as a sidekiq background worker and as the rails cache back end.
32
+
33
+ ## Contents
34
+
35
+ - orats
36
+ - [Installation](#installation)
37
+ - [Commands](#commands)
38
+ - Templates
39
+ - [Base](#base-template)
40
+ - [Authentication and authorization](#authentication-and-authorization)
41
+ - [Application deployment](#application-deployment)
42
+ - [Server provisioning](#server-provisioning)
43
+ - Sections
44
+ - [Expanding beyond the base template](#expanding-beyond-the-base-template)
45
+ - [Production tweaks](#production-tweaks)
46
+
47
+ ## orats
48
+
49
+ ### Installation
50
+
51
+ `gem install orats`
52
+
53
+
54
+ ### Commands
55
+
56
+ #### Application tasks
57
+
58
+ - Create a new rails application using the base template.
59
+ - `orats base <app name> --postgres-password <insert your development postgres db password>`
60
+ - Optionally takes `--postgres-location [localhost]`
61
+ - Optionally takes `--postgres-username [postgres]`
62
+
63
+ - Create a new rails application with authentication/authorization.
64
+ - `orats auth <app name> --postgres-password <insert your development postgres db password>`
65
+ - Optionally takes `--postgres-location [localhost]`
66
+ - Optionally takes `--postgres-username [postgres]`
67
+
68
+ - Delete an application and optionally its postgres databases and redis namespace.
69
+ - `orats nuke <app name>`
70
+ - Optionally takes `--delete-data [true]`
71
+
72
+ #### Why is it asking me for my development postgres password?
73
+
74
+ The password is it asking for is only for your development database. It will **never** ask for your production passwords.
75
+
76
+ In order to automate certain tasks such as running database migrations the script must be able to talk to your database.
77
+ It cannot talk to your database without knowing the location, username and password for postgres. In most cases the
78
+ location will be `localhost` and the username will be `postgres` so these values are provided by default.
79
+
80
+ If you are curious about the implementation details feel free to [take a look](https://github.com/nickjj/orats/blob/master/orats.thor#L127).
81
+
82
+ ## Base template
83
+
84
+ This is the starter template that every other template will append to. I feel like when I make a new project, 95% of the time
85
+ it includes these features and when I do not want a specific thing it is much quicker to remove it than add it.
86
+
87
+ ### Features that are included in the base template
88
+
89
+ - Add a few popular OS and editor files to the .gitignore file.
90
+ - Create development, staging and production environments.
91
+ - Use environment variables for things that are likely to change per environment.
92
+ - Use environment variables for anything that is sensitive and should not be included into version control.
93
+ - Use redis as the cache backend.
94
+ - Use sidekiq as a background worker.
95
+ - Use puma as the server with settings capable of doing phased restarts.
96
+ - Use foreman in development mode to manage starting both the rails server using puma and sidekiq.
97
+ - Set the production asset precompiler to include fonts and png files.
98
+ - Set the production logger to rotate the logs daily.
99
+ - Use DHH's config gem to store application wide configuration variables.
100
+ - Set the timezone to EST.
101
+ - Change how validation errors are reported by having them be displayed inline for each element.
102
+ - Dry out the `database.yml` and use postgres.
103
+ - Setup a sitemap that updates itself once a day using a cronjob managed through the `whenever` gem.
104
+ - Add a route level concern for pagination and use kaminari for pagination.
105
+ - Add a rake task which generates favicons for every popular device and a view helper to include them in your layout.
106
+ - Add 2 view helpers, `humanize_boolean` and `css_for_boolean` to nicely output true/false values and they can be changed easily.
107
+ - Add 3 view helpers to easily set a page's title, meta description and page heading. All of which are optional.
108
+ - Bootstrap ~3 layout file with conditionally loaded `html5shiv`, `json3` and `respondjs` libs for IE < 9 support.
109
+ - Separate the navigation, navigation links, flash messages, footer and google analytics snippets into partials.
110
+ - Public 404, 422, 500 and 502 pages so they can be served directly from your web server.
111
+ - Use sass and coffeescript.
112
+ - jquery 1.10.x loaded through a CDN.
113
+ - Use bootstrap ~3 and font awesome using the standard community gems.
114
+ - Rack mini profiler, bullet and meta_request support for development mode profiling and analysis.
115
+
116
+ Everything has been added with proper git commits so you have a trail of changes.
117
+
118
+ ### Try it
119
+
120
+ `orats base myapp --postgres-password <development postgres db password>`
121
+
122
+ ### All I see is the default rails page
123
+
124
+ Yes, this has been done by choice. I have no idea what your rails project is supposed to do. Rather than write in a million
125
+ questions into the template generator it expects you to dive in and start implementing your shiny new rails application.
126
+
127
+ ### Production tweaks
128
+
129
+ There are a few settings you need to be aware of for when you deploy your application into production. You also need to be
130
+ aware that the `.env` file is not loaded in production, in fact it is not even sent to your server because it is in .gitignore.
131
+
132
+ You can use the `.env` file as a guide so you know which values you need to write out as true ENV variables on your server
133
+ using whatever server provisioning tools you use.
134
+
135
+ #### Puma
136
+
137
+ You should set your puma min/max threads to 0 and 16 and use at least 2 workers if you want to do phased restarts. From
138
+ there you can load test your deploy and tinker as necessary.
139
+
140
+ In production mode it is expected that you will be placing your rails app behind a web server such as nginx or apache. If
141
+ you do not do this then you must open `config/puma.rb` and check out the `RAILS_ENV` conditional because by default it will
142
+ not listen on a port in production. Instead it will use a unix socket.
143
+
144
+ #### Sidekiq
145
+
146
+ Sidekiq's concurrency value is 25 by default, again experiment with what works best for you because there is no reasonable
147
+ default magic value that works for everyone.
148
+
149
+ #### Postgres
150
+
151
+ You should set the pool size to be the maximum between your puma max threads and sidekiq concurrency value but it does not
152
+ have to be exact. Feel free to experiment.
153
+
154
+ ## Authentication and authorization
155
+
156
+ Authentication is extremely common but the use cases of authentication vary by a lot. You might want 3 user profile
157
+ models that have foreign keys back to a devise model while someone else might only want to add 1 field directly on the devise model.
158
+ The authentication template was designed just to give you enough to get the ball rolling on your upcoming project.
159
+
160
+ ### Additional features added to the base template
161
+
162
+ - Devise for authentication.
163
+ - Devise async so that all of devise's e-mails are sent using sidekiq.
164
+ - Pundit for authorization. It seems to be gaining popularity over CanCan since ryan is MIA?
165
+ - Sensible defaults for the devise initializer file by placing all of the secrets into the `.env` file.
166
+ - Enable session timeouts and unlock strategies in the devise initializer.
167
+ - Bootstrap flavored view templates.
168
+ - A devise model called `Account` which contains a standard devise model with a `role` field added.
169
+ - `admin` and `guest` roles have been added to the `Account` model and the guest role is the default at the database level.
170
+ - An `.is?` method to determine if an account's role is equal to the role you pass in.
171
+ - The `Account` model has been enhanced to cache the `current_account` in redis so you do not have to perform a db lookup on every request.
172
+ - A basic pundit application policy has been generated.
173
+ - Alias `current_account` to `current_user` so that pundit and other potential gems will work as intended.
174
+ - Create a seed account in `db/seeds.rb` which acts as an admin, you should change these details asap.
175
+ - Toggle whether or not users can publicly register on the site and/or delete their account very easily.
176
+ - Expose a `/sidekiq` end-point which requires an admin account to access so you can view the queue details.
177
+
178
+ ### Preventing users from being able to register
179
+
180
+ You can disable users from registering by taking a look at `config/routes.rb` and inspecting the comments near the top.
181
+ I feel like this is the cleanest way to disable registrations while still allowing users to edit and/or delete their account.
182
+
183
+ ### Try it
184
+
185
+ `orats auth myapp --postgres-password <development postgres db password>`
186
+
187
+ ## Server provisioning
188
+
189
+ I really like chef and I think at some point there might be a template which creates an application cookbook which provisions
190
+ every dependency required to setup this stack using **ubuntu server 12.04 LTS**.
191
+
192
+ I don't think it will ever get too advanced because deployment is very specific to each application but it can at least
193
+ dump out a ~200 line cookbook that configures everything to get a server up and running and all you would have to do is
194
+ change a few settings in the chef attributes file and setup an encrypted data bag like usual.
195
+
196
+ Right now I have a template in the works that will get you from an empty ubuntu server to a fully working server that
197
+ can do everything but handle deploying your rails application. Normally I use capistrano to deploy my app but I want to
198
+ move away from that and let chef handle it but I do not have the chef chops to do this yet. I will gladly accept any pull
199
+ requests to add this functionality in.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
data/bin/orats ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # inject ../../lib into the $LOAD_PATH, this is useful because
4
+ # when developing locally on a gem the require paths will be
5
+ # different because the lib directory is not on the $LOAD_PATH
6
+
7
+ # since git directories are not included in gem releases we can
8
+ # determine if the gem is being actively developed by searching
9
+ # for a git repo
10
+ git_path = File.expand_path('../../.git', __FILE__)
11
+
12
+ if File.exist?(git_path)
13
+ $:.unshift(File.expand_path('../../lib', __FILE__))
14
+ end
15
+
16
+ require 'orats/cli'
17
+ Orats::Orats.start(ARGV)
data/lib/orats.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'orats/version'
2
+ require 'orats/cli'
3
+
4
+ module Orats
5
+ end
data/lib/orats/cli.rb ADDED
@@ -0,0 +1,89 @@
1
+ require 'thor'
2
+ require 'orats/shell'
3
+ require 'orats/server'
4
+
5
+ module Orats
6
+ class Orats < Thor
7
+ include Thor::Actions
8
+ include Shell
9
+ include Server
10
+
11
+ attr_accessor :app_name, :app_name_only
12
+
13
+ class_option :postgres_location, default: 'localhost'
14
+ class_option :postgres_username, default: 'postgres'
15
+
16
+ option :postgres_password, required: true
17
+ desc 'base APP_NAME', 'Create a new rails application using the base template.'
18
+ def base(app_name)
19
+ @app_name = app_name
20
+
21
+ run "rails new #{@app_name} --skip-bundle --template #{File.expand_path File.dirname(__FILE__)}/templates/commands/base.rb"
22
+
23
+ gsub_postgres_info options
24
+ git_commit 'Change the postgres information'
25
+
26
+ bundle_install
27
+ git_commit 'Add gem lock file'
28
+
29
+ run_rake 'db:create:all db:migrate db:test:prepare'
30
+ git_commit 'Add the database schema file'
31
+
32
+ foreman_start unless invoked?
33
+ end
34
+
35
+ option :postgres_password, required: true
36
+ desc 'auth APP_NAME', 'Create a new rails application with authentication/authorization.'
37
+ def auth(app_name)
38
+ @app_name = app_name
39
+
40
+ invoke :base
41
+
42
+ run "rails new #{@app_name} --skip --skip-bundle --template #{File.expand_path File.dirname(__FILE__)}/templates/commands/auth.rb"
43
+
44
+ run_rake 'db:migrate db:seed'
45
+
46
+ foreman_start unless invoked?
47
+ end
48
+
49
+ desc 'nuke APP_NAME', 'Delete an application and optionally its postgres databases and redis namespace.'
50
+ option :postgres_password, required: false
51
+ option :delete_data, type: :boolean, default: true
52
+ def nuke(app_name)
53
+ @app_name = app_name
54
+
55
+ puts
56
+ say_status 'nuke', "\e[1mYou are about to permanently delete this directory:\e[0m", :red
57
+ say_status 'path', "#{File.expand_path(app_name)}", :yellow
58
+
59
+ if options[:delete_data]
60
+ puts
61
+ say_status 'nuke', "\e[1mYou are about to permanently delete these postgres databases:\e[0m", :red
62
+ say_status 'databases', "#{app_name_only} and #{app_name_only}_test", :yellow
63
+ puts
64
+ say_status 'nuke', "\e[1mYou are about to permanently delete this redis namespace:\e[0m", :red
65
+ say_status 'namespace', app_name_only, :yellow
66
+ end
67
+ puts
68
+
69
+ confirmed_to_delete = yes?('Are you sure? (y/N)', :cyan)
70
+
71
+ if confirmed_to_delete
72
+ if options[:delete_data]
73
+ run_rake 'db:drop:all'
74
+ nuke_redis
75
+ nuke_directory
76
+ end
77
+ end
78
+ end
79
+
80
+ private
81
+ def app_name_only
82
+ @app_name.split('/').last
83
+ end
84
+
85
+ def invoked?
86
+ caller_locations(0).any? { |backtrace| backtrace.label == 'invoke' }
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,50 @@
1
+ require 'socket'
2
+ require 'timeout'
3
+
4
+ module Orats
5
+ module Server
6
+ def foreman_start
7
+ puts '', '='*80
8
+ say_status 'action', "\e[1mStarting server with the following commands:\e[0m", :cyan
9
+ say_status 'command', "cd #{@app_name}", :magenta
10
+ say_status 'command', 'bundle exec foreman start', :magenta
11
+ puts '='*80, ''
12
+
13
+ attempt_to_start
14
+ end
15
+
16
+ private
17
+
18
+ def attempt_to_start
19
+ while port_taken? do
20
+ puts
21
+ say_status 'error', "\e[1mAnother application is using port 3000\n\e[0m", :red
22
+ puts '-'*80
23
+
24
+ exit 1 if no?('Would you like to try running the server again? (y/N)', :cyan)
25
+ end
26
+
27
+ puts
28
+ run_with_cd 'bundle exec foreman start'
29
+ end
30
+
31
+ def port_taken?
32
+ begin
33
+ Timeout::timeout(5) do
34
+ begin
35
+ s = TCPSocket.new('localhost', 3000)
36
+ s.close
37
+
38
+ return true
39
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
40
+ return false
41
+ end
42
+ end
43
+ rescue Timeout::Error
44
+ false
45
+ end
46
+
47
+ false
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,49 @@
1
+ module Orats
2
+ module Shell
3
+ def run_with_cd(command)
4
+ run "cd #{@app_name} && #{command} && cd -"
5
+ end
6
+
7
+ def log_message(type, message)
8
+ puts
9
+ say_status type, "#{message}...", :yellow
10
+ puts '-'*80, ''; sleep 0.25
11
+ end
12
+
13
+ def git_commit(message)
14
+ run_with_cd "git add . && git commit -m '#{message}'"
15
+ end
16
+
17
+ def gsub_postgres_info(options)
18
+ log_message 'root', 'Changing the postgres information'
19
+
20
+ gsub_file "#{@app_name}/.env", ': localhost', ": #{options[:postgres_location]}"
21
+ gsub_file "#{@app_name}/.env", ': postgres', ": #{options[:postgres_username]}"
22
+ gsub_file "#{@app_name}/.env", ': supersecrets', ": #{options[:postgres_password]}"
23
+ end
24
+
25
+ def run_rake(command)
26
+ log_message 'shell', 'Running rake commands'
27
+
28
+ run_with_cd "bundle exec rake #{command}"
29
+ end
30
+
31
+ def bundle_install
32
+ log_message 'shell', 'Running bundle install, this may take a while'
33
+
34
+ run "cd #{@app_name} && bundle install && cd -"
35
+ end
36
+
37
+ def nuke_redis
38
+ log_message 'root', 'Removing redis keys'
39
+
40
+ run "redis-cli KEYS '#{@app_name_only}:*' | xargs --delim='\n' redis-cli DEL"
41
+ end
42
+
43
+ def nuke_directory
44
+ log_message 'root', 'Deleting directory'
45
+
46
+ run "rm -rf #{@app_name}"
47
+ end
48
+ end
49
+ end