eastrails 0.0.5
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.
- data/CHANGELOG.md +0 -0
- data/LICENSE +20 -0
- data/README.md +44 -0
- data/ROADMAP.md +0 -0
- data/bin/eastrails +4 -0
- data/lib/eastrails.rb +12 -0
- data/lib/eastrails/commands/add.rb +31 -0
- data/lib/eastrails/commands/base.rb +18 -0
- data/lib/eastrails/commands/init.rb +63 -0
- data/lib/eastrails/components.rb +18 -0
- data/lib/eastrails/components/base.rb +77 -0
- data/lib/eastrails/components/cancan.rb +12 -0
- data/lib/eastrails/components/capistrano.rb +15 -0
- data/lib/eastrails/components/cucumber.rb +14 -0
- data/lib/eastrails/components/devise.rb +47 -0
- data/lib/eastrails/components/exception_notifier.rb +17 -0
- data/lib/eastrails/components/haml.rb +15 -0
- data/lib/eastrails/components/heroku.rb +29 -0
- data/lib/eastrails/components/jasmine.rb +22 -0
- data/lib/eastrails/components/new_relic.rb +15 -0
- data/lib/eastrails/components/rspec.rb +24 -0
- data/lib/eastrails/components/twitter_bootstrap.rb +16 -0
- data/lib/eastrails/components/vcr.rb +21 -0
- data/lib/eastrails/executor.rb +38 -0
- data/lib/eastrails/generator.rb +13 -0
- data/lib/eastrails/parameters.rb +37 -0
- data/lib/eastrails/scanner/base.rb +17 -0
- data/lib/eastrails/scanner/security.rb +13 -0
- data/lib/eastrails/thor_ext.rb +36 -0
- data/lib/eastrails/version.rb +3 -0
- data/lib/resources/capistrano/deploy.rb +38 -0
- data/lib/resources/default/controllers/welcome_controller.rb +4 -0
- data/lib/resources/default/stylesheets/application-theme-default.css.scss +11 -0
- data/lib/resources/default/stylesheets/application-theme-kickstarter.css.scss +51 -0
- data/lib/resources/default/views/layouts/_messages.html.erb +8 -0
- data/lib/resources/default/views/layouts/_navigation.html.erb +1 -0
- data/lib/resources/default/views/layouts/application.html.erb +35 -0
- data/lib/resources/default/views/welcome/index.html.erb +1 -0
- data/lib/resources/devise/registrations/edit.html.erb +27 -0
- data/lib/resources/devise/registrations/new.html.erb +18 -0
- data/lib/resources/devise/sessions/new.html.erb +16 -0
- data/lib/resources/devise/shared/_links.html.erb +25 -0
- data/lib/resources/navigation/devise.html.erb +20 -0
- data/lib/resources/vcr/features/samples/internet.feature +6 -0
- data/lib/resources/vcr/features/step_definitions/internet_steps.rb +10 -0
- data/lib/resources/vcr/features/support/vcr_cucumber.rb +12 -0
- data/lib/resources/vcr/spec/samples/sample_spec.rb +10 -0
- data/lib/resources/vcr/spec/support/vcr_rspec.rb +13 -0
- metadata +238 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
module Eastrails
|
2
|
+
module Components
|
3
|
+
class Jasmine < Base
|
4
|
+
include Eastrails::ThorExt
|
5
|
+
|
6
|
+
def add
|
7
|
+
gem 'jasmine', :group => [:development, :test]
|
8
|
+
system 'bundle install'
|
9
|
+
system "rails g jasmine:install"
|
10
|
+
if yes_wizard?("Do you want to generate jasmine sample specs?")
|
11
|
+
system "rails g jasmine:examples"
|
12
|
+
end
|
13
|
+
puts "==============================="
|
14
|
+
puts "Usage: "
|
15
|
+
puts "- Start jasmine server: rake jasmine"
|
16
|
+
puts "- Point your browser to http://localhost:8888"
|
17
|
+
puts "More information at: https://github.com/pivotal/jasmine-gem"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Eastrails
|
2
|
+
module Components
|
3
|
+
class NewRelic < Base
|
4
|
+
def add
|
5
|
+
gem 'newrelic_rpm'
|
6
|
+
puts "============================"
|
7
|
+
puts "You should do followings manually:"
|
8
|
+
puts "- Create an account at http://newrelic.com/. There you can sign up for a free Lite account or one of our paid subscriptions."
|
9
|
+
puts "- Go to app setting page, download newrelic.yml"
|
10
|
+
puts "- Place this file into your app's config directory, replacing the existing one."
|
11
|
+
puts "- Restart your application. In a few minutes, your application will send data to New Relic. Then go to New Relic to monitor your applications in production."
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Eastrails
|
2
|
+
module Components
|
3
|
+
class Rspec < Base
|
4
|
+
def add
|
5
|
+
gem 'rspec-rails', '>= 2.11.4', :group => [:development, :test]
|
6
|
+
gem 'database_cleaner', :group => :test
|
7
|
+
system 'bundle install'
|
8
|
+
system 'rails g rspec:install -f'
|
9
|
+
inject_into_file 'spec/spec_helper.rb', :after => "RSpec.configure do |config|\n" do <<-RUBY
|
10
|
+
config.before(:suite) do
|
11
|
+
DatabaseCleaner.strategy = :truncation
|
12
|
+
end
|
13
|
+
config.before(:each) do
|
14
|
+
DatabaseCleaner.start
|
15
|
+
end
|
16
|
+
config.after(:each) do
|
17
|
+
DatabaseCleaner.clean
|
18
|
+
end
|
19
|
+
RUBY
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Eastrails
|
2
|
+
module Components
|
3
|
+
class TwitterBootstrap < Base
|
4
|
+
def add
|
5
|
+
gem 'anjlab-bootstrap-rails', '>= 2.2', :require => 'bootstrap-rails'
|
6
|
+
run "bundle"
|
7
|
+
inject_into_file "app/assets/stylesheets/application.css", :before => /\s\*= require_tree/ do
|
8
|
+
" *= require twitter/bootstrap\n"
|
9
|
+
end
|
10
|
+
append_to_file "app/assets/javascripts/application.js" do
|
11
|
+
"//= require twitter/bootstrap"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Eastrails
|
2
|
+
module Components
|
3
|
+
class Vcr < Base
|
4
|
+
def add
|
5
|
+
do_if_installed("cucumber", "rspec") do
|
6
|
+
gem "vcr", require: false, group: :test
|
7
|
+
gem "webmock", require: false, group: :test
|
8
|
+
|
9
|
+
system 'bundle install'
|
10
|
+
do_if_installed("rspec") do
|
11
|
+
directory "vcr/spec", "spec"
|
12
|
+
end
|
13
|
+
|
14
|
+
do_if_installed("cucumber") do
|
15
|
+
directory "vcr/features", "features"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Eastrails
|
2
|
+
class Executor
|
3
|
+
include Thor::Actions
|
4
|
+
|
5
|
+
def initialize(args)
|
6
|
+
self.args = args
|
7
|
+
self.destination_root = File.expand_path(".")
|
8
|
+
self.behavior = :invoke
|
9
|
+
end
|
10
|
+
|
11
|
+
def execute
|
12
|
+
parameter = Eastrails::Parameters.new(args)
|
13
|
+
case parameter.command
|
14
|
+
when "init"
|
15
|
+
Eastrails::Commands::Init.new(parameter).execute
|
16
|
+
when "add"
|
17
|
+
Eastrails::Commands::Add.new(parameter).execute
|
18
|
+
when "check"
|
19
|
+
scan_security_holes
|
20
|
+
else
|
21
|
+
puts "Invalid commands"
|
22
|
+
puts "Usage: "
|
23
|
+
puts <<-RUBY
|
24
|
+
eastrails init <app_name> <comma_separated_components_names>
|
25
|
+
eastrails add <component_name>
|
26
|
+
eastrails check
|
27
|
+
RUBY
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def scan_security_holes
|
32
|
+
Eastrails::Scanner::Security.new.execute
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
attr_accessor :args
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
module Eastrails
|
3
|
+
class Generator < ::Rails::Generators::Base
|
4
|
+
include Thor::Actions
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
self.options = {}
|
8
|
+
self.behavior = :invoke
|
9
|
+
self.destination_root = File.expand_path(".")
|
10
|
+
self.class.source_root File.expand_path("../../resources", __FILE__)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Eastrails
|
2
|
+
class Parameters
|
3
|
+
attr_accessor :args
|
4
|
+
attr_accessor :options
|
5
|
+
attr_accessor :non_options
|
6
|
+
|
7
|
+
def initialize(args = [])
|
8
|
+
self.args = args.dup
|
9
|
+
self.non_options = args.select { |arg| !arg.start_with?("-") }
|
10
|
+
parse_options
|
11
|
+
end
|
12
|
+
|
13
|
+
def parse_options
|
14
|
+
self.options = {}
|
15
|
+
parser = OptionParser.new do |opts|
|
16
|
+
opts.on('-v', '--verbose', 'Print debugging details') do
|
17
|
+
options[:verbose] = true
|
18
|
+
end
|
19
|
+
|
20
|
+
opts.on('-b', '--bundle', 'Run bundle after complete') do
|
21
|
+
options[:bundle] = true
|
22
|
+
end
|
23
|
+
|
24
|
+
opts.on('-d', '--database', "Specify the database adapter as of eastrails new")
|
25
|
+
end
|
26
|
+
parser.parse!(args)
|
27
|
+
end
|
28
|
+
|
29
|
+
def command
|
30
|
+
non_options[0] || "help"
|
31
|
+
end
|
32
|
+
|
33
|
+
def component
|
34
|
+
non_options[1]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Eastrails
|
2
|
+
module Scanner
|
3
|
+
class Security < Base
|
4
|
+
def execute
|
5
|
+
self.destination_root = File.expand_path(".")
|
6
|
+
system "brakeman -o tmp/scanner.html"
|
7
|
+
system "open 'tmp/scanner.html'"
|
8
|
+
puts "You should also check http://weblog.rubyonrails.org/ for security holes"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Eastrails
|
2
|
+
module ThorExt
|
3
|
+
def say_custom(tag, text); say "\033[1m\033[36m" + tag.to_s.rjust(10) + "\033[0m" + " #{text}" end
|
4
|
+
def say_recipe(name); say "\033[1m\033[36m" + "recipe".rjust(10) + "\033[0m" + " Running #{name} recipe..." end
|
5
|
+
def say_wizard(text); say_custom(@current_recipe || 'eastrails', text) end
|
6
|
+
|
7
|
+
def ask_wizard(question)
|
8
|
+
ask "\033[1m\033[30m\033[46m" + (@current_recipe || "prompt").rjust(10) + "\033[1m\033[36m" + " #{question}\033[0m"
|
9
|
+
end
|
10
|
+
|
11
|
+
def yes_wizard?(question)
|
12
|
+
answer = ask_wizard(question + " \033[33m(y/n)\033[0m")
|
13
|
+
case answer.downcase
|
14
|
+
when "yes", "y"
|
15
|
+
true
|
16
|
+
when "no", "n"
|
17
|
+
false
|
18
|
+
else
|
19
|
+
yes_wizard?(question)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def no_wizard?(question); !yes_wizard?(question) end
|
24
|
+
|
25
|
+
def multiple_choice(question, choices)
|
26
|
+
say_custom('question', question)
|
27
|
+
values = {}
|
28
|
+
choices.each_with_index do |choice,i|
|
29
|
+
values[(i + 1).to_s] = choice[1]
|
30
|
+
say_custom( (i + 1).to_s + ')', choice[0] )
|
31
|
+
end
|
32
|
+
answer = ask_wizard("Enter your selection:") while !values.keys.include?(answer)
|
33
|
+
values[answer]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "bundler/capistrano"
|
2
|
+
|
3
|
+
set :application, "<application_name>"
|
4
|
+
set :repository, "<git_repo_url>"
|
5
|
+
|
6
|
+
set :deploy_to, "/opt/#{application}"
|
7
|
+
set :keep_releases, 10
|
8
|
+
|
9
|
+
server "<server_domain>", :app, :web, :db, :primary => true
|
10
|
+
|
11
|
+
set :scm, 'git'
|
12
|
+
set :git_enable_submodules, 1 # if you have vendored rails
|
13
|
+
set :branch, 'master'
|
14
|
+
set :git_shallow_clone, 1
|
15
|
+
set :scm_verbose, true
|
16
|
+
set :use_sudo, false
|
17
|
+
set :rails_env, "production"
|
18
|
+
|
19
|
+
set :user, "<username>"
|
20
|
+
|
21
|
+
ssh_options[:forward_agent] = true
|
22
|
+
# if you're still using the script/reaper helper you will need
|
23
|
+
# these http://github.com/rails/irs_process_scripts
|
24
|
+
|
25
|
+
# for passenger
|
26
|
+
namespace :deploy do
|
27
|
+
task :start do ; end
|
28
|
+
task :stop do ; end
|
29
|
+
task :restart, :roles => :app, :except => { :no_release => true } do
|
30
|
+
run "touch #{File.join(current_path,'tmp','restart.txt')}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
after 'deploy:update_code', 'deploy:migrate'
|
35
|
+
before "deploy", "deploy:setup"
|
36
|
+
|
37
|
+
after "deploy:restart", "deploy:cleanup"
|
38
|
+
|
@@ -0,0 +1,11 @@
|
|
1
|
+
.content {
|
2
|
+
background-color: #eee;
|
3
|
+
padding: 20px;
|
4
|
+
margin: 50px -20px 0 -20px;
|
5
|
+
-webkit-border-radius: 0 0 6px 6px;
|
6
|
+
-moz-border-radius: 0 0 6px 6px;
|
7
|
+
border-radius: 0 0 6px 6px;
|
8
|
+
-webkit-box-shadow: 0 1px 2px rgba(0,0,0,.15);
|
9
|
+
-moz-box-shadow: 0 1px 2px rgba(0,0,0,.15);
|
10
|
+
box-shadow: 0 1px 2px rgba(0,0,0,.15);
|
11
|
+
}
|
@@ -0,0 +1,51 @@
|
|
1
|
+
.navbar-inner {
|
2
|
+
background-color: #E6E6E6;
|
3
|
+
background-image: -moz-linear-gradient(top, #E6E6E6, #E6E6E6);
|
4
|
+
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#E6E6E6), to(#E6E6E6));
|
5
|
+
background-image: -webkit-linear-gradient(top, #E6E6E6, #E6E6E6);
|
6
|
+
background-image: -o-linear-gradient(top, #E5E6E6, #E6E6E6);
|
7
|
+
background-image: linear-gradient(to bottom, #E6E6E6, #E6E6E6);
|
8
|
+
}
|
9
|
+
|
10
|
+
.content {
|
11
|
+
background-color: #EDEAE3;
|
12
|
+
padding: 20px;
|
13
|
+
margin: 50px -20px 0 -20px;
|
14
|
+
-webkit-border-radius: 0 0 6px 6px;
|
15
|
+
-moz-border-radius: 0 0 6px 6px;
|
16
|
+
border-radius: 0 0 6px 6px;
|
17
|
+
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
|
18
|
+
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
|
19
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
|
20
|
+
}
|
21
|
+
|
22
|
+
$primary_color: #86C543;
|
23
|
+
|
24
|
+
a {
|
25
|
+
color: $primary_color;
|
26
|
+
}
|
27
|
+
|
28
|
+
a:hover {
|
29
|
+
color: lighten($primary_color, 10%);
|
30
|
+
text-decoration: underline;
|
31
|
+
}
|
32
|
+
|
33
|
+
.btn-primary {
|
34
|
+
color: white;
|
35
|
+
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
36
|
+
background-color: darken($primary_color, 10%);
|
37
|
+
background-image: -moz-linear-gradient(top, $primary_color, darken($primary_color, 20%));
|
38
|
+
background-image: -webkit-gradient(linear, 0 0, 0 100%, from($primary_color), to(darken($primary_color, 50%)));
|
39
|
+
background-image: -webkit-linear-gradient(top, $primary_color, darken($primary_color, 20%));
|
40
|
+
background-image: -o-linear-gradient(top, $primary_color, darken($primary_color, 20%));
|
41
|
+
background-image: linear-gradient(to bottom, $primary_color, darken($primary_color, 20%));
|
42
|
+
background-repeat: repeat-x;
|
43
|
+
border-color: darken($primary_color, 20%) darken($primary_color, 20%) darken($primary_color, 30%);
|
44
|
+
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) fadein(rgba(0, 0, 0, 0.1), 15%);
|
45
|
+
}
|
46
|
+
|
47
|
+
|
48
|
+
.btn-primary:hover, .btn-primary:active, .btn-primary.active, .btn-primary.disabled, .btn-primary[disabled] {
|
49
|
+
color: white;
|
50
|
+
background-color: darken($primary_color, 20%);
|
51
|
+
}
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<% flash.each do |name, msg| %>
|
2
|
+
<% if msg.is_a?(String) %>
|
3
|
+
<div class="alert alert-<%= name == :notice ? "success" : "error" %>">
|
4
|
+
<a class="close" data-dismiss="alert">×</a>
|
5
|
+
<%= content_tag :div, msg, :id => "flash_#{name}" %>
|
6
|
+
</div>
|
7
|
+
<% end %>
|
8
|
+
<% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= link_to "App_Name", root_path, :class => 'brand' %>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
5
|
+
<title><%= content_for?(:title) ? yield(:title) : "App_Name" %></title>
|
6
|
+
<meta name="description" content="<%= content_for?(:description) ? yield(:description) : "App_Name" %>">
|
7
|
+
<%= stylesheet_link_tag "application", :media => "all" %>
|
8
|
+
<%= javascript_include_tag "application" %>
|
9
|
+
<%= csrf_meta_tags %>
|
10
|
+
<%= yield(:head) %>
|
11
|
+
</head>
|
12
|
+
<body class="<%= controller_name %> <%= action_name %>">
|
13
|
+
<header class="navbar navbar-fixed-top">
|
14
|
+
<nav class="navbar-inner">
|
15
|
+
<div class="container">
|
16
|
+
<%= render 'layouts/navigation' %>
|
17
|
+
</div>
|
18
|
+
</nav>
|
19
|
+
</header>
|
20
|
+
<div id="main" role="main">
|
21
|
+
<div class="container">
|
22
|
+
<div class="content">
|
23
|
+
<div class="row">
|
24
|
+
<div class="span12">
|
25
|
+
<%= render 'layouts/messages' %>
|
26
|
+
<%= yield %>
|
27
|
+
</div>
|
28
|
+
</div>
|
29
|
+
<footer>
|
30
|
+
</footer>
|
31
|
+
</div>
|
32
|
+
</div> <!--! end of .container -->
|
33
|
+
</div> <!--! end of #main -->
|
34
|
+
</body>
|
35
|
+
</html>
|
@@ -0,0 +1 @@
|
|
1
|
+
Hello from Main App
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<h2>Edit <%= resource_name.to_s.humanize %></h2>
|
2
|
+
|
3
|
+
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %>
|
4
|
+
<%= devise_error_messages! %>
|
5
|
+
<p><%= f.label :name %>
|
6
|
+
<%= f.text_field :name %></p>
|
7
|
+
|
8
|
+
<div class="control-group"><%= f.label :email %>
|
9
|
+
<%= f.email_field :email %></div>
|
10
|
+
|
11
|
+
<div class="control-group"><%= f.label :password %> <i>(leave blank if you don't want to change it)</i>
|
12
|
+
<%= f.password_field :password, :autocomplete => "off" %></div>
|
13
|
+
|
14
|
+
<div class="control-group"><%= f.label :password_confirmation %>
|
15
|
+
<%= f.password_field :password_confirmation %></div>
|
16
|
+
|
17
|
+
<div class="control-group"><%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i>
|
18
|
+
<%= f.password_field :current_password %></div>
|
19
|
+
|
20
|
+
<div class="control-group"><%= f.submit "Update", :class => "btn btn-primary" %></div>
|
21
|
+
<% end %>
|
22
|
+
|
23
|
+
<h3>Cancel my account</h3>
|
24
|
+
|
25
|
+
<p>Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), :data => { :confirm => "Are you sure?" }, :method => :delete %>.</p>
|
26
|
+
|
27
|
+
<%= link_to "Back", :back %>
|