kitestrings 1.0.2 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e359fb5855cd726d02dd9c2a51508e1d0a3bb848
|
4
|
+
data.tar.gz: 2cf04623592f47430d13f1da9c0bf81f3f78c122
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b02af42e038270039c4ce945729900c9c232086708c53988221bc26f3380367c44501b3c5c4b22641df175a2fe8406f631216fc4654d7b2fd6c7602c8c5a8d5
|
7
|
+
data.tar.gz: fa7776a4bc5cab3baf5b54cd82f0959b3b3215b70ffad2cbe96a9308f059c03eeee76f21396d0922a2e0ff39e5d3c971f21ecb54d741a2cb772ae7c56e0ca568
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# Version history:
|
2
2
|
|
3
|
+
## Next
|
4
|
+
|
5
|
+
* Added Kitestrings::Menu classes/modules to assist with rendering menus in web pages.
|
6
|
+
* Added generator: kitestrings:messages to add a scaffold model and controller.
|
7
|
+
|
8
|
+
## 1.0.3
|
9
|
+
|
10
|
+
* Added an Access Denied page to be shown when a CanCan::AccessDenied error occurs (except in develop/test)
|
11
|
+
* Added UAT and INTEG environments and deploy files to install generator.
|
12
|
+
|
3
13
|
## 1.0.2
|
4
14
|
|
5
15
|
* Added FormObject#update to behave like persisted active record model objects.
|
data/kitestrings.gemspec
CHANGED
@@ -19,12 +19,10 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_runtime_dependency "rails", ">= 3.2"
|
22
|
-
spec.add_runtime_dependency "activemodel", ">= 3.2"
|
23
22
|
|
24
23
|
spec.add_development_dependency "bundler", "~> 1.6"
|
25
24
|
spec.add_development_dependency "rake"
|
26
25
|
spec.add_development_dependency "rspec", "~> 2.14"
|
27
26
|
spec.add_development_dependency "generator_spec"
|
28
27
|
spec.add_development_dependency "sqlite3"
|
29
|
-
spec.add_development_dependency "activerecord", ">= 3.2"
|
30
28
|
end
|
@@ -8,12 +8,10 @@ module Kitestrings
|
|
8
8
|
|
9
9
|
desc "Copies 2rk relevant templates to the relevant directory"
|
10
10
|
|
11
|
-
def
|
12
|
-
copy_file "deploy.rb", "config/deploy.rb"
|
13
|
-
|
14
|
-
|
15
|
-
def copy_deploy_files
|
16
|
-
directory "deploy", "config/deploy"
|
11
|
+
def copy_config_files
|
12
|
+
copy_file "config/deploy.rb", "config/deploy.rb"
|
13
|
+
directory "config/deploy", "config/deploy"
|
14
|
+
directory "config/environments", "config/environments"
|
17
15
|
end
|
18
16
|
|
19
17
|
def copy_haml_files
|
@@ -35,6 +33,28 @@ module Kitestrings
|
|
35
33
|
def copy_app_view_files
|
36
34
|
copy_file "views/application/_navigation.html.haml", "app/views/application/_navigation.html.haml"
|
37
35
|
copy_file "views/layouts/application.html.haml", "app/views/layouts/application.html.haml"
|
36
|
+
copy_file "views/public/403.html", "app/views/public/403.html"
|
37
|
+
end
|
38
|
+
|
39
|
+
def setup_application_controller
|
40
|
+
inject_into_file "app/controllers/application_controller.rb", :after => /protect_from_forgery.*$/ do
|
41
|
+
<<-EOF
|
42
|
+
|
43
|
+
|
44
|
+
unless Rails.application.config.consider_all_requests_local
|
45
|
+
rescue_from CanCan::AccessDenied do |exception|
|
46
|
+
# Notify errbit if you would like to:
|
47
|
+
# Airbrake.notify(exception)
|
48
|
+
render 'public/403', status: 403, layout: 'none'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
EOF
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def setup_directories
|
56
|
+
empty_directory("lib/capistrano")
|
57
|
+
create_file("lib/capistrano/.keep")
|
38
58
|
end
|
39
59
|
end
|
40
60
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
.page-header
|
2
|
+
%h1 Listing messages
|
3
|
+
|
4
|
+
.row
|
5
|
+
.col-md-12
|
6
|
+
%table.table.table-striped
|
7
|
+
%tr
|
8
|
+
%th.subject= sortable_title :subject
|
9
|
+
%th= sortable_title :sent_at
|
10
|
+
%th= sortable_title :user_name
|
11
|
+
%th Link
|
12
|
+
%th= sortable_title :clicked_at
|
13
|
+
%th= sortable_title :id
|
14
|
+
|
15
|
+
- @messages.each do |message|
|
16
|
+
%tr
|
17
|
+
%td.subject= message.user && link_to(message.subject || "(none)", user_message_path(message.user_id, message))
|
18
|
+
%td= l message.created_at
|
19
|
+
%td= message.user && link_to_if(can?(:show, message.user), message.user.try(:full_name), user_path(message.user.id))
|
20
|
+
%td= link_to message.link, message_path(message)
|
21
|
+
%td= message.clicked_at ? l(message.clicked_at) : nil
|
22
|
+
%td= message.id
|
23
|
+
%br
|
24
|
+
|
25
|
+
%p.pagination
|
26
|
+
= paginate @messages
|
@@ -9,7 +9,7 @@ class Message < ActiveRecord::Base
|
|
9
9
|
<% end %>
|
10
10
|
serialize :options
|
11
11
|
|
12
|
-
include Rails.application.
|
12
|
+
include Rails.application.routes.url_helpers
|
13
13
|
|
14
14
|
after_create :send_email
|
15
15
|
|
@@ -41,7 +41,7 @@ class Message < ActiveRecord::Base
|
|
41
41
|
|
42
42
|
# prepare a mail object ready for delivery by email or display on the screen
|
43
43
|
def mail
|
44
|
-
@mail ||= MessageMailer.prepare_message(self
|
44
|
+
@mail ||= MessageMailer.prepare_message(self)
|
45
45
|
end
|
46
46
|
|
47
47
|
# The "view" link. This is the link to the messages controller that marks the message
|
@@ -53,4 +53,21 @@ class Message < ActiveRecord::Base
|
|
53
53
|
def name
|
54
54
|
"Message ID: #{id}"
|
55
55
|
end
|
56
|
+
|
57
|
+
def add_attachments(mailer)
|
58
|
+
# This is called by the mailer to add any attachments. For example:
|
59
|
+
# if context.is_a? CalendarEvent
|
60
|
+
# mailer.attachments.inline["calendar.ics"] = context.to_ical
|
61
|
+
# end
|
62
|
+
end
|
63
|
+
|
64
|
+
# return the mail body as a string, skipping any attachment parts that may be in the message
|
65
|
+
def mail_body
|
66
|
+
if mail.multipart?
|
67
|
+
part = mail.parts.select { |p| p.text? && !p.attachment? }.first
|
68
|
+
part.body.to_s
|
69
|
+
else
|
70
|
+
mail.body.to_s
|
71
|
+
end
|
72
|
+
end
|
56
73
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class MessageMailer < ActionMailer::Base
|
2
|
+
#TODO set default from address
|
3
|
+
default from: "noreply@example.com"
|
4
|
+
|
5
|
+
attr :subject
|
6
|
+
|
7
|
+
def prepare_message(message)
|
8
|
+
@message = message
|
9
|
+
@user = message.user
|
10
|
+
|
11
|
+
# ask the message model if we need any attachments added
|
12
|
+
message.add_attachments(self)
|
13
|
+
|
14
|
+
m = mail(to: message.user.email, subject: message.subject, template_name: message.template || :default)
|
15
|
+
# allow template to override subject in the view by doing: <% @message.subject = "new subject" %>
|
16
|
+
m.subject = message.subject
|
17
|
+
m
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class CreateMessages < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :messages do |t|
|
4
|
+
t.references :user
|
5
|
+
t.string :template
|
6
|
+
t.string :context_type
|
7
|
+
t.integer :context_id
|
8
|
+
t.string :link
|
9
|
+
t.string :subject
|
10
|
+
t.datetime :clicked_at
|
11
|
+
t.datetime :sent_at
|
12
|
+
t.text :options
|
13
|
+
|
14
|
+
t.timestamps
|
15
|
+
end
|
16
|
+
|
17
|
+
add_index :messages, :user_id
|
18
|
+
add_index :messages, [:context_type, :context_id]
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Message do
|
4
|
+
|
5
|
+
let(:freeze_1) { Time.zone.now.change(:usec => 0) }
|
6
|
+
|
7
|
+
common_lets
|
8
|
+
|
9
|
+
context "relationships" do
|
10
|
+
it { should belong_to(:user) }
|
11
|
+
it { should belong_to(:context) }
|
12
|
+
end
|
13
|
+
|
14
|
+
context "validations" do
|
15
|
+
# validate the common_lets generated message instance:
|
16
|
+
it { expect(message).to be_valid }
|
17
|
+
it { should validate_presence_of(:user) }
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'latest' do
|
21
|
+
before do
|
22
|
+
Timecop.freeze(Time.local(1990)) do
|
23
|
+
message_other
|
24
|
+
message
|
25
|
+
end
|
26
|
+
end
|
27
|
+
it { expect(Message.latest).to match_array([message_other, message]) }
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#mail" do
|
31
|
+
# Example test for mail content:
|
32
|
+
# let(:message) { Message.new(template: "report_untag", context: relation, options: {foo: "bar"}, user: user_owner) }
|
33
|
+
# context "rendering email" do
|
34
|
+
# subject { message.mail }
|
35
|
+
# it { expect(subject.subject).to eq("Tag Removed Notification") }
|
36
|
+
# it { expect(subject.body).to include("The following tag has just been removed") }
|
37
|
+
# end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#view_link" do
|
41
|
+
subject { message }
|
42
|
+
it "production" do
|
43
|
+
Rails.application.routes.stub(:default_url_options => {:host => 'example.com'})
|
44
|
+
Rails.env.stub(:production? => true)
|
45
|
+
expect(subject.view_link).to eq("http://example.com/messages/#{message.id}")
|
46
|
+
end
|
47
|
+
it "development" do
|
48
|
+
expect(subject.view_link).to eq("http://localhost/messages/#{message.id}")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
context '#send_email' do
|
54
|
+
context 'build only' do
|
55
|
+
before do
|
56
|
+
message.update_column(:sent_at, nil)
|
57
|
+
ActionMailer::Base.deliveries.clear
|
58
|
+
message.mail
|
59
|
+
end
|
60
|
+
it { expect(message.sent_at).to be_nil }
|
61
|
+
it { ActionMailer::Base.deliveries.should be_empty }
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'build and send' do
|
65
|
+
before do
|
66
|
+
Timecop.freeze(freeze_1) { message.send_email }
|
67
|
+
end
|
68
|
+
|
69
|
+
it { ActionMailer::Base.deliveries.last.to.should == [user.email] }
|
70
|
+
it { message.sent_at.should == freeze_1 }
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class MessagesController < ApplicationController
|
2
|
+
|
3
|
+
include PageAndSortHelper
|
4
|
+
include PageAndSortHelper::Controller
|
5
|
+
helper PageAndSortHelper
|
6
|
+
|
7
|
+
before_filter do
|
8
|
+
authenticate_user!
|
9
|
+
load_and_authorize_if_present :user do
|
10
|
+
load_and_authorize :message
|
11
|
+
end
|
12
|
+
load_and_authorize :message
|
13
|
+
end
|
14
|
+
|
15
|
+
def index
|
16
|
+
@messages =
|
17
|
+
case
|
18
|
+
when @user
|
19
|
+
@user.messages
|
20
|
+
when can?(:index_all, Message)
|
21
|
+
Message
|
22
|
+
else
|
23
|
+
current_user.messages
|
24
|
+
end
|
25
|
+
|
26
|
+
@messages = page_and_sort(@messages, default_sort: :created_at, default_direction: :desc)
|
27
|
+
end
|
28
|
+
|
29
|
+
# this one controller action has two totally different functions:
|
30
|
+
#
|
31
|
+
# 1. /users/1/messages/3 => show the message content
|
32
|
+
# 2. /messages/3 => mark the message clicked at time and redirect to the link in the message.
|
33
|
+
def show
|
34
|
+
if @user
|
35
|
+
# show
|
36
|
+
else
|
37
|
+
@message.update_column(:clicked_at, Time.now) if current_user == @message.user
|
38
|
+
redirect_to @message.link
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MessagesController do
|
4
|
+
render_views
|
5
|
+
common_lets
|
6
|
+
|
7
|
+
before :all do
|
8
|
+
Fracture.define_selector :new_message_link
|
9
|
+
Fracture.define_selector :cancel_new_message_link
|
10
|
+
Fracture.define_selector :edit_message_link
|
11
|
+
Fracture.define_selector :cancel_edit_message_link
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'not logged in' do
|
15
|
+
{index: :get, show: :get}.each do |v, m|
|
16
|
+
it "#{m} #{v} should logout" do
|
17
|
+
self.send(m, v, id: message)
|
18
|
+
should redirect_to new_user_session_path
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context "signed in" do
|
24
|
+
before do
|
25
|
+
sign_in user
|
26
|
+
controller.should_receive(:authenticate_user!).and_call_original
|
27
|
+
end
|
28
|
+
|
29
|
+
context "GET index" do
|
30
|
+
context "not nested" do
|
31
|
+
before do
|
32
|
+
controller.should_receive(:authorize!).with(:index, Message)
|
33
|
+
message; message_other
|
34
|
+
get :index
|
35
|
+
end
|
36
|
+
it { should assign_to(:messages).with_items([message]) }
|
37
|
+
it { should render_template :index }
|
38
|
+
it { should have_only_fractures }
|
39
|
+
end
|
40
|
+
|
41
|
+
context "under user" do
|
42
|
+
before do
|
43
|
+
controller.should_receive(:authorize!).with(:show, user)
|
44
|
+
controller.should_receive(:authorize!).with(:index, user => Message)
|
45
|
+
controller.should_receive(:authorize!).with(:index, Message)
|
46
|
+
message; message_other
|
47
|
+
get :index, :user_id => user.id
|
48
|
+
end
|
49
|
+
it { should assign_to(:messages).with_items([message]) }
|
50
|
+
it { should render_template :index }
|
51
|
+
it { should have_only_fractures }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "GET show" do
|
56
|
+
context "not nested" do # this is the redirect action. This link appears in the email.
|
57
|
+
before do
|
58
|
+
message.update_column :link, "/some/location"
|
59
|
+
Timecop.freeze(freeze_1) do
|
60
|
+
get :show, id: message
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
it { should assign_to(:message).with(message) }
|
65
|
+
it { should assign_to("message.clicked_at").with(freeze_1) }
|
66
|
+
it { should_not render_template :show }
|
67
|
+
it { should redirect_to("/some/location") }
|
68
|
+
end
|
69
|
+
|
70
|
+
# context 'not as the owner of the message' do
|
71
|
+
# it { expects_access_denied { get :show, id: message_other } }
|
72
|
+
# end
|
73
|
+
|
74
|
+
context "under user" do
|
75
|
+
before do
|
76
|
+
controller.should_receive(:authorize!).with(:show, user)
|
77
|
+
controller.should_receive(:authorize!).with(:show, message)
|
78
|
+
get :show, user_id: user, id: message
|
79
|
+
end
|
80
|
+
it { should assign_to(:message).with(message) }
|
81
|
+
it { should render_template :show }
|
82
|
+
it { should have_only_fractures }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
%h1 Message
|
2
|
+
|
3
|
+
.row.form-horizontal
|
4
|
+
.col-md-1
|
5
|
+
%label.control-label Subject
|
6
|
+
.col-md-9
|
7
|
+
%p.form-text
|
8
|
+
%b= @message.subject
|
9
|
+
.row
|
10
|
+
.col-md-1
|
11
|
+
%label.control-label Date Sent
|
12
|
+
.col-md-9
|
13
|
+
%p.form-text
|
14
|
+
= @message.sent_at ? l(@message.sent_at) : "(not sent)"
|
15
|
+
.row
|
16
|
+
.col-md-1
|
17
|
+
%label.control-label Body
|
18
|
+
.col-md-9
|
19
|
+
%p
|
20
|
+
= simple_format(@message.mail_body)
|
21
|
+
-# or add the `gem "rails_autolink"` to Gemfile to detect links in the message body:
|
22
|
+
-#= simple_format(auto_link(@message.mail_body))
|
23
|
+
|
24
|
+
-#- if @message.mail.attachments.any?
|
25
|
+
-# .row
|
26
|
+
-# .col-md-1
|
27
|
+
-# %label.control-label Attachments
|
28
|
+
-# .col-md-9
|
29
|
+
-# %ul
|
30
|
+
-# - @message.mail.attachments.each_with_index do |attachment, index|
|
31
|
+
-# %li
|
32
|
+
-# = link_to(attachment.filename, company_user_message_attachment_path(@company, @user, @message, index+1))
|