Skip to content
This repository
Browse code

[padrino-mailer] Major mailer refactoring and syntax changes; closes …

…issue #127
  • Loading branch information...
commit db429172c3609b47d710fc4da278c2b0bb7c886b 1 parent 8f739b6
Nathan Esquenazi authored

Showing 61 changed files with 1,302 additions and 729 deletions. Show diff stats Hide diff stats

  1. 2  padrino-admin/README.rdoc
  2. 5  padrino-admin/lib/padrino-admin.rb
  3. 13  padrino-admin/lib/padrino-admin/access_control.rb
  4. 47  padrino-admin/lib/padrino-admin/generators/templates/app/app.rb
  5. 4  padrino-admin/test/helper.rb
  6. 10  padrino-admin/test/test_admin_application.rb
  7. 14  padrino-core/lib/padrino-core/application.rb
  8. 19  padrino-core/lib/padrino-core/application/rendering.rb
  9. 20  padrino-core/lib/padrino-core/application/routing.rb
  10. 1  padrino-core/lib/padrino-core/support_lite.rb
  11. 2  padrino-core/test/fixtures/apps/complex.rb
  12. 2  padrino-core/test/fixtures/apps/simple.rb
  13. 2  padrino-core/test/test_application.rb
  14. 32  padrino-gen/lib/padrino-gen/generators/app/app.rb.tt
  15. 4  padrino-gen/lib/padrino-gen/generators/components/stylesheets/less.rb
  16. 4  padrino-gen/lib/padrino-gen/generators/components/stylesheets/sass.rb
  17. 10  padrino-gen/lib/padrino-gen/generators/mailer.rb
  18. 48  padrino-gen/lib/padrino-gen/generators/project/config/apps.rb.tt
  19. 53  padrino-gen/lib/padrino-gen/generators/templates/mailer.rb.tt
  20. 19  padrino-gen/lib/padrino-gen/generators/templates/mailer_initializer.rb.tt
  21. 10  padrino-gen/test/test_app_generator.rb
  22. 23  padrino-gen/test/test_mailer_generator.rb
  23. 1  padrino-helpers/test/fixtures/render_app/app.rb
  24. 105  padrino-mailer/README.rdoc
  25. 20  padrino-mailer/lib/padrino-mailer.rb
  26. 134  padrino-mailer/lib/padrino-mailer/base.rb
  27. 77  padrino-mailer/lib/padrino-mailer/delivery.rb
  28. 202  padrino-mailer/lib/padrino-mailer/ext.rb
  29. 123  padrino-mailer/lib/padrino-mailer/helpers.rb
  30. 65  padrino-mailer/lib/padrino-mailer/mail_object.rb
  31. 42  padrino-mailer/lib/padrino-mailer/mime.rb
  32. 4  padrino-mailer/padrino-mailer.gemspec
  33. 1  padrino-mailer/test/fixtures/basic.erb
  34. 1  padrino-mailer/test/fixtures/layout.erb
  35. 69  padrino-mailer/test/fixtures/mailer_app/app.rb
  36. 66  padrino-mailer/test/fixtures/padrino_app/app.rb
  37. 0  ...o-mailer/test/fixtures/{mailer_app/views/demo_mailer → padrino_app/views/mailers/demo}/sample_mail.erb
  38. 0  ...er_app/views/sample_mailer/anniversary_message.erb → padrino_app/views/mailers/sample/anniversary.erb}
  39. 0  .../{mailer_app/views/sample_mailer/birthday_message.erb → padrino_app/views/mailers/sample/birthday.erb}
  40. 0  ...iler/test/fixtures/{mailer_app/views/sample_mailer → padrino_app/views/mailers/sample}/foo_message.erb
  41. 64  padrino-mailer/test/fixtures/sinatra_app/app.rb
  42. 1  padrino-mailer/test/fixtures/sinatra_app/views/mailers/demo/sample_mail.erb
  43. 2  padrino-mailer/test/fixtures/sinatra_app/views/mailers/sample/anniversary.erb
  44. 2  padrino-mailer/test/fixtures/sinatra_app/views/mailers/sample/birthday.erb
  45. 1  padrino-mailer/test/fixtures/sinatra_app/views/mailers/sample/foo_message.erb
  46. 1  padrino-mailer/test/fixtures/views/mailers/alternate/foo.erb
  47. 1  padrino-mailer/test/fixtures/views/mailers/bar.erb
  48. 1  padrino-mailer/test/fixtures/views/mailers/i18n/hello.en.erb
  49. 1  padrino-mailer/test/fixtures/views/mailers/i18n/hello.it.erb
  50. 1  padrino-mailer/test/fixtures/views/mailers/layouts/sample.erb
  51. 1  padrino-mailer/test/fixtures/views/mailers/multipart/basic.html.erb
  52. 1  padrino-mailer/test/fixtures/views/mailers/multipart/basic.plain.erb
  53. 1  padrino-mailer/test/fixtures/views/mailers/sample/foo.erb
  54. 68  padrino-mailer/test/helper.rb
  55. 86  padrino-mailer/test/test_base.rb
  56. 21  padrino-mailer/test/test_delivery.rb
  57. 157  padrino-mailer/test/test_email.rb
  58. 25  padrino-mailer/test/test_mail_object.rb
  59. 138  padrino-mailer/test/test_message.rb
  60. 85  padrino-mailer/test/test_padrino_mailer.rb
  61. 119  padrino-mailer/test/test_part.rb
2  padrino-admin/README.rdoc
Source Rendered
@@ -49,7 +49,7 @@ For an ecommerce website, usually certain actions require permissions and authen
49 49
 by the admin access control features:
50 50
 
51 51
   class EcommerceSite < Padrino::Application
52  
-    enable :authentication
  52
+    register Padrino::Admin::AccessControl
53 53
     enable :store_location
54 54
     set    :login_page, "/login"
55 55
 
5  padrino-admin/lib/padrino-admin.rb
@@ -23,11 +23,6 @@ module Admin; end
23 23
 String.send(:include, Padrino::Admin::Utils::Crypt)
24 24
 
25 25
 ##
26  
-# We need to add to Padrino::Application a +access_control+ class
27  
-#
28  
-Padrino::Application.extend(Padrino::Admin::AccessControl::ClassMethods)
29  
-
30  
-##
31 26
 # Load our Padrino::Admin locales
32 27
 #
33 28
 I18n.load_path += Dir["#{File.dirname(__FILE__)}/padrino-admin/locale/**/*.yml"]
13  padrino-admin/lib/padrino-admin/access_control.rb
@@ -15,18 +15,13 @@ def self.registered(app)
15 15
         app.helpers Padrino::Admin::Helpers::AuthenticationHelpers
16 16
         app.helpers Padrino::Admin::Helpers::ViewHelpers
17 17
         app.before { login_required }
  18
+        app.extend(ClassMethods)
  19
+        app.send(:cattr_accessor, :access_control)
  20
+        app.send(:access_control=, Padrino::Admin::AccessControl::Base.new)
  21
+        app.class_eval { class << self; alias_method_chain :reload!, :access_control; end }
18 22
       end
19 23
 
20 24
       module ClassMethods #:nodoc:
21  
-        def inherited(base)
22  
-          unless base.respond_to?(:access_control)
23  
-            base.send(:cattr_accessor, :access_control)
24  
-            base.send(:access_control=, Padrino::Admin::AccessControl::Base.new)
25  
-          end
26  
-          super(base)
27  
-          base.class_eval { class << self; alias_method_chain :reload!, :access_control; end }
28  
-        end
29  
-
30 25
         def reload_with_access_control!
31 26
           self.access_control = Padrino::Admin::AccessControl::Base.new
32 27
           reload_without_access_control!
47  padrino-admin/lib/padrino-admin/generators/templates/app/app.rb
... ...
@@ -1,31 +1,28 @@
1 1
 class Admin < Padrino::Application
2  
-  configure do
3  
-    ##
4  
-    # Application-specific configuration options
5  
-    #
6  
-    # set :raise_errors, true     # Show exceptions (default for development)
7  
-    # set :public, "foo/bar"      # Location for static assets (default root/public)
8  
-    # set :reload, false          # Reload application files (default in development)
9  
-    # set :default_builder, "foo" # Set a custom form builder (default 'StandardFormBuilder')
10  
-    # set :locale_path, "bar"     # Set path for I18n translations (default your_app/locales)
11  
-    # enable  :sessions           # Disabled by default
12  
-    # disable :flash              # Disables rack-flash (enabled by default if sessions)
13  
-    # disable :padrino_helpers    # Disables padrino markup helpers (enabled by default if present)
14  
-    # disable :padrino_mailer     # Disables padrino mailer (enabled by default if present)
15  
-    # enable  :authentication     # Enable padrino-admin authentication (disabled by default)
16  
-    # layout  :my_layout          # Layout can be in views/layouts/foo.ext or views/foo.ext (default :application)
17  
-    #
18  
-    enable  :authentication
19  
-    disable :store_location
20  
-    set :login_page, "/admin/sessions/new"
  2
+  ##
  3
+  # Application configuration options
  4
+  #
  5
+  # set :raise_errors, true     # Show exceptions (default for development)
  6
+  # set :public, "foo/bar"      # Location for static assets (default root/public)
  7
+  # set :reload, false          # Reload application files (default in development)
  8
+  # set :default_builder, "foo" # Set a custom form builder (default 'StandardFormBuilder')
  9
+  # set :locale_path, "bar"     # Set path for I18n translations (default your_app/locales)
  10
+  # enable  :sessions           # Disabled by default
  11
+  # disable :flash              # Disables rack-flash (enabled by default if sessions)
  12
+  # layout  :my_layout          # Layout can be in views/layouts/foo.ext or views/foo.ext (default :application)
  13
+  #
  14
+  register Padrino::Mailer
  15
+  register Padrino::Helpers
  16
+  register Padrino::Admin::AccessControl
21 17
 
22  
-    access_control.roles_for :any do |role|
23  
-      role.protect "/"
24  
-      role.allow "/sessions"
25  
-    end
  18
+  set :login_page, "/admin/sessions/new"
  19
+  disable :store_location
26 20
 
27  
-    access_control.roles_for :admin do |role|
28  
-    end
  21
+  access_control.roles_for :any do |role|
  22
+    role.protect "/"
  23
+    role.allow "/sessions"
  24
+  end
29 25
 
  26
+  access_control.roles_for :admin do |role|
30 27
   end
31 28
 end
4  padrino-admin/test/helper.rb
@@ -54,13 +54,13 @@ class Test::Unit::TestCase
54 54
   def mock_app(base=Padrino::Application, &block)
55 55
     @app = Sinatra.new(base, &block)
56 56
     @app.send :include, Test::Unit::Assertions
57  
-    @app.use Rack::Session::Cookie if Sinatra::VERSION =~ /0\.9\.\d+/ # Need this because Sinatra 0.9.x have use Rack::Session::Cookie if sessions? && !test?
  57
+    @app.register Padrino::Helpers
58 58
   end
59 59
 
60 60
   def app
61 61
     Rack::Lint.new(@app)
62 62
   end
63  
-  
  63
+
64 64
   # generate(:admin_app, '-r=/tmp/sample_project')
65 65
   def generate(name, *params)
66 66
     "Padrino::Generators::#{name.to_s.camelize}".constantize.start(params)
10  padrino-admin/test/test_admin_application.rb
@@ -8,7 +8,7 @@ def setup
8 8
 
9 9
   should 'require correctly login' do
10 10
     mock_app do
11  
-      enable :authentication
  11
+      register Padrino::Admin::AccessControl
12 12
 
13 13
       # Do a simple mapping
14 14
       access_control.roles_for :any do |role|
@@ -35,7 +35,7 @@ def setup
35 35
   should 'set basic roles with store location and login page' do
36 36
     mock_app do
37 37
       set    :app_name, :basic_app
38  
-      enable :authentication
  38
+      register Padrino::Admin::AccessControl
39 39
       enable :store_location
40 40
       set    :login_page, "/login"
41 41
 
@@ -69,7 +69,7 @@ def setup
69 69
 
70 70
   should 'set advanced roles with store location and login page' do
71 71
     mock_app do
72  
-      enable :authentication
  72
+      register Padrino::Admin::AccessControl
73 73
 
74 74
       access_control.roles_for :any do |role|
75 75
         role.protect "/"
@@ -145,7 +145,7 @@ def setup
145 145
 
146 146
   should 'emulate an ecommerce app' do
147 147
     mock_app do
148  
-      enable :authentication
  148
+      register Padrino::Admin::AccessControl
149 149
 
150 150
       access_control.roles_for :any do |role|
151 151
         role.protect "/cart"
@@ -195,7 +195,7 @@ def setup
195 195
 
196 196
   should 'check access control helper' do
197 197
     mock_app do
198  
-      enable :authentication
  198
+      register Padrino::Admin::AccessControl
199 199
 
200 200
       access_control.roles_for :any do |role|
201 201
         role.project_module :foo, "/foo"
14  padrino-core/lib/padrino-core/application.rb
@@ -46,7 +46,6 @@ def reload!
46 46
         reset! # reset sinatra app
47 47
         reset_routes! # remove all existing user-defined application routes
48 48
         Padrino.load_dependency(self.app_file)  # reload the app file
49  
-        register_framework_extensions # reload our extensions
50 49
         register_initializers # reload our middlewares
51 50
         load_paths.each { |path| Padrino.load_dependencies(File.join(self.root, path)) } # reload dependencies
52 51
         default_filters! # reload filters
@@ -72,7 +71,6 @@ def reset_routes!
72 71
       def setup_application!
73 72
         return if @_configured
74 73
         self.calculate_paths
75  
-        self.register_framework_extensions
76 74
         self.register_initializers
77 75
         self.require_load_paths
78 76
         self.disable :logging # We need do that as default because Sinatra use commonlogger.
@@ -108,9 +106,6 @@ def default_configuration!
108 106
           set :authentication, false
109 107
           # Padrino locale
110 108
           set :locale_path, Proc.new { Dir[File.join(self.root, "/locale/**/*.{rb,yml}")] }
111  
-          # Plugin specific
112  
-          set :padrino_mailer, defined?(Padrino::Mailer)
113  
-          set :padrino_helpers, defined?(Padrino::Helpers)
114 109
         end
115 110
 
116 111
         ##
@@ -170,15 +165,6 @@ def register_initializers
170 165
         end
171 166
 
172 167
         ##
173  
-        # Registers all desired padrino extension helpers
174  
-        #
175  
-        def register_framework_extensions
176  
-          register Padrino::Mailer  if padrino_mailer?
177  
-          register Padrino::Helpers if padrino_helpers?
178  
-          register Padrino::Admin::AccessControl if authentication?
179  
-        end
180  
-
181  
-        ##
182 168
         # Returns the load_paths for the application (relative to the application root)
183 169
         #
184 170
         def load_paths
19  padrino-core/lib/padrino-core/application/rendering.rb
@@ -101,7 +101,7 @@ def render(engine, data=nil, options={}, locals={}, &block)
101 101
         options[:outvar] ||= '@_out_buf' if [:erb, :erubis] & [engine]
102 102
 
103 103
         # Resolve layouts similar to in Rails
104  
-        if (options[:layout].nil? || options[:layout] == true) && !self.class.templates.has_key?(:layout)
  104
+        if (options[:layout].nil? || options[:layout] == true) && !settings.templates.has_key?(:layout)
105 105
           options[:layout] = resolved_layout || false # We need to force layout false so sinatra don't try to render it
106 106
           logger.debug "Resolving layout #{options[:layout]}" if defined?(logger) && options[:layout].present?
107 107
         end
@@ -119,7 +119,7 @@ def render(engine, data=nil, options={}, locals={}, &block)
119 119
       # => "/layouts/custom"
120 120
       #
121 121
       def resolved_layout
122  
-        located_layout = resolve_template(self.class.fetch_layout_path, :strict_format => true, :raise_exceptions => false)
  122
+        located_layout = resolve_template(settings.fetch_layout_path, :strict_format => true, :raise_exceptions => false)
123 123
         located_layout ? located_layout[0] : false
124 124
       end
125 125
 
@@ -141,12 +141,12 @@ def resolve_template(template_path, options={})
141 141
         # Fetch cached template for rendering options
142 142
         template_path = "/#{template_path}" unless template_path.to_s[0] == ?/
143 143
         rendering_options = [template_path, content_type, locale]
144  
-        cached_template = self.class.fetch_template_file(rendering_options)
  144
+        cached_template = settings.fetch_template_file(rendering_options)
145 145
         return cached_template if cached_template
146 146
 
147 147
         # Resolve view path and options
148 148
         options.reverse_merge!(DEFAULT_RENDERING_OPTIONS)
149  
-        view_path = options.delete(:views) || self.options.views || self.class.views || "./views"
  149
+        view_path = options.delete(:views) || settings.views || settings.views || "./views"
150 150
         target_extension = File.extname(template_path)[1..-1] || "none" # retrieves explicit template extension
151 151
         template_path = template_path.chomp(".#{target_extension}")
152 152
 
@@ -157,17 +157,20 @@ def resolve_template(template_path, options={})
157 157
           [template_file, template_engine] unless IGNORE_FILE_PATTERN.any? { |pattern| template_engine.to_s =~ pattern }
158 158
         end
159 159
 
  160
+        # Check if we have a valid content type
  161
+        valid_content_type = [:html, :plain].include?(content_type)
  162
+
160 163
         # Resolve final template to render
161 164
         located_template =
162 165
           templates.find { |file, e| file.to_s == "#{template_path}.#{locale}.#{content_type}" } ||
163  
-          templates.find { |file, e| file.to_s == "#{template_path}.#{locale}" && content_type == :html } ||
  166
+          templates.find { |file, e| file.to_s == "#{template_path}.#{locale}" && valid_content_type } ||
164 167
           templates.find { |file, e| File.extname(file.to_s) == ".#{target_extension}" or e.to_s == target_extension.to_s } ||
165 168
           templates.find { |file, e| file.to_s == "#{template_path}.#{content_type}" } ||
166  
-          templates.find { |file, e| file.to_s == "#{template_path}" && content_type == :html } ||
  169
+          templates.find { |file, e| file.to_s == "#{template_path}" && valid_content_type } ||
167 170
           templates.any? && !options[:strict_format] && templates.first # If not strict, fall back to the first located template
168 171
 
169  
-        self.class.cache_template_file!(located_template, rendering_options) unless settings.reload_templates?
170  
-        raise TemplateNotFound.new("Template path '#{template_path}' could not be located!") if !located_template && options[:raise_exceptions]
  172
+        settings.cache_template_file!(located_template, rendering_options) unless settings.reload_templates?
  173
+        raise TemplateNotFound, "Template path '#{template_path}' could not be located in '#{view_path}'!" if !located_template && options[:raise_exceptions]
171 174
         located_template
172 175
       end
173 176
 
20  padrino-core/lib/padrino-core/application/routing.rb
@@ -54,6 +54,16 @@ def static_file?(path_info)
54 54
     end
55 55
 
56 56
     ##
  57
+    # Method for deliver static files.
  58
+    #
  59
+    def static!
  60
+      if path = static_file?(request.path_info)
  61
+        env['sinatra.static_file'] = path
  62
+        send_file(path, :disposition => nil)
  63
+      end
  64
+    end
  65
+
  66
+    ##
57 67
     # Return the request format, this is useful when we need to respond to a given content_type like:
58 68
     #
59 69
     # ==== Examples
@@ -70,16 +80,6 @@ def content_type(type=nil, params={})
70 80
       type.nil? ? @_content_type : super(type, params)
71 81
     end
72 82
 
73  
-    ##
74  
-    # Method for deliver static files.
75  
-    #
76  
-    def static!
77  
-      if path = static_file?(request.path_info)
78  
-        env['sinatra.static_file'] = path
79  
-        send_file(path, :disposition => nil)
80  
-      end
81  
-    end
82  
-
83 83
     private
84 84
       ##
85 85
       # Compatibility with usher
1  padrino-core/lib/padrino-core/support_lite.rb
@@ -20,7 +20,6 @@
20 20
 #   * Hash#symbolize_keys, Hash.symbolize_keys!
21 21
 #   * Hash#reverse_merge, Hash#reverse_merge!
22 22
 #   * Symbol#to_proc
23  
-#   * SupportLite::OrderedHash
24 23
 #
25 24
 require 'rbconfig'
26 25
 require 'active_support/version'
2  padrino-core/test/fixtures/apps/complex.rb
@@ -21,7 +21,7 @@ class Complex2Demo < Padrino::Application
21 21
 end
22 22
 
23 23
 Complex2Demo.controllers do
24  
-  get("(/)"){ "The magick number is: 33!" } # Change only the number!!!
  24
+  get("(/)"){ "The magick number is: 20!" } # Change only the number!!!
25 25
 end
26 26
 
27 27
 Padrino.load!
2  padrino-core/test/fixtures/apps/simple.rb
@@ -14,7 +14,7 @@ class SimpleDemo < Padrino::Application
14 14
 
15 15
 SimpleDemo.controllers do
16 16
   get "/" do
17  
-    'The magick number is: 28!' # Change only the number!!!
  17
+    'The magick number is: 39!' # Change only the number!!!
18 18
   end
19 19
 
20 20
   get "/rand" do
2  padrino-core/test/test_application.rb
@@ -27,8 +27,6 @@ class PadrinoTestApp < Padrino::Application; end
27 27
       assert 'padrino_test_app', PadrinoTestApp.app_name
28 28
       assert 'StandardFormBuilder', PadrinoTestApp.default_builder
29 29
       assert !PadrinoTestApp.flash
30  
-      assert !PadrinoTestApp.padrino_mailer
31  
-      assert !PadrinoTestApp.padrino_helpers
32 30
     end
33 31
 
34 32
     #compare to: test_routing: allow global provides
32  padrino-gen/lib/padrino-gen/generators/app/app.rb.tt
... ...
@@ -1,21 +1,18 @@
1 1
 class <%= @class_name %> < Padrino::Application
2  
-  configure do
3  
-    ##
4  
-    # Application-specific configuration options
5  
-    #
6  
-    # set :raise_errors, true     # Show exceptions (default for development)
7  
-    # set :public, "foo/bar"      # Location for static assets (default root/public)
8  
-    # set :reload, false          # Reload application files (default in development)
9  
-    # set :default_builder, "foo" # Set a custom form builder (default 'StandardFormBuilder')
10  
-    # set :locale_path, "bar"     # Set path for I18n translations (default your_app/locales)
11  
-    # enable  :sessions           # Disabled by default
12  
-    # disable :flash              # Disables rack-flash (enabled by default if sessions)
13  
-    # disable :padrino_helpers    # Disables padrino markup helpers (enabled by default if present)
14  
-    # disable :padrino_mailer     # Disables padrino mailer (enabled by default if present)
15  
-    # enable  :authentication     # Enable padrino-admin authentication (disabled by default)
16  
-    # layout  :my_layout          # Layout can be in views/layouts/foo.ext or views/foo.ext (default :application)
17  
-    #
18  
-  end
  2
+  ##
  3
+  # Application configuration options
  4
+  #
  5
+  # set :raise_errors, true     # Show exceptions (default for development)
  6
+  # set :public, "foo/bar"      # Location for static assets (default root/public)
  7
+  # set :reload, false          # Reload application files (default in development)
  8
+  # set :default_builder, "foo" # Set a custom form builder (default 'StandardFormBuilder')
  9
+  # set :locale_path, "bar"     # Set path for I18n translations (default your_app/locales)
  10
+  # enable  :sessions           # Disabled by default
  11
+  # disable :flash              # Disables rack-flash (enabled by default if sessions)
  12
+  # layout  :my_layout          # Layout can be in views/layouts/foo.ext or views/foo.ext (default :application)
  13
+  #
  14
+  register Padrino::Mailer
  15
+  register Padrino::Helpers
19 16
 
20 17
   ##
21 18
   # You can configure for a specified environment like:
@@ -32,5 +29,4 @@ class <%= @class_name %> < Padrino::Application
32 29
   #     render 'errors/404'
33 30
   #   end
34 31
   #
35  
-
36 32
 end
4  padrino-gen/lib/padrino-gen/generators/components/stylesheets/less.rb
@@ -22,12 +22,12 @@ def self.registered(app)
22 22
 LESS
23 23
 
24 24
 LESS_REGISTER = (<<-LESSR).gsub(/^ {10}/, '') unless defined?(LESS_REGISTER)
25  
-    register LessInitializer\n
  25
+  register LessInitializer\n
26 26
 LESSR
27 27
 
28 28
 def setup_stylesheet
29 29
   require_dependencies 'less', 'rack-less'
30 30
   create_file destination_root('/lib/less_plugin.rb'), LESS_INIT
31  
-  inject_into_file destination_root('/app/app.rb'), LESS_REGISTER, :after => "configure do\n"
  31
+  inject_into_file destination_root('/app/app.rb'), LESS_REGISTER, :after => "register Padrino::Helpers\n"
32 32
   empty_directory destination_root('/app/stylesheets')
33 33
 end
4  padrino-gen/lib/padrino-gen/generators/components/stylesheets/sass.rb
@@ -14,12 +14,12 @@ def self.registered(app)
14 14
 SASS
15 15
 
16 16
 SASS_REGISTER = (<<-SASSR).gsub(/^ {10}/, '') unless defined?(SASS_REGISTER)
17  
-    register SassInitializer\n
  17
+  register SassInitializer\n
18 18
 SASSR
19 19
 
20 20
 def setup_stylesheet
21 21
   require_dependencies 'haml'
22 22
   create_file destination_root('/lib/sass_plugin.rb'), SASS_INIT
23  
-  inject_into_file destination_root('/app/app.rb'), SASS_REGISTER, :after => "configure do\n"
  23
+  inject_into_file destination_root('/app/app.rb'), SASS_REGISTER, :after => "register Padrino::Helpers\n"
24 24
   empty_directory destination_root('/app/stylesheets')
25 25
 end
10  padrino-gen/lib/padrino-gen/generators/mailer.rb
@@ -31,13 +31,11 @@ def create_mailer
31 31
           app = options[:app].underscore
32 32
           check_app_existence(app)
33 33
           self.behavior = :revoke if options[:destroy]
34  
-          simple_name = name.to_s.gsub(/mailer/i, '')
35  
-          @mailer_basename = "#{simple_name.downcase.underscore}_mailer"
36  
-          @mailer_klass    = "#{simple_name.downcase.camelize}Mailer"
37  
-          template "templates/mailer_initializer.rb.tt", destination_root("lib/mailer.rb"), :skip => true
  34
+          @app_name = fetch_app_name(app)
  35
+          @short_name = name.to_s.gsub(/mailer/i, '').underscore.downcase
  36
+          @mailer_basename = @short_name.underscore
38 37
           template "templates/mailer.rb.tt", destination_root(app, "mailers", "#{@mailer_basename}.rb")
39  
-          inject_into_file(destination_root(app, "app.rb"), "    register MailerInitializer\n", :after => "configure do\n")
40  
-          empty_directory destination_root(app, 'views', @mailer_basename)
  38
+          empty_directory destination_root(app, 'views', 'mailers', @mailer_basename)
41 39
         else
42 40
           say "You are not at the root of a Padrino application! (config/boot.rb not found)" and return unless in_app_root?
43 41
         end
48  padrino-gen/lib/padrino-gen/generators/project/config/apps.rb.tt
... ...
@@ -1,28 +1,26 @@
1  
-=begin
2  
-
3  
-This file mounts each application within the Padrino project to a specific path.
4  
-You can mount additional applications using any of these below:
5  
-
6  
-  Padrino.mount("blog").to('/blog')
7  
-  Padrino.mount("blog", :app_class => "BlogApp").to('/blog')
8  
-  Padrino.mount("blog", :app_file =>  "/path/to/blog/app.rb").to('/blog')
9  
-
10  
-You can map also apps to a specified host:
11  
-
12  
-  Padrino.mount_core("Blog").host("blog.example.org")
13  
-  Padrino.mount("Admin").host("admin.example.org")
14  
-  Padrino.mount("WebSite").host(/.*\.?example.org/)
15  
-  Padrino.mount("Foo").to("/foo").host("bar.example.org")
16  
-
17  
-Note 1: that mounted apps by default should be placed into 'apps/app_name'.
18  
-Note 2: if you use host match remember that it's important respect order.
19  
-
20  
-By default, this file simply mounts the core app which was generated with this project.
21  
-However, the mounted core can be modified as needed:
22  
-
23  
-  Padrino.mount_core(:app_file => "/path/to/file", :app_class => "Blog")
24  
-
25  
-=end
  1
+##
  2
+# This file mounts each application within the Padrino project to a specific path.
  3
+# You can mount additional applications using any of these below:
  4
+#
  5
+#   Padrino.mount("blog").to('/blog')
  6
+#   Padrino.mount("blog", :app_class => "BlogApp").to('/blog')
  7
+#   Padrino.mount("blog", :app_file =>  "/path/to/blog/app.rb").to('/blog')
  8
+#
  9
+# You can map also apps to a specified host:
  10
+#
  11
+#   Padrino.mount_core("Blog").host("blog.example.org")
  12
+#   Padrino.mount("Admin").host("admin.example.org")
  13
+#   Padrino.mount("WebSite").host(/.*\.?example.org/)
  14
+#   Padrino.mount("Foo").to("/foo").host("bar.example.org")
  15
+#
  16
+# Note 1: that mounted apps by default should be placed into 'apps/app_name'.
  17
+# Note 2: if you use host match remember that it's important respect order.
  18
+#
  19
+# By default, this file simply mounts the core app which was generated with this project.
  20
+# However, the mounted core can be modified as needed:
  21
+#
  22
+#   Padrino.mount_core(:app_file => "/path/to/file", :app_class => "Blog")
  23
+#
26 24
 
27 25
 # Mounts the core application for this project
28 26
 Padrino.mount_core("<%= @class_name %>")
53  padrino-gen/lib/padrino-gen/generators/templates/mailer.rb.tt
... ...
@@ -1,19 +1,38 @@
1  
-=begin
  1
+##
  2
+# Mailer methods can be defined using the simple format:
  3
+#
  4
+# message :registration_email do |name, user|
  5
+#   from 'admin@site.com'
  6
+#   to   user.email
  7
+#   subject 'Welcome to the site!'
  8
+#   body    render('registration_email', :locals => { :name => name })
  9
+#   content_type 'text/html'       # optional, defaults to plain/text
  10
+#   charset 'windows-1252'         # optional, defaults to utf-8
  11
+#   via     :sendmail              # optional, to smtp if defined, otherwise sendmail
  12
+# end
  13
+#
  14
+# You can set the default delivery settings from your app through:
  15
+#
  16
+#   set :delivery_method, :smtp => {
  17
+#     :address         => 'smtp.yourserver.com',
  18
+#     :port            => '25',
  19
+#     :user_name       => 'user',
  20
+#     :password        => 'pass',
  21
+#     :authentication  => :plain # :plain, :login, :cram_md5, no auth by default
  22
+#     :domain          => "localhost.localdomain" # the HELO domain provided by the client to the server
  23
+#   }
  24
+#
  25
+# or sendmail:
  26
+#
  27
+#   set :delivery_method, :sendmail
  28
+#
  29
+# or for tests:
  30
+#
  31
+#   set :delivery_method, :test
  32
+#
  33
+# and then all delivered mail will use these settings unless otherwise specified.
  34
+#
2 35
 
3  
-Mailer methods can be defined using the simple format:
4  
-
5  
-  def registration_email(name, user_email_address)
6  
-    from 'admin@site.com'
7  
-    to user_email_address
8  
-    subject 'Welcome to the site!'
9  
-    body    :name => name
10  
-    content_type 'text/html'        # optional, defaults to plain/text
11  
-    charset 'windows-1252'        # optional, defaults to utf-8
12  
-    via     :sendmail             # optional, to smtp if defined otherwise sendmail
13  
-  end
14  
-
15  
-=end
16  
-
17  
-class <%= @mailer_klass %> < Padrino::Mailer::Base
18  
-  # Mailer methods here...
  36
+<%= @app_name %>.mailer :<%= @short_name %> do
  37
+  # Message definitions here...
19 38
 end
19  padrino-gen/lib/padrino-gen/generators/templates/mailer_initializer.rb.tt
... ...
@@ -1,19 +0,0 @@
1  
-=begin
2  
-
3  
-By default, Padrino mailer uses the built-in sendmail binary functionality on the server.
4  
-However, smtp is also supported using the following configuration if needed:
5  
-
6  
-=end
7  
-
8  
-module MailerInitializer
9  
-  def self.registered(app)
10  
-    # Padrino::Mailer::Base.smtp_settings = {
11  
-    #  :host   => 'smtp.gmail.com',
12  
-    #  :port   => '587',
13  
-    #  :tls    => true,
14  
-    #  :user   => 'user',
15  
-    #  :pass   => 'pass',
16  
-    #  :auth   => :plain
17  
-    # }
18  
-  end
19  
-end
10  padrino-gen/test/test_app_generator.rb
@@ -37,12 +37,10 @@ def setup
37 37
 
38 38
     should "correctly create a new mailer inside a padrino application" do
39 39
       silence_logger { generate(:project, 'sample_project', '--root=/tmp', '--script=none', '-t=bacon') }
40  
-      silence_logger { generate(:app, 'demo', '--root=/tmp/sample_project') }
41  
-      silence_logger { generate(:mailer, 'demo', '-r=/tmp/sample_project', '-a=demo') }
42  
-      assert_match_in_file(/class DemoMailer < Padrino::Mailer::Base/m, '/tmp/sample_project/demo/mailers/demo_mailer.rb')
43  
-      assert_match_in_file(/Padrino::Mailer::Base.smtp_settings/m, '/tmp/sample_project/lib/mailer.rb')
44  
-      assert_match_in_file(/register MailerInitializer/,'/tmp/sample_project/demo/app.rb')
45  
-      assert_file_exists('/tmp/sample_project/demo/views/demo_mailer')
  40
+      silence_logger { generate(:app, 'demo_app', '--root=/tmp/sample_project') }
  41
+      silence_logger { generate(:mailer, 'demo', '-r=/tmp/sample_project', '-a=demo_app') }
  42
+      assert_match_in_file(/DemoApp.mailer :demo/m, '/tmp/sample_project/demo_app/mailers/demo.rb')
  43
+      assert_dir_exists('/tmp/sample_project/demo_app/views/mailers/demo')
46 44
     end
47 45
   end
48 46
 end
23  padrino-gen/test/test_mailer_generator.rb
@@ -15,26 +15,22 @@ def setup
15 15
     should "support generating a new mailer extended from base" do
16 16
       silence_logger { generate(:project, 'sample_project', '--root=/tmp', '--script=none', '-t=bacon') }
17 17
       silence_logger { generate(:mailer, 'demo', '-r=/tmp/sample_project') }
18  
-      assert_match_in_file(/class DemoMailer < Padrino::Mailer::Base/m, '/tmp/sample_project/app/mailers/demo_mailer.rb')
19  
-      assert_match_in_file(/Padrino::Mailer::Base.smtp_settings/m, '/tmp/sample_project/lib/mailer.rb')
20  
-      assert_match_in_file(/register MailerInitializer/m, '/tmp/sample_project/app/app.rb')
21  
-      assert_file_exists('/tmp/sample_project/app/views/demo_mailer')
  18
+      assert_match_in_file(/SampleProject.mailer :demo/m, '/tmp/sample_project/app/mailers/demo.rb')
  19
+      assert_dir_exists('/tmp/sample_project/app/views/mailers/demo')
22 20
     end
23 21
 
24 22
     should "support generating a new mailer extended from base with long name" do
25 23
       silence_logger { generate(:project, 'sample_project', '--root=/tmp', '--script=none', '-t=bacon') }
26  
-      silence_logger { generate(:mailer, 'user_notice', '-r=/tmp/sample_project') }
27  
-      assert_match_in_file(/class UserNoticeMailer/m, '/tmp/sample_project/app/mailers/user_notice_mailer.rb')
28  
-      assert_match_in_file(/Padrino::Mailer::Base.smtp_settings/m, '/tmp/sample_project/lib/mailer.rb')
29  
-      assert_file_exists('/tmp/sample_project/app/views/user_notice_mailer')
  24
+      silence_logger { generate(:mailer, 'UserNotice', '-r=/tmp/sample_project') }
  25
+      assert_match_in_file(/SampleProject.mailer :user_notice/m, '/tmp/sample_project/app/mailers/user_notice.rb')
  26
+      assert_dir_exists('/tmp/sample_project/app/views/mailers/user_notice')
30 27
     end
31 28
 
32 29
     should "support generating a new mailer extended from base with capitalized name" do
33 30
       silence_logger { generate(:project, 'sample_project', '--root=/tmp', '--script=none', '-t=bacon') }
34 31
       silence_logger { generate(:mailer, 'DEMO', '-r=/tmp/sample_project') }
35  
-      assert_match_in_file(/class DemoMailer < Padrino::Mailer::Base/m, '/tmp/sample_project/app/mailers/demo_mailer.rb')
36  
-      assert_match_in_file(/Padrino::Mailer::Base.smtp_settings/m, '/tmp/sample_project/lib/mailer.rb')
37  
-      assert_file_exists('/tmp/sample_project/app/views/demo_mailer')
  32
+      assert_match_in_file(/SampleProject.mailer :demo/m, '/tmp/sample_project/app/mailers/demo.rb')
  33
+      assert_dir_exists('/tmp/sample_project/app/views/mailers/demo')
38 34
     end
39 35
   end
40 36
 
@@ -43,9 +39,8 @@ def setup
43 39
       silence_logger { generate(:project, 'sample_project', '--root=/tmp', '--script=none', '-t=bacon') }
44 40
       silence_logger { generate(:mailer, 'demo', '-r=/tmp/sample_project') }
45 41
       silence_logger { generate(:mailer, 'demo', '-r=/tmp/sample_project','-d') }
46  
-      assert_no_dir_exists('/tmp/sample_project/app/views/demo_mailer')
47  
-      assert_no_file_exists('/tmp/sample_project/app/mailers/demo_mailer.rb')
48  
-      assert_no_file_exists('/tmp/sample_project/lib/mailer.rb')
  42
+      assert_no_dir_exists('/tmp/sample_project/app/views/demo')
  43
+      assert_no_file_exists('/tmp/sample_project/app/mailers/demo.rb')
49 44
     end
50 45
   end
51 46
 end
1  padrino-helpers/test/fixtures/render_app/app.rb
@@ -9,6 +9,7 @@ def initialize(name); @name = name; end
9 9
 end
10 10
 
11 11
 class RenderDemo < Padrino::Application
  12
+  register Padrino::Helpers
12 13
 
13 14
   # partial with object
14 15
   get '/partial/object' do
105  padrino-mailer/README.rdoc
Source Rendered
@@ -2,37 +2,39 @@
2 2
 
3 3
 === Overview
4 4
 
5  
-This component uses an enhanced version of the excellent <tt>pony</tt> library (vendored) for a powerful but simple
6  
-mailer system within Padrino (and Sinatra). There is full support for using an html content type as well as for file attachments.
7  
-The MailerPlugin has many similarities to ActionMailer but is much lighterweight and (arguably) easier to use.
  5
+This component creates an easy and intuitive interface for delivering email within a Sinatra application. The mail library is utilized
  6
+to do the bulk of the work. There is full support for rendering email templates, using an html content type and for file attachments. 
  7
+The Padrino Mailer uses a familiar Sinatra syntax similar to that of defining routes for a controller.
8 8
 
9 9
 === Usage
10 10
 
11  
-Let's take a look at using the MailerPlugin in an application. By default, MailerPlugin uses the built-in sendmail
12  
-functionality on the server. However, smtp is also supported using the following configuration:
  11
+Let's take a look at using the Mailer in an application. By default, the Mailer uses the built-in sendmail
  12
+command on the server. However, smtp is also supported using the following configuration:
13 13
 
14  
-    Padrino::Mailer::Base.smtp_settings = {
15  
-      :host   => 'smtp.gmail.com',
16  
-      :port   => '587',
17  
-      :tls    => true,
18  
-      :user   => 'user',
19  
-      :pass   => 'pass',
20  
-      :auth   => :plain
21  
-   }
  14
+  # Example for configuring gmail smtp
  15
+  set :delivery_method, :smtp => { 
  16
+    :address              => "smtp.gmail.com",
  17
+    :port                 => 587,
  18
+    :domain               => 'your.host.name',
  19
+    :user_name            => '<username>',
  20
+    :password             => '<password>',
  21
+    :authentication       => 'plain',
  22
+    :enable_starttls_auto => true  
  23
+  }
22 24
 
23  
-Once those have been defined, the default will become smtp delivery unless overwritten in an individual mail definition.
  25
+Once the delivery settings have been defined, the default will become smtp delivery but can be overwritten in each message.
24 26
 
25  
-Padrino supports sending any arbitrary email (using either sendmail or smtp) right from your controllers. 
26  
-This is ideal for ‘one-off’ emails where the ‘full’ mailer object is simply unnecessary or too heavy for your simple task.
  27
+Padrino supports sending quick emails (using either sendmail or smtp) right from your controllers. 
  28
+This is ideal for ‘one-off’ emails where the ‘full’ mailer declaration is simply unnecessary.
27 29
 
28  
-Delivering an email within your controller is simple:
  30
+Delivering an email from within your controller is simple:
29 31
 
30 32
   # app/controllers/session.rb
31 33
   post :create do
32 34
     email(:to => "john@smith.com", :subject => "Successfully Registered!", :body => "Test Body")
33 35
   end
34 36
   
35  
-This simple helper will accept any of the standard email attributes and deliver your email in a single command. You can also render a template for the body and specify the delivery method:
  37
+This <tt>email</tt> helper will accept any of the standard email attributes and deliver your email in a single command. You can also render a template for the body and specify the delivery method:
36 38
 
37 39
   # app/controllers/session.rb
38 40
   post :create do
@@ -40,41 +42,66 @@ This simple helper will accept any of the standard email attributes and deliver
40 42
           :body => render('email/registered'), :via => :sendmail)
41 43
   end
42 44
 
43  
-Padrino also supports more structured mailers. We can define a custom mailer extended from <tt>Padrino::Mailer::Base</tt>.
  45
+Padrino also supports structured mailer declarations. We can define a new mailer using a <tt>mailer</tt> block.
44 46
 
45 47
   # app/mailers/sample_mailer.rb
46  
-  class SampleMailer < Padrino::Mailer::Base
47  
-    def registration_email(name, user_email_address)
48  
-      from 'admin@site.com'
49  
-      to user_email_address
  48
+  MyAppName.mailers :sample do
  49
+    email :registration do |name|
  50
+      from    'admin@site.com'
  51
+      to      'user@domain.com'
50 52
       subject 'Welcome to the site!'
51  
-      body    :name => name
52  
-      type    'html'                # optional, defaults to plain/text
53  
-      charset 'windows-1252'        # optional, defaults to utf-8
54  
-      via     :sendmail             # optional, to smtp if defined otherwise sendmail
55  
-      template 'sample_mailer/foo'  # optional, defaults to views/sample_mailer/registration_email.erb
  53
+      body    render('registration', :locals => { :name => name })
  54
+      content_type 'html'        # optional, defaults to plain/text
  55
+      charset 'windows-1252'     # optional, defaults to utf-8
  56
+      via     :sendmail          # optional, smtp if defined otherwise sendmail
  57
+    end
  58
+  end
  59
+  
  60
+In addition to a standard body, Padrino also easily supports multi-part emails:
  61
+
  62
+  # app/mailers/sample_mailer.rb
  63
+  MyAppName.mailers :sample do
  64
+    email :registration do |name|
  65
+      to      'padrino@test.lindsaar.net'
  66
+      subject "nested multipart"
  67
+      from    "test@example.com"
  68
+
  69
+      text_part render('multipart/basic.plain')
  70
+      html_part render('multipart/basic.html')
  71
+    end
  72
+  end
  73
+  
  74
+Defaults can also be declared on a per-mailer or app-wide basis:
  75
+
  76
+  # app/app.rb
  77
+  set :mailer_defaults, :from => 'admin@site.com'
  78
+  
  79
+  # app/mailers/sample_mailer.rb
  80
+  MyAppName.mailers :sample do
  81
+    defaults :content_type => 'html'
  82
+    email :registration do |name, age|
  83
+      # Uses default 'content_type' and 'from' values but can also overwrite them
  84
+      to      'user@domain.com'
  85
+      subject 'Welcome to the site!'
  86
+      body    render('registration', :locals => { :name => name })
56 87
     end
57 88
   end
58 89
 
59  
-This defines a mail called '<tt>registration_mail</tt>' with the specified attributes for delivery. The <tt>body</tt> method
60  
-is passing the <tt>name</tt> attribute to the body message template which should be defined in
61  
-<tt>[views_path]/sample_mailer/registration_email.erb</tt> as shown below:
  90
+This defines a message called '<tt>registration</tt>' with the specified attributes. The <tt>body</tt> method
  91
+is invoking the render function passing the <tt>name</tt> attribute to the body message template which is defined in
  92
+<tt>[views_path]/mailers/sample/registration.erb</tt> as shown below:
62 93
 
63  
-  # ./views/sample_mailer/registration_email.erb
  94
+  # ./views/mailers/sample/registration.erb
64 95
   This is the body of the email and can access the <%= name %> that was passed in from the mailer definition
65 96
   That's all there is to defining the body of the email which can be plain text or html
66 97
 
67 98
 Once the mailer definition has been completed and the template has been defined, the email can be sent using:
68 99
 
69  
-  SampleMailer.deliver(:registration_email, "Bob", "bob@bobby.com")
70  
-
71  
-or if you like the method_missing approach:
72  
-
73  
-  SampleMailer.deliver_registration_email "Bob", 'bob@bobby.com'
  100
+  deliver(:sample, :registration_email, "Bob", "21")
74 101
 
75  
-And that will then deliver the email according the the configured options. This is really all you need to send emails.
  102
+And that will then deliver the email according the the configured options. This is all you need to send basic emails.
76 103
 
77  
-Be sure to check out the
  104
+The mailer also supports the attachment of files and various other options. Be sure to check out the 
78 105
 {Padrino Mailer}[http://www.padrinorb.com/guides/padrino-mailer] guide for more details on usage.
79 106
 
80 107
 == Copyright
20  padrino-mailer/lib/padrino-mailer.rb
@@ -5,8 +5,10 @@
5 5
   require 'sinatra/tilt'
6 6
 end
7 7
 require 'padrino-core/support_lite'
  8
+require 'mail'
8 9
 
9  
-Dir[File.dirname(__FILE__) + '/padrino-mailer/**/*.rb'].each { |file| require file }
  10
+# Require respecting order our dependencies
  11
+Dir[File.dirname(__FILE__) + '/padrino-mailer/**/*.rb'].each {|file| require file }
10 12
 
11 13
 module Padrino
12 14
   ##
@@ -19,23 +21,7 @@ module Mailer
19 21
     # Used Padrino::Application for register Padrino::Mailer::Base::views_path
20 22
     #
21 23
     def self.registered(app)
22  
-      Padrino::Mailer::Base::views_path << app.views
23 24
       app.helpers Padrino::Mailer::Helpers
24 25
     end
25  
-    
26  
-    module Helpers
27  
-      ##
28  
-      # Delivers an email with the given mail attributes (to, from, subject, cc, bcc, body, et.al)
29  
-      #
30  
-      # ==== Examples
31  
-      #
32  
-      #   email :to => @user.email, :from => "awesomeness@example.com", 
33  
-      #         :subject => "Welcome to Awesomeness!", :body => haml(:some_template)
34  
-      #
35  
-      def email(mail_attributes)
36  
-        smtp_settings = Padrino::Mailer::Base.smtp_settings
37  
-        Padrino::Mailer::MailObject.new(mail_attributes, smtp_settings).deliver
38  
-      end
39  
-    end
40 26
   end # Mailer
41 27
 end # Padrino
134  padrino-mailer/lib/padrino-mailer/base.rb
@@ -3,100 +3,78 @@ module Mailer
3 3
     ##
4 4
     # This is the abstract class that other mailers will inherit from in order to send mail
5 5
     #
6  
-    # You can set the default delivery settings through:
  6
+    # You can set the default delivery settings from your app through:
7 7
     #
8  
-    #   Padrino::Mailer::Base.smtp_settings = {
9  
-    #     :host   => 'smtp.yourserver.com',
10  
-    #     :port   => '25',
11  
-    #     :user   => 'user',
12  
-    #     :pass   => 'pass',
13  
-    #     :auth   => :plain # :plain, :login, :cram_md5, no auth by default
14  
-    #     :domain => "localhost.localdomain" # the HELO domain provided by the client to the server
  8
+    #   set :delivery_method, :smtp => {
  9
+    #     :address         => 'smtp.yourserver.com',
  10
+    #     :port            => '25',
  11
+    #     :user_name       => 'user',
  12
+    #     :password        => 'pass',
  13
+    #     :authentication  => :plain # :plain, :login, :cram_md5, no auth by default
  14
+    #     :domain          => "localhost.localdomain" # the HELO domain provided by the client to the server
15 15
     #   }
16 16
     #
  17
+    # or sendmail:
  18
+    #
  19
+    #   set :delivery_method, :sendmail
  20
+    #
  21
+    # or for tests:
  22
+    #
  23
+    #   set :delivery_method, :test
  24
+    #
17 25
     # and then all delivered mail will use these settings unless otherwise specified.
18 26
     #
19 27
     class Base
20  
-      ##
21  
-      # Returns the available mail fields when composing a message
22  
-      #
23  
-      def self.mail_fields
24  
-        [:to, :cc, :bcc, :reply_to, :from, :subject, :content_type, :charset, :via, :attachments, :template]
25  
-      end
26  
-
27  
-      @@views_path = []
28  
-      cattr_accessor :smtp_settings
29  
-      cattr_accessor :views_path
30  
-      attr_accessor :mail_attributes
31  
-
32  
-      def initialize(mail_name=nil) #:nodoc:
33  
-        @mail_name = mail_name
34  
-        @mail_attributes = {}
35  
-      end
36  
-
37  
-      ##
38  
-      # Defines a method allowing mail attributes to be set into a hash for use when delivering
39  
-      #
40  
-      self.mail_fields.each do |field|
41  
-        define_method(field) { |value| @mail_attributes[field] = value }
42  
-      end
43  
-
44  
-      ##
45  
-      # Assigns the body key to the mail attributes either with the rendered body from a template or the given string value
46  
-      #
47  
-      def body(body_value)
48  
-        final_template = template_path
49  
-        raise "Template for '#{@mail_name}' could not be located in views path!" unless final_template
50  
-        @mail_attributes[:body] = Tilt.new(final_template).render(self, body_value.symbolize_keys) if body_value.is_a?(Hash)
51  
-        @mail_attributes[:body] = body_value if body_value.is_a?(String)
52  
-      end
  28
+      attr_accessor :delivery_settings, :app, :mailer_name, :messages
53 29
 
54  
-      ##
55  
-      # Returns the path to the email template searched for using glob pattern
56  
-      #
57  
-      def template_path
58  
-        self.views_path.each do |view_path|
59  
-          template = Dir[File.join(view_path, template_pattern)].first
60  
-          return template if template
61  
-        end
  30
+      def initialize(app, name, &block) #:nodoc:
  31
+        @mailer_name = name
  32
+        @messages    = {}
  33
+        @defaults    = {}
  34
+        @app         = app
  35
+        instance_eval(&block)
62 36
       end
63 37
 
64 38
       ##
65  
-      # Delivers the specified message for mail_name to the intended recipients
66  
-      # mail_name corresponds to the name of a defined method within the mailer class
  39
+      # Defines a mailer object allowing the definition of various email messages that can be delivered
67 40
       #
68 41
       # ==== Examples
69 42
       #
70  
-      #   SampleMailer.deliver(:birthday_message)
71  
-      #
72  
-      def self.deliver(mail_name, *args)
73  
-        mail_object = self.new(mail_name)
74  
-        mail_object.method(mail_name).call(*args)
75  
-        MailObject.new(mail_object.mail_attributes, self.smtp_settings).deliver
76  
-      end
77  
-
78  
-      ##
79  
-      # Returns true if a mail exists with the name being delivered
  43
+      #   email :birthday do |name, age|
  44
+      #     subject "Happy Birthday!"
  45
+      #     to   'john@fake.com'
  46
+      #     from 'noreply@birthday.com'
  47
+      #     body 'name' => name, 'age' => age
  48
+      #   end
80 49
       #
81  
-      def self.respond_to?(method_sym, include_private = false)
82  
-        method_sym.to_s =~ /deliver_(.*)/ ? self.method_defined?($1) : super(method_sym, include_private)
  50
+      def email(name, &block)
  51
+        raise "The email '#{name}' is already defined" if self.messages[name].present?
  52
+        self.messages[name] = Proc.new { |*attrs|
  53
+          message = Mail::Message.new(self.app)
  54
+          message.defaults = self.defaults if self.defaults.any?
  55
+          message.delivery_method(*delivery_settings)
  56
+          message.instance_exec(*attrs, &block)
  57
+          message
  58
+        }
83 59
       end
84  
-
85  
-      ##
86  
-      # Handles method missing for a mailer class. Delivers a message based on the method
87  
-      # being called i.e #deliver_birthday_message(22) invokes #birthday_message(22) to setup mail object
  60
+      alias :message :email
  61
+      
  62
+      # Defines the default attributes for a message in this mailer (including app-wide defaults)
  63
+      # 
  64
+      # ==== Examples
88 65
       #
89  
-      def self.method_missing(method_sym, *arguments, &block)
90  
-        method_sym.to_s =~ /deliver_(.*)/ ? self.deliver($1, *arguments) : super(method_sym, *arguments, &block)
91  
-      end
92  
-
93  
-      private
94  
-
95  
-        # Returns the glob pattern of the template file to locate and render
96  
-        def template_pattern
97  
-          @_pattern ||= (@mail_attributes[:template].present? ? "#{@mail_attributes[:template]}.*" :
98  
-                         File.join(self.class.name.underscore.split("/").last, "#{@mail_name}.*"))
  66
+      #   mailer :alternate do
  67
+      #    defaults :from => 'padrino@from.com', :to => 'padrino@to.com'
  68
+      #    email(:foo) do ... end
  69
+      #  end
  70
+      # 
  71
+      def defaults(attributes=nil)
  72
+        if attributes.nil? # Retrieve the default values
  73
+          @app.respond_to?(:mailer_defaults) ? @app.mailer_defaults.merge(@defaults) : @defaults
  74
+        else # updates the default values
  75
+          @defaults = attributes
99 76
         end
  77
+      end
100 78
     end # Base
101 79
   end # Mailer
102  
-end # Padrino
  80
+end # Padrino
77  padrino-mailer/lib/padrino-mailer/delivery.rb
... ...
@@ -1,77 +0,0 @@
1  
-require 'rubygems'
2  
-require 'net/smtp'
3  
-begin
4  
-  require 'smtp_tls'
5  
-rescue LoadError
6  
-end
7  
-require 'base64'
8  
-require 'mail'
9  
-
10  
-module Padrino
11  
-  module Mailer
12  
-    module Delivery
13  
-
14  
-      class << self
15  
-        def mail(options)
16  
-          raise(ArgumentError, ":to is required") unless options[:to]
17  
-          via = options.delete(:via)
18  
-          mail = build_mail(options)
19  
-          if via.nil?
20  
-            transport(mail)
21  
-          elsif via.present? && via_options.include?(via.to_s)
22  
-            method("transport_via_#{via}").call(mail, options)
23  
-          else # via option is incorrect
24  
-            raise(ArgumentError, ":via must be either smtp or sendmail")
25  
-          end
26  
-        end
27  
-
28  
-        def build_mail(options)
29  
-          mail = Mail.new
30  
-          mail.to       = options[:to]
31  
-          mail.cc       = options[:cc]   || ''
32  
-          mail.bcc      = options[:bcc]  || ''
33  
-          mail.from     = options[:from] || 'padrino@unknown'
34