orats 0.2.0

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