kitestrings 1.0.2 → 1.0.3
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 +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +10 -0
- data/kitestrings.gemspec +0 -2
- data/lib/generators/kitestrings/install_generator.rb +26 -6
- data/lib/generators/kitestrings/message_templates/default.text.erb +7 -0
- data/lib/generators/kitestrings/message_templates/index.html.haml +26 -0
- data/lib/generators/kitestrings/{templates → message_templates}/message.rb.erb +19 -2
- data/lib/generators/kitestrings/message_templates/message_mailer.rb +19 -0
- data/lib/generators/kitestrings/message_templates/message_migration.rb +20 -0
- data/lib/generators/kitestrings/message_templates/message_spec.rb +73 -0
- data/lib/generators/kitestrings/message_templates/messages.rb +11 -0
- data/lib/generators/kitestrings/message_templates/messages_controller.rb +41 -0
- data/lib/generators/kitestrings/message_templates/messages_controller_spec.rb +86 -0
- data/lib/generators/kitestrings/message_templates/show.html.haml +32 -0
- data/lib/generators/kitestrings/messages_generator.rb +64 -1
- data/lib/generators/templates/{deploy.rb → config/deploy.rb} +19 -16
- data/lib/generators/templates/config/deploy/integ.rb +3 -0
- data/lib/generators/templates/config/deploy/production.rb +12 -0
- data/lib/generators/templates/config/deploy/uat.rb +3 -0
- data/lib/generators/templates/config/environments/integ.rb +21 -0
- data/lib/generators/templates/config/environments/uat.rb +21 -0
- data/lib/generators/templates/views/public/403.html +30 -0
- data/lib/kitestrings/menu.rb +10 -0
- data/lib/kitestrings/menu/admin_controller.rb +21 -0
- data/lib/kitestrings/menu/controller.rb +24 -0
- data/lib/kitestrings/menu/item.rb +94 -0
- data/lib/kitestrings/menu/item_collection.rb +29 -0
- data/lib/kitestrings/menu/model.rb +29 -0
- data/lib/kitestrings/menu/view_helper.rb +68 -0
- data/lib/kitestrings/version.rb +1 -1
- data/spec/lib/generators/kitestrings/install_generator_spec.rb +17 -13
- data/spec/lib/generators/kitestrings/messages_generator_spec.rb +31 -3
- data/spec/lib/kitestrings/menu/model_spec.rb +33 -0
- data/spec/support/active_record.rb +0 -1
- data/spec/support/generator_support.rb +15 -0
- metadata +30 -35
- data/lib/generators/templates/deploy/integ.rb +0 -21
- data/lib/generators/templates/deploy/production.rb +0 -26
- data/lib/generators/templates/deploy/uat.rb +0 -23
@@ -1,10 +1,73 @@
|
|
1
1
|
module Kitestrings
|
2
2
|
module Generators
|
3
3
|
class MessagesGenerator < Rails::Generators::Base
|
4
|
-
|
4
|
+
|
5
|
+
include Rails::Generators::Migration
|
6
|
+
|
7
|
+
source_root File.expand_path("../message_templates", __FILE__)
|
5
8
|
|
6
9
|
def setup_messages_model
|
7
10
|
template "message.rb.erb", "app/models/message.rb"
|
11
|
+
copy_file "message_mailer.rb", "app/mailers/message_mailer.rb"
|
12
|
+
copy_file "default.text.erb", "app/views/message_mailer/default.text.erb"
|
13
|
+
copy_file "message_spec.rb", "spec/models/message_spec.rb"
|
14
|
+
copy_file "messages.rb", "spec/factories/messages.rb"
|
15
|
+
copy_file "messages_controller.rb", "app/controllers/messages_controller.rb"
|
16
|
+
copy_file "messages_controller_spec.rb", "spec/controllers/messages_controller_spec.rb"
|
17
|
+
copy_file "index.html.haml", "app/views/messages/index.html.haml"
|
18
|
+
copy_file "show.html.haml", "app/views/messages/show.html.haml"
|
19
|
+
|
20
|
+
if Dir.glob(destination_root + "/db/migrate/*create_messages.rb").count == 0
|
21
|
+
migration_template "message_migration.rb", "db/migrate/create_messages.rb"
|
22
|
+
end
|
23
|
+
|
24
|
+
routes = <<RUBY
|
25
|
+
resources :messages, only: [:index, :show]
|
26
|
+
# also nest under user, for example:
|
27
|
+
# resources :user do
|
28
|
+
# resources :messages, only: [:index, :show]
|
29
|
+
# end
|
30
|
+
RUBY
|
31
|
+
inject_into_file "config/routes.rb", routes, :before => /^end/
|
32
|
+
|
33
|
+
|
34
|
+
puts <<OUTPUT
|
35
|
+
-------------------------------------------------------------------------------
|
36
|
+
|
37
|
+
Kitestrings Message scaffold. Please complete the following manually:
|
38
|
+
|
39
|
+
1. Check config/routes.rb for nesting messages under the user model. For example:
|
40
|
+
|
41
|
+
resources :user do
|
42
|
+
resources :messages, only: [:index, :show]
|
43
|
+
end
|
44
|
+
|
45
|
+
2. Update CanCan abilities so users can read their messages, for example:
|
46
|
+
|
47
|
+
can(:read, Message) { |message| message.user == user }
|
48
|
+
can(:index_all, Message) if user.admin?
|
49
|
+
|
50
|
+
3. Add the following to your user model
|
51
|
+
|
52
|
+
has_many :messages
|
53
|
+
|
54
|
+
4. Set the default host. This is needed as the Message model needs to generate
|
55
|
+
absolute URLs to be inserted into email bodies. Example, add to routes.rb:
|
56
|
+
|
57
|
+
default_url_options :host => (ENV['DEFAULT_URL_HOST'] || 'localhost')
|
58
|
+
|
59
|
+
5. Add "message" and "message_other" to your common lets. Example:
|
60
|
+
|
61
|
+
# Messages
|
62
|
+
let(:message) { create :message, user: user }
|
63
|
+
let(:message_other) { create :message, user: user_other }
|
64
|
+
|
65
|
+
-------------------------------------------------------------------------------
|
66
|
+
OUTPUT
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.next_migration_number(dirname)
|
70
|
+
Time.now.utc.strftime("%Y%m%d%H%M%S")
|
8
71
|
end
|
9
72
|
end
|
10
73
|
end
|
@@ -5,18 +5,20 @@ require 'airbrake/capistrano'
|
|
5
5
|
|
6
6
|
set :stages, %w(integ, uat, production)
|
7
7
|
set :default_stage, "integ"
|
8
|
-
set :application, '
|
9
|
-
set :user, '
|
8
|
+
set :application, 'APP_NAME'
|
9
|
+
set :user, 'APP_NAME'
|
10
10
|
set (:deploy_to) { "/home/#{user}/apps/#{rails_env}" }
|
11
11
|
set :deploy_via, :remote_cache
|
12
12
|
set :use_sudo, false
|
13
13
|
set :scm, 'git'
|
14
|
-
|
14
|
+
|
15
|
+
#set :repository, 'git@github.com:2rk/APP_NAME.git'
|
15
16
|
|
16
17
|
set :ssl, false
|
17
|
-
# set :ssl_certificates_path, '/home/
|
18
|
-
# set :ssl_certificates_name, '
|
18
|
+
# set :ssl_certificates_path, '/home/APP_NAME/ssl'
|
19
|
+
# set :ssl_certificates_name, 'APP_NAME'
|
19
20
|
|
21
|
+
set :rvm_ruby_string, File.read(".ruby-version").chomp
|
20
22
|
set :mysql_password, YAML::load_file("config/database.yml.server")["production"]["password"]
|
21
23
|
set :bundle_flags, "--deployment"
|
22
24
|
|
@@ -68,9 +70,11 @@ conf
|
|
68
70
|
|
69
71
|
|
70
72
|
task :github_ssh_key do
|
71
|
-
run "ssh-keygen -t rsa -f ~/.ssh/id_rsa -P '';
|
73
|
+
run "if [ ! -f ~/.ssh/id_rsa ]; then ssh-keygen -t rsa -f ~/.ssh/id_rsa -P ''; fi"
|
74
|
+
# This will return an error back but it is not an issue
|
75
|
+
run "ssh -T -oStrictHostKeyChecking=no git@github.com; true"
|
76
|
+
run "cat .ssh/id_rsa.pub"
|
72
77
|
end
|
73
|
-
|
74
78
|
task :symlink_config do
|
75
79
|
run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml"
|
76
80
|
end
|
@@ -102,7 +106,7 @@ namespace :ruby_make do
|
|
102
106
|
desc "Run a task on a remote server."
|
103
107
|
# run like: cap staging rake:invoke task=a_certain_task
|
104
108
|
task :invoke do
|
105
|
-
run("cd #{deploy_to}/current;
|
109
|
+
run("cd #{deploy_to}/current; bin/rake #{ENV['task']} RAILS_ENV=#{rails_env}")
|
106
110
|
end
|
107
111
|
end
|
108
112
|
|
@@ -121,16 +125,15 @@ namespace :deploy do
|
|
121
125
|
end
|
122
126
|
desc "reload the database with seed data"
|
123
127
|
task :seed do
|
124
|
-
run "cd #{current_path};
|
128
|
+
run "cd #{current_path}; bin/rake db:seed RAILS_ENV=#{rails_env}"
|
125
129
|
end
|
126
130
|
end
|
127
131
|
|
128
|
-
namespace :rvm do
|
129
|
-
task :trust_rvmrc do
|
130
|
-
run "rvm rvmrc trust #{release_path}"
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
after "deploy", "rvm:trust_rvmrc"
|
135
132
|
after 'deploy:setup', 'deploy:create_database', 'deploy:github_ssh_key', 'deploy:nginx_conf', 'deploy:create_shared_database_config'
|
136
133
|
after 'deploy:cold', 'deploy:airbrake_test'
|
134
|
+
|
135
|
+
before 'deploy:setup', 'rvm:install_rvm' # update RVM
|
136
|
+
before 'deploy:setup', 'rvm:install_ruby'
|
137
|
+
|
138
|
+
# load additional deploy steps and configuration from lib/capistrano/*.cap files:
|
139
|
+
Dir["lib/capistrano/*.cap"].each { |file| load file }
|
@@ -0,0 +1,12 @@
|
|
1
|
+
set :rails_env, 'production'
|
2
|
+
|
3
|
+
$:.unshift(File.expand_path('./lib', ENV['rvm_path']))
|
4
|
+
|
5
|
+
set :rvm_install_ruby_params, '--verify-downloads 1'
|
6
|
+
set :rvm_type, :user
|
7
|
+
set :branch, 'master'
|
8
|
+
|
9
|
+
#default_run_option[:pty] = true
|
10
|
+
ssh_options[:forward_agent] = true
|
11
|
+
|
12
|
+
#server 'APP_NAME.production.tworedkites.com', :web, :app, :db, primary: true
|
@@ -0,0 +1,21 @@
|
|
1
|
+
load File.expand_path("../production.rb", __FILE__)
|
2
|
+
|
3
|
+
Rails.application.configure do
|
4
|
+
|
5
|
+
config.loglevel = :debug
|
6
|
+
|
7
|
+
# config.airbrake_api_key = 'AIRBRAKE_KEY'
|
8
|
+
|
9
|
+
# used by message model to create links (outside of a controller / mailer)
|
10
|
+
Rails.application.routes.default_url_options[:host] = 'APP_NAME.integ.tworedkites.com'
|
11
|
+
|
12
|
+
# config.action_mailer.delivery_method = :mail_gate
|
13
|
+
# config.action_mailer.mail_gate_settings = {
|
14
|
+
# :whitelist => /VALIDATE_EMAIL_REGEX/,
|
15
|
+
# :subject_prefix => '[INTEG] ',
|
16
|
+
# :delivery_method => :smtp,
|
17
|
+
# :smtp_settings => {
|
18
|
+
# :address => 'smtp.example.com'
|
19
|
+
# }
|
20
|
+
# }
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
load File.expand_path("../production.rb", __FILE__)
|
2
|
+
|
3
|
+
Rails.application.configure do
|
4
|
+
|
5
|
+
config.log_level = :info
|
6
|
+
|
7
|
+
# config.airbrake_api_key = 'AIRBRAKE_KEY'
|
8
|
+
|
9
|
+
# used by message model to create links (outside of a controller / mailer)
|
10
|
+
Rails.application.routes.default_url_options[:host] = 'APP_NAME.uat.tworedkites.com'
|
11
|
+
|
12
|
+
# config.action_mailer.delivery_method = :mail_gate
|
13
|
+
# config.action_mailer.mail_gate_settings = {
|
14
|
+
# :whitelist => /VALIDATE_EMAIL_REGEX/,
|
15
|
+
# :subject_prefix => '[UAT] ',
|
16
|
+
# :delivery_method => :smtp,
|
17
|
+
# :smtp_settings => {
|
18
|
+
# :address => 'smtp.example.com'
|
19
|
+
# }
|
20
|
+
# }
|
21
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Access Denied (403)</title>
|
5
|
+
<style type="text/css">
|
6
|
+
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
|
7
|
+
div.dialog {
|
8
|
+
width: 25em;
|
9
|
+
padding: 0 4em;
|
10
|
+
margin: 4em auto 0 auto;
|
11
|
+
border: 1px solid #ccc;
|
12
|
+
border-right-color: #999;
|
13
|
+
border-bottom-color: #999;
|
14
|
+
}
|
15
|
+
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
|
16
|
+
</style>
|
17
|
+
</head>
|
18
|
+
|
19
|
+
<body>
|
20
|
+
<!-- This file lives in public/500.html -->
|
21
|
+
<div class="dialog">
|
22
|
+
<h1>Access Denied.</h1>
|
23
|
+
<p>
|
24
|
+
You do not have permissions to view the current page.
|
25
|
+
</p>
|
26
|
+
<p> </p>
|
27
|
+
<p>Click <a href="/">here</a> to return to the home page.</p>
|
28
|
+
</div>
|
29
|
+
</body>
|
30
|
+
</html>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Kitestrings
|
2
|
+
module Menu::AdminController
|
3
|
+
def menu_context
|
4
|
+
Admin.new
|
5
|
+
end
|
6
|
+
|
7
|
+
# this class acts like a Menu::Item
|
8
|
+
class Admin
|
9
|
+
|
10
|
+
# pretend to be a persisted resource (new pages don't show context menu)
|
11
|
+
def persisted?
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
# use 'admin' as the menu partial name
|
16
|
+
def partial_name
|
17
|
+
"admin"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Kitestrings
|
2
|
+
module Menu::Controller
|
3
|
+
# return an array of the menu items constructed as polymorphic paths. For example, if loaded_resources was:
|
4
|
+
# [Company:1, Project:2, Audit:3] then this would return an array of Menu::Item objects for the following paths:
|
5
|
+
# - /companies/1
|
6
|
+
# - /companies/1/projects/2
|
7
|
+
# - /companies/1/projects/2/audits/3
|
8
|
+
#
|
9
|
+
# Each item is constructed with polymorphic path
|
10
|
+
def loaded_menu_items
|
11
|
+
@loaded_menu_items ||= Menu::ItemCollection.new(loaded_resources)
|
12
|
+
end
|
13
|
+
|
14
|
+
# get the menu item for the contextual menu (second row). On an index page, this is the item the index is nested
|
15
|
+
# under, if present. For normal pages it is the last item in the array.
|
16
|
+
def current_menu_item
|
17
|
+
if action_name == "index"
|
18
|
+
loaded_menu_items[-2]
|
19
|
+
else
|
20
|
+
loaded_menu_items[-1]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Kitestrings::Menu
|
2
|
+
# A class to represent an item in the menu. It is capable of looking up menu item paths and names and a link id,
|
3
|
+
# all the required data to construct links, include links to subpaths
|
4
|
+
class Item
|
5
|
+
include Rails.application.routes.url_helpers
|
6
|
+
|
7
|
+
attr :resources
|
8
|
+
attr_accessor :active
|
9
|
+
|
10
|
+
def initialize(resources)
|
11
|
+
@resources = resources
|
12
|
+
end
|
13
|
+
|
14
|
+
# the path of the item. eg: /companies/1/projects/2/audits/3
|
15
|
+
def path
|
16
|
+
@path ||= polymorphic_path @resources
|
17
|
+
end
|
18
|
+
|
19
|
+
# return a new item with the given extra resources added to the resource list.
|
20
|
+
def sub_item(*extras)
|
21
|
+
Item.new([*@resources, *extras].compact)
|
22
|
+
end
|
23
|
+
|
24
|
+
def parent_item
|
25
|
+
Item.new(resources[0..-2])
|
26
|
+
end
|
27
|
+
|
28
|
+
# return the menu display name for the object. This defaults to the .name method of an instance, and the
|
29
|
+
# localised human name for classes.
|
30
|
+
def name
|
31
|
+
object.try(:menu_display_name)
|
32
|
+
end
|
33
|
+
|
34
|
+
# return the name of a menu partial to use for contextual menus relating to this item.
|
35
|
+
def partial_name
|
36
|
+
last = @resources.last
|
37
|
+
klass = last.is_a?(Class) ? last : last.class
|
38
|
+
klass.model_name.underscore
|
39
|
+
end
|
40
|
+
|
41
|
+
# fetch the last object in the chain. This is the resource that is actually being rendered. If this is an
|
42
|
+
# index action, this will be the class representing the type to be shown in the list.
|
43
|
+
def object
|
44
|
+
@resources.last
|
45
|
+
end
|
46
|
+
|
47
|
+
# a string to use as a link id in the menu link. Eg: for the path /companies/1/projects/2, the link would be
|
48
|
+
# menu_companies_projects_link
|
49
|
+
def link_id
|
50
|
+
names = @resources.map do |resource|
|
51
|
+
case resource
|
52
|
+
when Class
|
53
|
+
resource.name.pluralize.downcase
|
54
|
+
else
|
55
|
+
resource.class.name.downcase
|
56
|
+
end
|
57
|
+
end
|
58
|
+
"menu_#{names.join('_')}_link"
|
59
|
+
end
|
60
|
+
|
61
|
+
# Active is set on the last item in the Menu::ItemCollection based on the assumption that this is the active item
|
62
|
+
# in the collection.
|
63
|
+
def active?
|
64
|
+
@active
|
65
|
+
end
|
66
|
+
|
67
|
+
# Should the item be hidden in the menus? If so, menu_link_to will not generate any output. Implement a menu_hidden
|
68
|
+
# instance or class method to hide that instance or class from the menu.
|
69
|
+
def hidden?
|
70
|
+
if object.respond_to? :menu_hidden
|
71
|
+
object.menu_hidden
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def collection?
|
76
|
+
object.is_a?(Class)
|
77
|
+
end
|
78
|
+
|
79
|
+
# if this item is for a resource instance (eg: companies/1 => <# Company id:1 #>, then make a new item representing
|
80
|
+
# the collection of that class, eg: companies/ => <# Company class #>
|
81
|
+
def index_item
|
82
|
+
if @resources.last && @resources.last.is_a?(ActiveRecord::Base)
|
83
|
+
index_resources = @resources.dup
|
84
|
+
index_resources << index_resources.pop.class
|
85
|
+
Item.new index_resources
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# true if the object is persisted. Classes are not persisted.
|
90
|
+
def persisted?
|
91
|
+
object.respond_to?(:persisted?) && object.persisted?
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
module Kitestrings
|
4
|
+
class Menu::ItemCollection < ::SimpleDelegator
|
5
|
+
attr :items
|
6
|
+
|
7
|
+
def initialize(loaded_resources)
|
8
|
+
length = loaded_resources.length
|
9
|
+
@items = (0...length).map do |count|
|
10
|
+
Menu::Item.new loaded_resources[0..count]
|
11
|
+
end
|
12
|
+
|
13
|
+
# if the last item in the resources is a new_record? object, then substitute it for the class. This will
|
14
|
+
# cause polymorphic path to show the #index action in the breadcrumb instead of the new action, or a route
|
15
|
+
# error looking for an object that has no id.
|
16
|
+
last = @items.last
|
17
|
+
if last && last.object.respond_to?(:new_record?) && last.object.new_record?
|
18
|
+
@items.pop
|
19
|
+
@items << Menu::Item.new(last.resources[0..-2] + [last.object.class])
|
20
|
+
end
|
21
|
+
|
22
|
+
# the last item in the array is assumed to be active.
|
23
|
+
@items.last.active = true unless items.empty?
|
24
|
+
|
25
|
+
# delegate all methods to this array object
|
26
|
+
super(@items)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Kitestrings::Menu::Model
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
class_attribute :menu_name_method
|
6
|
+
|
7
|
+
# default to :name
|
8
|
+
self.menu_name_method = :name
|
9
|
+
end
|
10
|
+
|
11
|
+
# get the display name for this item in the menu structure. Defaults to the :name method, can be specified by setting
|
12
|
+
# the menu_name_method class attribute on the class.
|
13
|
+
def menu_display_name
|
14
|
+
case
|
15
|
+
when respond_to?(menu_name_method)
|
16
|
+
self.send(menu_name_method)
|
17
|
+
else
|
18
|
+
"##{to_key}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
module ClassMethods
|
23
|
+
# Get the display name of the collection for this class (index action). This uses ActiveModel::Naming to fetch
|
24
|
+
# the plural name of the resource class.
|
25
|
+
def menu_display_name
|
26
|
+
self.model_name.human.pluralize.titlecase
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|