effective_email_templates 0.2.8

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.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +195 -0
  4. data/Rakefile +23 -0
  5. data/app/assets/javascripts/effective_email_templates.js +1 -0
  6. data/app/assets/stylesheets/effective_email_templates.css.scss +1 -0
  7. data/app/controllers/admin/email_templates_controller.rb +63 -0
  8. data/app/errors/effective/access_denied.rb +18 -0
  9. data/app/helpers/effective_email_templates_helper.rb +19 -0
  10. data/app/mailers/effective/email_template_mailer.rb +14 -0
  11. data/app/models/effective/datatables/email_templates.rb +22 -0
  12. data/app/models/effective/email_template.rb +55 -0
  13. data/app/views/admin/email_templates/_actions.html.haml +2 -0
  14. data/app/views/admin/email_templates/_form.html.haml +9 -0
  15. data/app/views/admin/email_templates/edit.html.haml +3 -0
  16. data/app/views/admin/email_templates/index.html.haml +3 -0
  17. data/app/views/effective/email_template_mailer/templated_email.html.haml +1 -0
  18. data/config/routes.rb +11 -0
  19. data/db/migrate/01_create_effective_email_templates.rb.erb +20 -0
  20. data/lib/effective/liquid_mailer.rb +12 -0
  21. data/lib/effective_email_templates.rb +33 -0
  22. data/lib/effective_email_templates/email_view_template.rb +29 -0
  23. data/lib/effective_email_templates/engine.rb +27 -0
  24. data/lib/effective_email_templates/liquid_resolver.rb +46 -0
  25. data/lib/effective_email_templates/template_importer.rb +46 -0
  26. data/lib/effective_email_templates/version.rb +3 -0
  27. data/lib/generators/effective_email_templates/install_generator.rb +32 -0
  28. data/lib/generators/templates/README +1 -0
  29. data/lib/generators/templates/effective_email_templates.rb +51 -0
  30. data/lib/tasks/effective_email_templates/import_default_views.rake +5 -0
  31. data/spec/controllers/admin/email_templates_controller_spec.rb +60 -0
  32. data/spec/dummy/README.rdoc +28 -0
  33. data/spec/dummy/Rakefile +6 -0
  34. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  35. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  36. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  37. data/spec/dummy/app/controllers/welcome_controller.rb +4 -0
  38. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  39. data/spec/dummy/app/mailers/liquid_resolved_mailer.rb +9 -0
  40. data/spec/dummy/app/mailers/user_liquid_mailer.rb +10 -0
  41. data/spec/dummy/app/models/user.rb +15 -0
  42. data/spec/dummy/app/views/layouts/application.html.erb +17 -0
  43. data/spec/dummy/app/views/user_liquid/after_create_user.liquid +7 -0
  44. data/spec/dummy/app/views/welcome/index.html.haml +1 -0
  45. data/spec/dummy/bin/bundle +3 -0
  46. data/spec/dummy/bin/rails +4 -0
  47. data/spec/dummy/bin/rake +4 -0
  48. data/spec/dummy/config.ru +4 -0
  49. data/spec/dummy/config/application.rb +26 -0
  50. data/spec/dummy/config/boot.rb +5 -0
  51. data/spec/dummy/config/database.yml +25 -0
  52. data/spec/dummy/config/environment.rb +5 -0
  53. data/spec/dummy/config/environments/development.rb +37 -0
  54. data/spec/dummy/config/environments/production.rb +78 -0
  55. data/spec/dummy/config/environments/test.rb +40 -0
  56. data/spec/dummy/config/initializers/assets.rb +8 -0
  57. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  58. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  59. data/spec/dummy/config/initializers/devise.rb +259 -0
  60. data/spec/dummy/config/initializers/effective_email_templates.rb +51 -0
  61. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  62. data/spec/dummy/config/initializers/inflections.rb +16 -0
  63. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  64. data/spec/dummy/config/initializers/session_store.rb +3 -0
  65. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  66. data/spec/dummy/config/locales/devise.en.yml +60 -0
  67. data/spec/dummy/config/locales/en.yml +23 -0
  68. data/spec/dummy/config/routes.rb +57 -0
  69. data/spec/dummy/config/secrets.yml +22 -0
  70. data/spec/dummy/db/migrate/20141126222940_devise_create_users.rb +42 -0
  71. data/spec/dummy/db/migrate/20141126222941_create_effective_email_templates.rb +20 -0
  72. data/spec/dummy/db/schema.rb +46 -0
  73. data/spec/dummy/public/404.html +67 -0
  74. data/spec/dummy/public/422.html +67 -0
  75. data/spec/dummy/public/500.html +66 -0
  76. data/spec/dummy/public/favicon.ico +0 -0
  77. data/spec/effective_email_templates_spec.rb +35 -0
  78. data/spec/factories/email_template.rb +12 -0
  79. data/spec/factories/user.rb +16 -0
  80. data/spec/factory_spec.rb +10 -0
  81. data/spec/lib/effective_email_templates/template_importer_spec.rb +44 -0
  82. data/spec/mailers/liquid_resolved_mailer_spec.rb +38 -0
  83. data/spec/models/email_template_spec.rb +61 -0
  84. data/spec/models/user_spec.rb +10 -0
  85. data/spec/sanity_spec.rb +7 -0
  86. data/spec/spec_helper.rb +26 -0
  87. metadata +353 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 84fc52994b336f0edeb95c8e579b18059c940495
4
+ data.tar.gz: 3c6adf8992086a0209fc8c763296978e61b47d9e
5
+ SHA512:
6
+ metadata.gz: 3256fb050c2c3e4162ecd4d6eabe69dec4f6731d338cd0746dcc3120bc3c197088e40fdc923ad38d4244ec59d910a0dffa569aad166956bc323a45c4c93adfdb
7
+ data.tar.gz: d9b1b88b614d46a12da2403a7a658693940cb85697bcf5ad6ac17ff80c07bc4a75f8d4797bf3582badb902f5b392005adab558c17683ce020a092ce0d8a517b7
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2014 Code and Effect Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,195 @@
1
+ # Effective Email Templates
2
+
3
+ Description!!
4
+
5
+ Rails 3.2.x and Rails 4 Support
6
+
7
+ ## Getting Started
8
+
9
+ Add to your Gemfile:
10
+
11
+ ```ruby
12
+ gem 'effective_email_templates', :git => 'https://github.com/code-and-effect/effective_email_templates'
13
+ ```
14
+
15
+ Run the bundle command to install it:
16
+
17
+ ```console
18
+ bundle install
19
+ ```
20
+
21
+ Then run the generator:
22
+
23
+ ```ruby
24
+ rails generate effective_email_templates:install
25
+ ```
26
+
27
+ The generator will install an initializer which describes all configuration options and creates a database migration.
28
+
29
+ If you want to tweak the table name (to use something other than the default 'email_templates'), manually adjust both the configuration file and the migration now.
30
+
31
+ Then migrate the database:
32
+
33
+ ```ruby
34
+ rake db:migrate
35
+ ```
36
+
37
+
38
+ ## Usage
39
+
40
+ - Create some email templates at `/admin/email_templates`
41
+ - Create a mailer method for each email
42
+ - Mailer objects need to inherit from `Effective::LiquidMailer`
43
+ - Mailer methods and email template slugs need to match up
44
+ - Email headers can be declared in the #mail method but can be overrided by the saved attributes on the Effective::EmailTemplate model.
45
+ - Create mail objects and deliver them like normal
46
+
47
+ An example liquid template (put these into the database through the admin panel: `/admin/email_templates`):
48
+
49
+ ```liquid
50
+ Welcome to our site. We think you're {{ adjective }}
51
+ ```
52
+
53
+ The corresponding Mailer:
54
+
55
+ ```ruby
56
+ # app/mailers/user_liquid_mailer.rb
57
+ class UserLiquidMailer < Effective::LiquidMailer
58
+ def after_create_user(user)
59
+ @to_liquid = {
60
+ 'adjective' => 'awesome'
61
+ }
62
+ mail(to: user.email)
63
+ end
64
+ end
65
+ ```
66
+
67
+ Send the emails like normal:
68
+
69
+ ```ruby
70
+ mail = UserLiquidMailer.after_create_user(self)
71
+ mail.deliver
72
+ ```
73
+
74
+ ### Default Templates
75
+
76
+ Email templates can still be added by a developer into a view file if a rake task is run to import
77
+ them into the database in production. To create a view template for the `after_create_user` email
78
+ above, simply create a template file inside /app/views (probably in the user_liquid directory)
79
+ with a .liquid file extension. That file should contain metadata in YAML format at the top
80
+ surrounded by two lines with three hyphens:
81
+
82
+ ```yaml
83
+ ---
84
+ subject: 'Hello User' # REQUIRED
85
+ from: 'effective@email_templates.com' # REQUIRED
86
+ cc: 'my_friend@email_templates.com' # optional
87
+ bcc: 'my_secret_friend@example.com' # optional
88
+ ---
89
+ Hello new user! I'm a liquid template and you can use {{ }} inside of me to interpolate variables
90
+ defined in the corresponding LiquidMailer method.
91
+ ```
92
+
93
+ To add these templates to the database, run the `effective_email_templates:import_default_views` task.
94
+ This task can be run even when no new templates have been added and will not overwrite existing
95
+ database templates. This allows you to run the rake task in a deploy script:
96
+
97
+ ```ruby
98
+ # an example Heroku deploy script
99
+ ...
100
+ system 'heroku run rake effective_email_templates:import_default_views'
101
+ ...
102
+ ```
103
+
104
+ ## Authorization
105
+
106
+ All authorization checks are handled via the config.authorization_method found in the config/initializers/ file.
107
+
108
+ It is intended for flow through to CanCan or Pundit, but that is not required.
109
+
110
+ This method is called by all controller actions with the appropriate action and resource
111
+
112
+ Action will be one of [:index, :show, :new, :create, :edit, :update, :destroy]
113
+
114
+ Resource will the appropriate Effective::Something ActiveRecord object or class
115
+
116
+ The authorization method is defined in the initializer file:
117
+
118
+ ```ruby
119
+ # As a Proc (with CanCan)
120
+ config.authorization_method = Proc.new { |controller, action, resource| authorize!(action, resource) }
121
+ ```
122
+
123
+ ```ruby
124
+ # As a Custom Method
125
+ config.authorization_method = :my_authorization_method
126
+ ```
127
+
128
+ and then in your application_controller.rb:
129
+
130
+ ```ruby
131
+ def my_authorization_method(action, resource)
132
+ current_user.is?(:admin) || EffectivePunditPolicy.new(current_user, resource).send('#{action}?')
133
+ end
134
+ ```
135
+
136
+ or disabled entirely:
137
+
138
+ ```ruby
139
+ config.authorization_method = false
140
+ ```
141
+
142
+ If the method or proc returns false (user is not authorized) an Effective::AccessDenied exception will be raised
143
+
144
+ You can rescue from this exception by adding the following to your application_controller.rb:
145
+
146
+ ```ruby
147
+ rescue_from Effective::AccessDenied do |exception|
148
+ respond_to do |format|
149
+ format.html { render 'static_pages/access_denied', :status => 403 }
150
+ format.any { render :text => 'Access Denied', :status => 403 }
151
+ end
152
+ end
153
+ ```
154
+
155
+
156
+ ## License
157
+
158
+ MIT License. Copyright Code and Effect Inc. http://www.codeandeffect.com
159
+
160
+ You are not granted rights or licenses to the trademarks of Code and Effect
161
+
162
+ ## TODO
163
+
164
+ - minimize gem dependencies
165
+ - remove unused non-admin routes and config option
166
+ - Add an admin alert if there are mailer methods that do not have associated email templates
167
+ - Show admin what the available arguments are for each template
168
+ - remove `caller` usage from Effective::LiquidMailer (or remove requirement for Ruby 2.0+)
169
+ - add `EffectiveEmailTemplates::present?` to check if a template model is present
170
+ - notify the app but don't raise an error if template is not present when an email is sent
171
+ - configurable default from address
172
+ - configurable prefix for subject line
173
+ - use autoload rather than require
174
+ - research panoramic gem's usage of the Resolver class and improve our Resolver usage
175
+ - enable multipart emails
176
+ - enable file attachments
177
+ - import factories/fixtures in install task
178
+
179
+ ## Testing
180
+
181
+
182
+
183
+
184
+
185
+
186
+
187
+
188
+
189
+
190
+
191
+
192
+
193
+
194
+
195
+
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+
8
+ # Our tasks
9
+ load 'lib/tasks/effective_email_templates/import_default_views.rake'
10
+
11
+ # Testing tasks
12
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
13
+ load 'rails/tasks/engine.rake'
14
+
15
+ Bundler::GemHelper.install_tasks
16
+
17
+ require 'rspec/core'
18
+ require 'rspec/core/rake_task'
19
+
20
+ desc "Run all specs in spec directory (excluding plugin specs)"
21
+ RSpec::Core::RakeTask.new(:spec => 'app:db:test:prepare')
22
+
23
+ task :default => :spec
@@ -0,0 +1 @@
1
+ //= require_tree ./effective_email_templates
@@ -0,0 +1,63 @@
1
+ module Admin
2
+ class EmailTemplatesController < ApplicationController
3
+ before_filter :authenticate_user! # This is devise, ensure we're logged in.
4
+
5
+ layout (EffectiveEmailTemplates.layout.kind_of?(Hash) ? EffectiveEmailTemplates.layout[:admin_email_templates] : EffectiveEmailTemplates.layout)
6
+
7
+ def index
8
+ EffectiveEmailTemplates.authorized?(self, :index, Effective::EmailTemplate)
9
+
10
+ @page_title = 'Manage Email Templates'
11
+ @datatable = Effective::Datatables::EmailTemplates.new() if defined?(EffectiveDatatables)
12
+ @page_title = 'Email Templates'
13
+ end
14
+
15
+ def new
16
+ @email_template = Effective::EmailTemplate.new
17
+ EffectiveEmailTemplates.authorized?(self, :new, @email_template)
18
+
19
+ @page_title = 'New Email Template'
20
+ end
21
+
22
+ def create
23
+ @email_template = Effective::EmailTemplate.new(email_template_params)
24
+ EffectiveEmailTemplates.authorized?(self, :create, @email_template)
25
+
26
+ if @email_template.save
27
+ flash[:success] = "Email template created successfully"
28
+ redirect_to effective_email_templates.admin_email_templates_path
29
+ else
30
+ flash.now[:error] = "Could not create email template"
31
+ @page_title = 'New Email Template'
32
+ render :new
33
+ end
34
+ end
35
+
36
+ def edit
37
+ @email_template = Effective::EmailTemplate.find(params[:id])
38
+ EffectiveEmailTemplates.authorized?(self, :edit, @email_template)
39
+
40
+ @page_title = 'Edit Email Template'
41
+ end
42
+
43
+ def update
44
+ @email_template = Effective::EmailTemplate.find(params[:id])
45
+ EffectiveEmailTemplates.authorized?(self, :update, @email_template)
46
+
47
+ if @email_template.update(email_template_params)
48
+ flash[:success] = "Email template updated successfully"
49
+ redirect_to effective_email_templates.admin_email_templates_path
50
+ else
51
+ flash.now[:error] = "Could not update email template"
52
+ @page_title = 'Edit Email Template'
53
+ render :edit
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ def email_template_params
60
+ params.require(:effective_email_template).permit([ :from, :cc, :bcc, :subject, :body ])
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,18 @@
1
+ unless defined?(Effective::AccessDenied)
2
+ module Effective
3
+ class AccessDenied < StandardError
4
+ attr_reader :action, :subject
5
+
6
+ def initialize(message = nil, action = nil, subject = nil)
7
+ @message = message
8
+ @action = action
9
+ @subject = subject
10
+ end
11
+
12
+ def to_s
13
+ @message || I18n.t(:'unauthorized.default', :default => 'Access Denied')
14
+ end
15
+ end
16
+ end
17
+ end
18
+
@@ -0,0 +1,19 @@
1
+ module EffectiveEmailTemplatesHelper
2
+ def datatable_of(description_of_objects, datatable)
3
+ if datatable.nil?
4
+ content_tag(:p, "Please use Effective Datatables gem")
5
+ elsif datatable.collection.length > 0
6
+ render_datatable(datatable)
7
+ else
8
+ content_tag(:p, "There are no email templates")
9
+ end
10
+ end
11
+
12
+ def email_template_form_url( email_template )
13
+ if email_template.new_record?
14
+ effective_email_templates.admin_email_templates_path
15
+ else
16
+ effective_email_templates.admin_email_template_path( email_template )
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,14 @@
1
+ module Effective
2
+ class EmailTemplateMailer < ActionMailer::Base
3
+ def templated_email(address, body, email_template, options)
4
+ @body = body
5
+ mail(
6
+ to: address,
7
+ from: email_template.from,
8
+ subject: email_template.subject,
9
+ cc: options.fetch(:cc, false),
10
+ bcc: options.fetch(:bcc, false),
11
+ )
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,22 @@
1
+ if defined?(EffectiveDatatables)
2
+ module Effective
3
+ module Datatables
4
+ class EmailTemplates < Effective::Datatable
5
+ default_order :subject, :asc
6
+
7
+ table_column :id, visible: false
8
+ table_column :slug
9
+ table_column :subject
10
+ table_column :from
11
+ table_column :cc, sortable: false, visible: false, label: 'CC'
12
+ table_column :bcc, sortable: false, visible: false, label: 'BCC'
13
+ table_column :body, sortable: false, visible: false
14
+ table_column :actions, sortable: false, partial: '/admin/email_templates/actions'
15
+
16
+ def collection
17
+ Effective::EmailTemplate.all
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,55 @@
1
+ require 'liquid'
2
+ Liquid::Template.error_mode = :strict # Raises a SyntaxError when invalid syntax is used
3
+
4
+ module Effective
5
+ class EmailTemplate < ActiveRecord::Base
6
+
7
+ self.table_name = EffectiveEmailTemplates.email_templates_table_name.to_s
8
+
9
+ serialize :template, Liquid::Template
10
+
11
+ validate :slug_needs_to_have_simple_format
12
+ validates :slug, presence: true, uniqueness: true
13
+ validates :body, presence: true
14
+ validates :subject, presence: true
15
+ validates :from, presence: true
16
+ validates :template, presence: true
17
+
18
+ before_validation :try_precompile
19
+
20
+ def precompile
21
+ begin
22
+ self.template = Liquid::Template.parse( body )
23
+ rescue Liquid::SyntaxError => error
24
+ errors.add :template, error.message
25
+ end
26
+ end
27
+
28
+ def mail_options
29
+ {
30
+ from: from,
31
+ subject: subject,
32
+ cc: cc,
33
+ bcc: bcc
34
+ }.delete_if { |_, v| v.blank? }
35
+ end
36
+
37
+ def render( *args )
38
+ template.render( *args )
39
+ end
40
+
41
+ private
42
+
43
+ def try_precompile
44
+ precompile if body_changed?
45
+ end
46
+
47
+ def slug_needs_to_have_simple_format
48
+ # convert slug to symbol
49
+ # add error if symbol has non-simple format (i.e. `:"symbol with spaces"` vs `:symbol_with_underscores`)
50
+ if /[@$"]/ =~ slug.to_sym.inspect || slug.match(/[A-Z]/)
51
+ errors.add(:slug, 'must have a simple format with no spaces, capital letters, and most punctuation (good: "hello_world", bad: "hello, world")')
52
+ end
53
+ end
54
+ end
55
+ end