orats 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +19 -0
- data/LICENSE.txt +22 -0
- data/README.md +199 -0
- data/Rakefile +1 -0
- data/bin/orats +17 -0
- data/lib/orats.rb +5 -0
- data/lib/orats/cli.rb +89 -0
- data/lib/orats/server.rb +50 -0
- data/lib/orats/shell.rb +49 -0
- data/lib/orats/templates/commands/auth.rb +853 -0
- data/lib/orats/templates/commands/base.rb +809 -0
- data/lib/orats/templates/includes/Gemfile +46 -0
- data/lib/orats/version.rb +3 -0
- data/orats.gemspec +25 -0
- metadata +104 -0
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
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
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
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
|
data/lib/orats/server.rb
ADDED
@@ -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
|
data/lib/orats/shell.rb
ADDED
@@ -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
|