merb 0.3.7 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +25 -26
- data/Rakefile +48 -36
- data/app_generators/merb/USAGE +5 -0
- data/app_generators/merb/merb_generator.rb +107 -0
- data/app_generators/merb/templates/Rakefile +99 -0
- data/{examples/skeleton/dist → app_generators/merb/templates}/app/controllers/application.rb +1 -1
- data/app_generators/merb/templates/app/controllers/exceptions.rb +13 -0
- data/{examples/skeleton/dist → app_generators/merb/templates}/app/helpers/global_helper.rb +0 -0
- data/{examples/skeleton/dist/app/mailers → app_generators/merb/templates/app/mailers/views}/layout/application.erb +0 -0
- data/app_generators/merb/templates/app/views/exceptions/internal_server_error.html.erb +207 -0
- data/app_generators/merb/templates/app/views/exceptions/not_acceptable.html.erb +38 -0
- data/app_generators/merb/templates/app/views/exceptions/not_found.html.erb +40 -0
- data/app_generators/merb/templates/app/views/layout/application.html.erb +11 -0
- data/app_generators/merb/templates/config/boot.rb +11 -0
- data/app_generators/merb/templates/config/dependencies.rb +41 -0
- data/{examples/skeleton/dist/conf → app_generators/merb/templates/config}/environments/development.rb +0 -0
- data/{examples/skeleton/dist/conf → app_generators/merb/templates/config}/environments/production.rb +0 -0
- data/{examples/skeleton/dist/conf → app_generators/merb/templates/config}/environments/test.rb +0 -0
- data/app_generators/merb/templates/config/merb.yml +64 -0
- data/app_generators/merb/templates/config/merb_init.rb +16 -0
- data/app_generators/merb/templates/config/plugins.yml +1 -0
- data/app_generators/merb/templates/config/router.rb +32 -0
- data/{lib/merb/core_ext/merb_array.rb → app_generators/merb/templates/config/upload.conf} +0 -0
- data/app_generators/merb/templates/public/images/merb.jpg +0 -0
- data/app_generators/merb/templates/public/merb.fcgi +6 -0
- data/app_generators/merb/templates/public/stylesheets/master.css +119 -0
- data/app_generators/merb/templates/script/destroy +28 -0
- data/app_generators/merb/templates/script/generate +28 -0
- data/{examples/skeleton → app_generators/merb/templates}/script/stop_merb +0 -0
- data/app_generators/merb/templates/script/win_script.cmd +1 -0
- data/app_generators/merb/templates/spec/spec.opts +6 -0
- data/app_generators/merb/templates/spec/spec_helper.rb +10 -0
- data/app_generators/merb/templates/test/test_helper.rb +13 -0
- data/app_generators/merb_plugin/USAGE +5 -0
- data/app_generators/merb_plugin/merb_plugin_generator.rb +64 -0
- data/app_generators/merb_plugin/templates/LICENSE +20 -0
- data/app_generators/merb_plugin/templates/README +4 -0
- data/app_generators/merb_plugin/templates/Rakefile +35 -0
- data/app_generators/merb_plugin/templates/TODO +5 -0
- data/app_generators/merb_plugin/templates/merbtasks.rb +6 -0
- data/app_generators/merb_plugin/templates/sampleplugin.rb +10 -0
- data/app_generators/merb_plugin/templates/sampleplugin_spec.rb +7 -0
- data/app_generators/merb_plugin/templates/spec_helper.rb +2 -0
- data/bin/merb +1 -1
- data/lib/autotest/discover.rb +3 -0
- data/lib/autotest/merb_rspec.rb +79 -0
- data/lib/merb.rb +72 -93
- data/lib/merb/{merb_abstract_controller.rb → abstract_controller.rb} +28 -5
- data/lib/merb/caching/action_cache.rb +65 -29
- data/lib/merb/caching/fragment_cache.rb +9 -4
- data/lib/merb/caching/store/file_cache.rb +22 -14
- data/lib/merb/caching/store/memory_cache.rb +26 -8
- data/lib/merb/{merb_constants.rb → constants.rb} +9 -7
- data/lib/merb/controller.rb +178 -0
- data/lib/merb/core_ext.rb +13 -11
- data/lib/merb/core_ext/array.rb +0 -0
- data/lib/merb/core_ext/{merb_class.rb → class.rb} +0 -0
- data/lib/merb/core_ext/{merb_enumerable.rb → enumerable.rb} +0 -0
- data/lib/merb/core_ext/get_args.rb +52 -0
- data/lib/merb/core_ext/{merb_hash.rb → hash.rb} +40 -11
- data/lib/merb/core_ext/{merb_inflections.rb → inflections.rb} +0 -0
- data/lib/merb/core_ext/{merb_inflector.rb → inflector.rb} +1 -1
- data/lib/merb/core_ext/{merb_kernel.rb → kernel.rb} +56 -3
- data/lib/merb/core_ext/mash.rb +88 -0
- data/lib/merb/core_ext/{merb_module.rb → module.rb} +0 -0
- data/lib/merb/core_ext/{merb_numeric.rb → numeric.rb} +0 -0
- data/lib/merb/core_ext/{merb_object.rb → object.rb} +10 -47
- data/lib/merb/core_ext/string.rb +56 -0
- data/lib/merb/core_ext/{merb_symbol.rb → symbol.rb} +0 -0
- data/lib/merb/dispatcher.rb +109 -0
- data/lib/merb/{merb_drb_server.rb → drb_server.rb} +0 -0
- data/lib/merb/erubis_ext.rb +10 -0
- data/lib/merb/exceptions.rb +173 -0
- data/lib/merb/generators/merb_app/merb_app.rb +5 -25
- data/lib/merb/generators/merb_generator_helpers.rb +317 -0
- data/lib/merb/generators/merb_plugin.rb +19 -0
- data/lib/merb/logger.rb +65 -0
- data/lib/merb/{merb_mail_controller.rb → mail_controller.rb} +102 -49
- data/lib/merb/{merb_mailer.rb → mailer.rb} +31 -27
- data/lib/merb/mixins/{basic_authentication_mixin.rb → basic_authentication.rb} +3 -3
- data/lib/merb/mixins/{controller_mixin.rb → controller.rb} +131 -112
- data/lib/merb/mixins/{erubis_capture_mixin.rb → erubis_capture.rb} +12 -21
- data/lib/merb/mixins/{form_control_mixin.rb → form_control.rb} +6 -12
- data/lib/merb/mixins/render.rb +401 -0
- data/lib/merb/mixins/responder.rb +378 -0
- data/lib/merb/mixins/{view_context_mixin.rb → view_context.rb} +65 -10
- data/lib/merb/mixins/web_controller.rb +29 -0
- data/lib/merb/{merb_handler.rb → mongrel_handler.rb} +59 -38
- data/lib/merb/part_controller.rb +19 -0
- data/lib/merb/plugins.rb +16 -0
- data/lib/merb/rack_adapter.rb +37 -0
- data/lib/merb/request.rb +421 -0
- data/lib/merb/router.rb +576 -0
- data/lib/merb/{merb_server.rb → server.rb} +275 -71
- data/lib/merb/session.rb +10 -10
- data/lib/merb/session/cookie_store.rb +125 -0
- data/lib/merb/session/{merb_mem_cache_session.rb → mem_cache_session.rb} +22 -9
- data/lib/merb/session/{merb_memory_session.rb → memory_session.rb} +15 -11
- data/lib/merb/template.rb +35 -8
- data/lib/merb/template/erubis.rb +16 -10
- data/lib/merb/template/haml.rb +33 -20
- data/lib/merb/template/markaby.rb +16 -14
- data/lib/merb/template/xml_builder.rb +8 -4
- data/lib/merb/test/{merb_fake_request.rb → fake_request.rb} +11 -5
- data/lib/merb/test/helper.rb +31 -0
- data/lib/merb/test/hpricot.rb +136 -0
- data/lib/merb/test/{merb_multipart.rb → multipart.rb} +1 -1
- data/lib/merb/test/rspec.rb +93 -0
- data/lib/merb/{merb_upload_handler.rb → upload_handler.rb} +5 -6
- data/lib/merb/{merb_upload_progress.rb → upload_progress.rb} +1 -1
- data/lib/merb/{merb_view_context.rb → view_context.rb} +27 -42
- data/lib/{merb_tasks.rb → tasks.rb} +0 -0
- data/lib/tasks/merb.rake +21 -11
- data/merb_default_generators/model/USAGE +0 -0
- data/merb_default_generators/model/model_generator.rb +16 -0
- data/merb_default_generators/model/templates/new_model_template.erb +5 -0
- data/merb_default_generators/resource_controller/USAGE +0 -0
- data/merb_default_generators/resource_controller/resource_controller_generator.rb +26 -0
- data/merb_default_generators/resource_controller/templates/controller.rb +30 -0
- data/merb_default_generators/resource_controller/templates/edit.html.erb +1 -0
- data/merb_default_generators/resource_controller/templates/helper.rb +5 -0
- data/merb_default_generators/resource_controller/templates/index.html.erb +1 -0
- data/merb_default_generators/resource_controller/templates/new.html.erb +1 -0
- data/merb_default_generators/resource_controller/templates/show.html.erb +1 -0
- data/merb_generators/controller/USAGE +5 -0
- data/merb_generators/controller/controller_generator.rb +16 -0
- data/merb_generators/controller/templates/controller.rb +8 -0
- data/merb_generators/controller/templates/helper.rb +5 -0
- data/merb_generators/controller/templates/index.html.erb +3 -0
- data/merb_generators/resource/USAGE +0 -0
- data/merb_generators/resource/resource_generator.rb +60 -0
- data/rspec_generators/merb_controller_test/merb_controller_test_generator.rb +67 -0
- data/rspec_generators/merb_controller_test/templates/controller_spec.rb +8 -0
- data/rspec_generators/merb_controller_test/templates/edit_spec.rb +12 -0
- data/rspec_generators/merb_controller_test/templates/helper_spec.rb +5 -0
- data/rspec_generators/merb_controller_test/templates/index_spec.rb +12 -0
- data/rspec_generators/merb_controller_test/templates/new_spec.rb +12 -0
- data/rspec_generators/merb_controller_test/templates/show_spec.rb +5 -0
- data/rspec_generators/merb_model_test/merb_model_test_generator.rb +26 -0
- data/rspec_generators/merb_model_test/templates/model_spec_template.erb +7 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/test_unit_generators/merb_controller_test/merb_controller_test_generator.rb +53 -0
- data/test_unit_generators/merb_controller_test/templates/functional_test.rb +17 -0
- data/test_unit_generators/merb_controller_test/templates/helper_test.rb +9 -0
- data/test_unit_generators/merb_model_test/merb_model_test_generator.rb +29 -0
- data/test_unit_generators/merb_model_test/templates/model_test_unit_template.erb +9 -0
- metadata +172 -94
- data/examples/README_EXAMPLES +0 -10
- data/examples/skeleton/Rakefile +0 -68
- data/examples/skeleton/dist/app/views/layout/application.herb +0 -12
- data/examples/skeleton/dist/conf/database.yml +0 -23
- data/examples/skeleton/dist/conf/merb.yml +0 -57
- data/examples/skeleton/dist/conf/merb_init.rb +0 -24
- data/examples/skeleton/dist/conf/router.rb +0 -22
- data/examples/skeleton/dist/conf/upload.conf +0 -5
- data/examples/skeleton/dist/schema/migrations/001_add_sessions_table.rb +0 -14
- data/examples/skeleton/script/new_migration +0 -21
- data/lib/merb/core_ext/merb_string.rb +0 -18
- data/lib/merb/merb_controller.rb +0 -206
- data/lib/merb/merb_dispatcher.rb +0 -87
- data/lib/merb/merb_exceptions.rb +0 -319
- data/lib/merb/merb_part_controller.rb +0 -42
- data/lib/merb/merb_plugins.rb +0 -293
- data/lib/merb/merb_request.rb +0 -165
- data/lib/merb/merb_router.rb +0 -309
- data/lib/merb/merb_yaml_store.rb +0 -31
- data/lib/merb/mixins/render_mixin.rb +0 -283
- data/lib/merb/mixins/responder_mixin.rb +0 -159
- data/lib/merb/session/merb_ar_session.rb +0 -131
- data/lib/merb/vendor/paginator/README.txt +0 -84
- data/lib/merb/vendor/paginator/paginator.rb +0 -124
- data/lib/tasks/db.rake +0 -55
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
require 'find'
|
|
3
|
+
|
|
4
|
+
module Merb
|
|
5
|
+
|
|
6
|
+
class PluginGenerator
|
|
7
|
+
def self.run(path)
|
|
8
|
+
require 'rubygems'
|
|
9
|
+
require 'rubigen'
|
|
10
|
+
|
|
11
|
+
require 'rubigen/scripts/generate'
|
|
12
|
+
RubiGen::Base.use_application_sources!
|
|
13
|
+
RubiGen::Scripts::Generate.new.run([path], :generator => 'merb_plugin', :backtrace => true)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
end
|
|
19
|
+
|
data/lib/merb/logger.rb
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
module Merb
|
|
2
|
+
|
|
3
|
+
class Logger
|
|
4
|
+
module Severity
|
|
5
|
+
DEBUG = 0
|
|
6
|
+
INFO = 1
|
|
7
|
+
WARN = 2
|
|
8
|
+
ERROR = 3
|
|
9
|
+
FATAL = 4
|
|
10
|
+
UNKNOWN = 5
|
|
11
|
+
end
|
|
12
|
+
include Severity
|
|
13
|
+
|
|
14
|
+
attr_accessor :level
|
|
15
|
+
attr_reader :buffer
|
|
16
|
+
|
|
17
|
+
def initialize(log, level = DEBUG)
|
|
18
|
+
@level = level
|
|
19
|
+
@buffer = []
|
|
20
|
+
if log.respond_to?(:write)
|
|
21
|
+
@log = log
|
|
22
|
+
elsif File.exist?(log)
|
|
23
|
+
@log = open(log, (File::WRONLY | File::APPEND))
|
|
24
|
+
@log.sync = true
|
|
25
|
+
else
|
|
26
|
+
@log = open(log, (File::WRONLY | File::APPEND | File::CREAT))
|
|
27
|
+
@log.sync = true
|
|
28
|
+
@log.write("# Logfile created on %s\n" % [Time.now.to_s])
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def flush
|
|
33
|
+
@log.write @buffer.slice!(0..-1).to_s unless @buffer.size == 0
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def close
|
|
37
|
+
flush
|
|
38
|
+
@log.close if @log.respond_to?(:close)
|
|
39
|
+
@log = nil
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def add(severity, message = nil, progname = nil, &block)
|
|
43
|
+
return if @level > severity
|
|
44
|
+
message = (message || (block && block.call) || progname).to_s
|
|
45
|
+
# If a newline is necessary then create a new message ending with a newline.
|
|
46
|
+
# Ensures that the original message is not mutated.
|
|
47
|
+
message = "#{message}\n" unless message[-1] == ?\n
|
|
48
|
+
@buffer << message
|
|
49
|
+
message
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
Severity.constants.each do |severity|
|
|
53
|
+
class_eval <<-EOT
|
|
54
|
+
def #{severity.downcase}(message = nil, progname = nil, &block)
|
|
55
|
+
add(#{severity}, message, progname, &block)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def #{severity.downcase}?
|
|
59
|
+
#{severity} >= @level
|
|
60
|
+
end
|
|
61
|
+
EOT
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -1,9 +1,72 @@
|
|
|
1
|
-
require File.dirname(__FILE__)+'/merb_mailer'
|
|
2
1
|
|
|
3
2
|
module Merb
|
|
3
|
+
|
|
4
|
+
# Sending mail from a controller involves three steps:
|
|
5
|
+
#
|
|
6
|
+
# * Set mail settings in merb_init.rb (Not shown here...see the Mailer docs).
|
|
7
|
+
# * Create a MailController subclass with actions and templates.
|
|
8
|
+
# * Call the MailController from another Controller via the send_mail method.
|
|
9
|
+
#
|
|
10
|
+
# First, create a file in app/mailers that subclasses Merb::MailController.
|
|
11
|
+
# The actions in this controller will do nothing but render mail.
|
|
12
|
+
#
|
|
13
|
+
# # app/mailers/article_mailer.rb
|
|
14
|
+
# class ArticleMailer < Merb::MailController
|
|
15
|
+
#
|
|
16
|
+
# def notify
|
|
17
|
+
# @user = params[:user]
|
|
18
|
+
# render_mail
|
|
19
|
+
# end
|
|
20
|
+
#
|
|
21
|
+
# end
|
|
22
|
+
#
|
|
23
|
+
# You also can access the params hash for values passed with the
|
|
24
|
+
# Controller.send_mail method. See also the documentation for
|
|
25
|
+
# render_mail to see all the ways it can be called.
|
|
26
|
+
#
|
|
27
|
+
# Create a template in a subdirectory of app/mailers/views that corresponds
|
|
28
|
+
# to the controller and action name. Put plain text and ERB tags here:
|
|
29
|
+
#
|
|
30
|
+
# # app/mailers/views/article_mailer/notify.text.erb
|
|
31
|
+
# Hey, <%= @user.name %>,
|
|
32
|
+
#
|
|
33
|
+
# We're running a sale on dog bones!
|
|
34
|
+
#
|
|
35
|
+
# Finally, call the Controller.send_mail method from a standard
|
|
36
|
+
# Merb controller.
|
|
37
|
+
#
|
|
38
|
+
# class Articles < Application
|
|
39
|
+
#
|
|
40
|
+
# def index
|
|
41
|
+
# @user = User.find_by_name('louie')
|
|
42
|
+
#
|
|
43
|
+
# send_mail(ArticleMailer, :notify, {
|
|
44
|
+
# :from => "me@example.com",
|
|
45
|
+
# :to => "louie@example.com",
|
|
46
|
+
# :subject => "Sale on Dog Bones!"
|
|
47
|
+
# }, { :user => @user })
|
|
48
|
+
# render
|
|
49
|
+
# end
|
|
50
|
+
#
|
|
51
|
+
# end
|
|
52
|
+
#
|
|
53
|
+
# Note: If you don't pass a fourth argument to Controller.send_mail,
|
|
54
|
+
# the controller's params will be sent to the MailController subclass
|
|
55
|
+
# as params. However, you can explicitly send a hash of objects that
|
|
56
|
+
# will populate the params hash instead. In either case, you must
|
|
57
|
+
# set instance variables in the MailController's actions if you
|
|
58
|
+
# want to use them in the MailController's views.
|
|
59
|
+
#
|
|
60
|
+
# The MailController class is very powerful. You can:
|
|
61
|
+
#
|
|
62
|
+
# * Send multipart email with a single call to render_mail.
|
|
63
|
+
# * Attach files.
|
|
64
|
+
# * Render layouts and other templates.
|
|
65
|
+
# * Use any template engine supported by Merb.
|
|
66
|
+
|
|
4
67
|
class MailController < AbstractController
|
|
5
68
|
|
|
6
|
-
self._template_root = File.expand_path(
|
|
69
|
+
self._template_root = File.expand_path(self._template_root / "../app/mailers/views")
|
|
7
70
|
class_inheritable_accessor :_mailer_klass
|
|
8
71
|
self._mailer_klass = Merb::Mailer
|
|
9
72
|
|
|
@@ -18,6 +81,7 @@ module Merb
|
|
|
18
81
|
@params = params
|
|
19
82
|
@base_controller = controller
|
|
20
83
|
@session = (controller && controller.session) || {}
|
|
84
|
+
super
|
|
21
85
|
end
|
|
22
86
|
|
|
23
87
|
def filters_halted
|
|
@@ -32,13 +96,13 @@ module Merb
|
|
|
32
96
|
# default Merb render method.
|
|
33
97
|
#
|
|
34
98
|
# First of all, you'll need to store email files in your
|
|
35
|
-
#
|
|
99
|
+
# app/mailers/views directory. They should be under a directory that
|
|
36
100
|
# matches the name of your mailer (e.g. TestMailer's views would be stored
|
|
37
101
|
# under test_mailer).
|
|
38
102
|
#
|
|
39
103
|
# The files themselves should be named action_name.mime_type.extension. For
|
|
40
|
-
# example,
|
|
41
|
-
# rendered from the "foo" action would be named foo.html.
|
|
104
|
+
# example, an erb template that should be the HTML part of the email, and
|
|
105
|
+
# rendered from the "foo" action would be named foo.html.erb.
|
|
42
106
|
#
|
|
43
107
|
# The only mime-types currently supported are "html" and "text", which
|
|
44
108
|
# correspond to text/html and text/plain respectively. All template systems
|
|
@@ -91,37 +155,41 @@ module Merb
|
|
|
91
155
|
#
|
|
92
156
|
# render_mail :html => :foo, :text => "BAR"
|
|
93
157
|
def render_mail(options = @method)
|
|
94
|
-
#
|
|
158
|
+
@_missing_templates = false # used to make sure that at least one template was found
|
|
159
|
+
# # If the options are not a hash, normalize to an action hash
|
|
95
160
|
options = {:action => {:html => options, :text => options}} if !options.is_a?(Hash)
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
#
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
161
|
+
|
|
162
|
+
# Take care of the options
|
|
163
|
+
use_options = {}
|
|
164
|
+
opts = options.dup
|
|
165
|
+
actions = opts.delete(:action) if opts[:action].is_a?(Hash)
|
|
166
|
+
templates = opts.delete(:template) if opts[:template].is_a?(Hash)
|
|
167
|
+
|
|
168
|
+
# Prepare the options hash for each format
|
|
169
|
+
# We need to delete anything relating to the other format here
|
|
170
|
+
# before we try to render the template.
|
|
171
|
+
[:html, :text].each do |fmt|
|
|
172
|
+
opts_hash = use_options[fmt] = {}
|
|
173
|
+
opts_hash[fmt] = opts.delete(fmt)
|
|
174
|
+
opts_hash[fmt] ||= actions[fmt] if actions && actions[fmt]
|
|
175
|
+
opts_hash[:tempalte] = templates[fmt] if templates && templates[fmt]
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# Send the result to the mailer
|
|
179
|
+
{ :html => "rawhtml=", :text => "text="}.each do |fmt,meth|
|
|
180
|
+
begin
|
|
181
|
+
value = render use_options[fmt].merge!(opts).merge!(:clean_context => true, :format => fmt)
|
|
182
|
+
@mail.send(meth,value) unless value.nil? || value.empty?
|
|
183
|
+
rescue => e
|
|
184
|
+
# An error should be logged if no template is found instead of an error raised
|
|
185
|
+
if @_missing_templates
|
|
186
|
+
MERB_LOGGER.error(e)
|
|
187
|
+
else
|
|
188
|
+
@_missing_templates = true
|
|
119
189
|
end
|
|
120
|
-
# string to render
|
|
121
|
-
else
|
|
122
|
-
@mail.send((mime_type == :html ? "rawhtml=" : "text="), renderer)
|
|
123
190
|
end
|
|
124
191
|
end
|
|
192
|
+
@mail
|
|
125
193
|
end
|
|
126
194
|
|
|
127
195
|
# Attaches a file or multiple files to an email. You call this from a
|
|
@@ -163,6 +231,8 @@ module Merb
|
|
|
163
231
|
@mailer = self.class._mailer_klass.new(mail_params)
|
|
164
232
|
@mail = @mailer.mail
|
|
165
233
|
@method = method
|
|
234
|
+
|
|
235
|
+
# dipatch and render use params[:action], so set it
|
|
166
236
|
params[:action] = method
|
|
167
237
|
body = dispatch method
|
|
168
238
|
if !@mail.html.blank? || !@mail.text.blank?
|
|
@@ -179,22 +249,5 @@ module Merb
|
|
|
179
249
|
new({}).dispatch_and_deliver method, mail_params
|
|
180
250
|
end
|
|
181
251
|
|
|
182
|
-
private
|
|
183
|
-
def mimed_layout(mime_type, layout = nil)
|
|
184
|
-
if layout && layout != :application
|
|
185
|
-
layout_choice = find_template(:layout => layout + ".#{mime_type}") ||
|
|
186
|
-
find_template(:layout => layout)
|
|
187
|
-
elsif name = find_template(:layout => self.class.name.snake_case + ".#{mime_type}")
|
|
188
|
-
layout_choice = name
|
|
189
|
-
elsif name = find_template(:layout => self.class.name.snake_case)
|
|
190
|
-
layout_choice = name
|
|
191
|
-
elsif name = find_template(:layout => "application.#{mime_type}")
|
|
192
|
-
layout_choice = name
|
|
193
|
-
else
|
|
194
|
-
layout_choice = find_template(:layout => "application")
|
|
195
|
-
end
|
|
196
|
-
layout_choice = layout_choice.split("/").last.split(".")[0...-1].join(".")
|
|
197
|
-
end
|
|
198
|
-
|
|
199
252
|
end
|
|
200
253
|
end
|
|
@@ -11,6 +11,32 @@ class MailFactory
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
module Merb
|
|
14
|
+
|
|
15
|
+
# You'll need a simple config like this in merb_init.rb if you want
|
|
16
|
+
# to actually send mail:
|
|
17
|
+
#
|
|
18
|
+
# Merb::Mailer.config = {
|
|
19
|
+
# :host=>'smtp.yourserver.com',
|
|
20
|
+
# :port=>'25',
|
|
21
|
+
# :user=>'user',
|
|
22
|
+
# :pass=>'pass',
|
|
23
|
+
# :auth=>:plain # :plain, :login, or :cram_md5, default :plain
|
|
24
|
+
# }
|
|
25
|
+
#
|
|
26
|
+
# or
|
|
27
|
+
#
|
|
28
|
+
# Merb::Mailer.config = {:sendmail_path => '/somewhere/odd')
|
|
29
|
+
# Merb::Mailer.delivery_method = :sendmail
|
|
30
|
+
#
|
|
31
|
+
# You could send mail manually like this (but it's better to use
|
|
32
|
+
# a MailController instead).
|
|
33
|
+
#
|
|
34
|
+
# m = Merb::Mailer.new :to => 'foo@bar.com',
|
|
35
|
+
# :from => 'bar@foo.com',
|
|
36
|
+
# :subject => 'Welcome to whatever!',
|
|
37
|
+
# :body => partial(:sometemplate)
|
|
38
|
+
# m.deliver!
|
|
39
|
+
|
|
14
40
|
class Mailer
|
|
15
41
|
|
|
16
42
|
class_inheritable_accessor :config, :delivery_method, :deliveries
|
|
@@ -18,7 +44,7 @@ module Merb
|
|
|
18
44
|
self.deliveries = []
|
|
19
45
|
|
|
20
46
|
def sendmail
|
|
21
|
-
sendmail = IO.popen("
|
|
47
|
+
sendmail = IO.popen("#{config[:sendmail_path]} #{@mail.to}", 'w+')
|
|
22
48
|
sendmail.puts @mail.to_s
|
|
23
49
|
sendmail.close
|
|
24
50
|
end
|
|
@@ -50,34 +76,12 @@ module Merb
|
|
|
50
76
|
end
|
|
51
77
|
|
|
52
78
|
def initialize(o={})
|
|
53
|
-
self.config = :sendmail if config.nil?
|
|
79
|
+
self.config = {:sendmail_path => '/usr/sbin/sendmail'} if config.nil?
|
|
54
80
|
o[:rawhtml] = o.delete(:html)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
81
|
+
m = MailFactory.new()
|
|
82
|
+
o.each { |k,v| m.send "#{k}=", v }
|
|
83
|
+
@mail = m
|
|
58
84
|
end
|
|
59
85
|
|
|
60
86
|
end
|
|
61
87
|
end
|
|
62
|
-
|
|
63
|
-
=begin
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
Merb::Mailer.config = {
|
|
67
|
-
:host=>'smtp.yourserver.com',
|
|
68
|
-
:port=>'25',
|
|
69
|
-
:user=>'user',
|
|
70
|
-
:pass=>'pass',
|
|
71
|
-
:auth=>:plain # :plain, :login, or :cram_md5, default :plain
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
Merb::Mailer.delivery_method = :sendmail
|
|
75
|
-
|
|
76
|
-
m = Merb::Mailer.new :to => 'foo@bar.com',
|
|
77
|
-
:from => 'bar@foo.com',
|
|
78
|
-
:subject => 'Welcome to whatever!',
|
|
79
|
-
:body => partial(:sometemplate)
|
|
80
|
-
m.deliver!
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
=end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module Merb
|
|
2
2
|
|
|
3
|
-
module
|
|
3
|
+
module AuthenticationMixin
|
|
4
4
|
require 'base64'
|
|
5
5
|
|
|
6
6
|
def credentials
|
|
@@ -13,7 +13,7 @@ module Merb
|
|
|
13
13
|
|
|
14
14
|
def authenticated?
|
|
15
15
|
username, password = *credentials
|
|
16
|
-
username == Merb::Server.basic_auth[:username] and password == Merb::Server.basic_auth[:password]
|
|
16
|
+
username == Merb::Server.config[:basic_auth][:username] and password == Merb::Server.config[:basic_auth][:password]
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def basic_authentication
|
|
@@ -26,7 +26,7 @@ module Merb
|
|
|
26
26
|
set_status(401)
|
|
27
27
|
headers['Content-type'] = 'text/plain'
|
|
28
28
|
headers['Status'] = 'Unauthorized'
|
|
29
|
-
headers['WWW-Authenticate'] = "Basic realm=\"#{Merb::Server.basic_auth[:domain]}\""
|
|
29
|
+
headers['WWW-Authenticate'] = "Basic realm=\"#{Merb::Server.config[:basic_auth][:domain]}\""
|
|
30
30
|
return 'Unauthorized'
|
|
31
31
|
end
|
|
32
32
|
|
|
@@ -4,6 +4,15 @@ module Merb
|
|
|
4
4
|
# Returns a URL according to the defined route. Accepts the path and
|
|
5
5
|
# an options hash. The path specifies the route requested. The options
|
|
6
6
|
# hash fills in the dynamic parts of the route.
|
|
7
|
+
#
|
|
8
|
+
# Merb routes can often be one-way; if they use a regex to define
|
|
9
|
+
# the route, then knowing the controller & action won't be enough
|
|
10
|
+
# to reverse-generate the route. However, if you use the default
|
|
11
|
+
# /controller/action/id?query route, +default_route+ can generate
|
|
12
|
+
# it for you.
|
|
13
|
+
#
|
|
14
|
+
# For easy reverse-routes that use a Regex, be sure to also add
|
|
15
|
+
# a name to the route, so +url+ can find it.
|
|
7
16
|
#
|
|
8
17
|
# Nested resources such as:
|
|
9
18
|
# r.resources :blogposts do |post|
|
|
@@ -39,123 +48,129 @@ module Merb
|
|
|
39
48
|
# url(:edit_comment, @comment) # => /blogposts/1/comments/1/edit
|
|
40
49
|
# url(:custom_new_comment, :blogpost => @post)
|
|
41
50
|
#
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
buf = ""
|
|
56
|
-
content_length = env['CONTENT_LENGTH'].to_i
|
|
57
|
-
input = request
|
|
58
|
-
input.binmode if defined? input.binmode
|
|
59
|
-
boundary_size = boundary.size + EOL.size
|
|
60
|
-
bufsize = 16384
|
|
61
|
-
content_length -= boundary_size
|
|
62
|
-
status = input.read(boundary_size)
|
|
63
|
-
raise EOFError, "bad content body" unless status == boundary + EOL
|
|
64
|
-
rx = /(?:#{EOL})?#{Regexp.quote(boundary,'n')}(#{EOL}|--)/
|
|
65
|
-
loop {
|
|
66
|
-
head = nil
|
|
67
|
-
body = ''
|
|
68
|
-
filename = content_type = name = nil
|
|
69
|
-
read_size = 0
|
|
70
|
-
until head && buf =~ rx
|
|
71
|
-
i = buf.index("\r\n\r\n")
|
|
72
|
-
if( i == nil && read_size == 0 && content_length == 0 )
|
|
73
|
-
content_length = -1
|
|
74
|
-
break
|
|
75
|
-
end
|
|
76
|
-
if !head && i
|
|
77
|
-
head = buf.slice!(0, i+2) # First \r\n
|
|
78
|
-
buf.slice!(0, 2) # Second \r\n
|
|
79
|
-
filename = head[FILENAME_REGEX, 1]
|
|
80
|
-
content_type = head[CONTENT_TYPE_REGEX, 1]
|
|
81
|
-
name = head[NAME_REGEX, 1]
|
|
82
|
-
|
|
83
|
-
if filename && !filename.empty?
|
|
84
|
-
body = Tempfile.new(:Merb)
|
|
85
|
-
body.binmode if defined? body.binmode
|
|
86
|
-
end
|
|
87
|
-
next
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
# Save the read body part.
|
|
92
|
-
if head && (boundary_size+4 < buf.size)
|
|
93
|
-
body << buf.slice!(0, buf.size - (boundary_size+4))
|
|
94
|
-
end
|
|
51
|
+
# url(:page => 2) # => /posts/show/1?page=2
|
|
52
|
+
# url(:new_post, :page => 3) # => /posts/new?page=3
|
|
53
|
+
# url('/go/here', :page => 3) # => /go/here?page=3
|
|
54
|
+
#
|
|
55
|
+
# url(:controller => "welcome") # => /welcome
|
|
56
|
+
# url(:controller => "welcome", :action => "greet")
|
|
57
|
+
# # => /welcome/greet
|
|
58
|
+
#
|
|
59
|
+
def url(route_name = nil, new_params = {})
|
|
60
|
+
if route_name.is_a?(Hash)
|
|
61
|
+
new_params = route_name
|
|
62
|
+
route_name = nil
|
|
63
|
+
end
|
|
95
64
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
65
|
+
url = if new_params.respond_to?(:keys) &&
|
|
66
|
+
!(new_params.keys & [:controller, :action, :id]).empty?
|
|
67
|
+
url_from_default_route(new_params)
|
|
68
|
+
elsif route_name.nil? && !route.regexp?
|
|
69
|
+
url_from_route(route, new_params)
|
|
70
|
+
elsif route_name.nil?
|
|
71
|
+
request.path + (new_params.empty? ? "" : "?" + params_to_query_string(new_params))
|
|
72
|
+
elsif route_name.is_a?(Symbol)
|
|
73
|
+
url_from_route(route_name, new_params)
|
|
74
|
+
elsif route_name.is_a?(String)
|
|
75
|
+
route_name + (new_params.empty? ? "" : "?" + params_to_query_string(new_params))
|
|
76
|
+
else
|
|
77
|
+
raise "URL not generated: #{route_name.inspect}, #{new_params.inspect}"
|
|
103
78
|
end
|
|
79
|
+
url = MerbHandler.path_prefix + url if MerbHandler.path_prefix
|
|
80
|
+
url
|
|
81
|
+
end
|
|
104
82
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
body.rewind
|
|
115
|
-
data = {
|
|
116
|
-
:filename => File.basename(filename),
|
|
117
|
-
:content_type => content_type,
|
|
118
|
-
:tempfile => body,
|
|
119
|
-
:size => File.size(body)
|
|
120
|
-
}
|
|
121
|
-
else
|
|
122
|
-
data = body
|
|
83
|
+
def url_from_route(symbol, new_params = {})
|
|
84
|
+
route = symbol.is_a?(Symbol) ? Merb::Router.named_routes[symbol] : symbol
|
|
85
|
+
raise "URL could not be constructed. Route symbol not found: #{symbol.inspect}" unless route
|
|
86
|
+
path = route.generate(new_params, params)
|
|
87
|
+
keys = route.symbol_segments
|
|
88
|
+
if new_params.is_a? Hash
|
|
89
|
+
if ext = format_extension(new_params)
|
|
90
|
+
new_params.delete(:format)
|
|
91
|
+
path += "." + ext
|
|
123
92
|
end
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
93
|
+
extras = new_params.reject{ |k, v| keys.include?(k) }
|
|
94
|
+
path += "?" + params_to_query_string(extras) unless extras.empty?
|
|
95
|
+
end
|
|
96
|
+
path
|
|
128
97
|
end
|
|
129
98
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
99
|
+
# this is pretty ugly, but it works. TODO: make this cleaner
|
|
100
|
+
def url_from_default_route(new_params)
|
|
101
|
+
query_params = new_params.reject do |k,v|
|
|
102
|
+
[:controller, :action, :id, :format].include?(k)
|
|
103
|
+
end
|
|
104
|
+
controller = new_params[:controller] || params[:controller]
|
|
105
|
+
controller = params[:controller] if controller == :current
|
|
106
|
+
url = "/#{controller}"
|
|
107
|
+
if new_params[:action] || new_params[:id] ||
|
|
108
|
+
new_params[:format] || !query_params.empty?
|
|
109
|
+
action = new_params[:action] || params[:action]
|
|
110
|
+
url += "/#{action}"
|
|
111
|
+
end
|
|
112
|
+
if new_params[:id]
|
|
113
|
+
url += "/#{new_params[:id]}"
|
|
114
|
+
end
|
|
115
|
+
if format = new_params[:format]
|
|
116
|
+
format = params[:format] if format == :current
|
|
117
|
+
url += ".#{format}"
|
|
118
|
+
end
|
|
119
|
+
unless query_params.empty?
|
|
120
|
+
url += "?" + params_to_query_string(query_params)
|
|
121
|
+
end
|
|
122
|
+
url
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
protected
|
|
126
|
+
|
|
127
|
+
# Creates query string from params, supporting nested arrays and hashes.
|
|
128
|
+
# ==== Example
|
|
129
|
+
# params_to_query_string(:user => {:filter => {:name => "quux*"}, :order => ["name"]})
|
|
130
|
+
# # => user[filter][name]=quux%2A&user[order][]=name
|
|
131
|
+
def params_to_query_string(value, prefix = nil)
|
|
132
|
+
case value
|
|
133
|
+
when Array
|
|
134
|
+
value.map { |v|
|
|
135
|
+
params_to_query_string(v, "#{prefix}[]")
|
|
136
|
+
} * "&"
|
|
137
|
+
when Hash
|
|
138
|
+
value.map { |k, v|
|
|
139
|
+
params_to_query_string(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
|
|
140
|
+
} * "&"
|
|
140
141
|
else
|
|
141
|
-
|
|
142
|
+
"#{prefix}=#{escape(value)}"
|
|
142
143
|
end
|
|
143
|
-
parms
|
|
144
144
|
end
|
|
145
145
|
|
|
146
|
-
|
|
147
|
-
#
|
|
148
|
-
#
|
|
149
|
-
#
|
|
150
|
-
#
|
|
151
|
-
#
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
146
|
+
# +format_extension+ dictates when named route urls generated by #url
|
|
147
|
+
# will have a file-extension. It will return false or the format
|
|
148
|
+
# extension to append.
|
|
149
|
+
#
|
|
150
|
+
# url(:post, :id => post, :format => 'xml')
|
|
151
|
+
#
|
|
152
|
+
# generates:
|
|
153
|
+
#
|
|
154
|
+
# /posts/34.xml
|
|
155
|
+
#
|
|
156
|
+
# by default NON-HTML urls will be given an extension. it is posible
|
|
157
|
+
# to override this behaviour by setting +:use_format_in_urls+ in your
|
|
158
|
+
# server config (merb.yml) to either true/false
|
|
159
|
+
#
|
|
160
|
+
# +true+ would result in ALL urls (even html) being given extensions
|
|
161
|
+
# this is often desirable when you have many formats and dont
|
|
162
|
+
# wish to treat .html any differently from
|
|
163
|
+
# +false+ would result in NO urls being given extensions, and format
|
|
164
|
+
# gets treated just like any other param. leave it unset for
|
|
165
|
+
# the default behavior
|
|
166
|
+
#
|
|
167
|
+
def format_extension(new_params={})
|
|
168
|
+
use_format = Merb::Server.config[:use_format_in_urls]
|
|
169
|
+
if use_format.nil?
|
|
170
|
+
prms = params.merge(new_params)
|
|
171
|
+
use_format = prms[:format] != 'html' && prms[:format]
|
|
172
|
+
end
|
|
173
|
+
use_format
|
|
159
174
|
end
|
|
160
175
|
|
|
161
176
|
# render using chunked encoding
|
|
@@ -231,10 +246,8 @@ module Merb
|
|
|
231
246
|
# stream_file( { :filename => file_name,
|
|
232
247
|
# :type => content_type,
|
|
233
248
|
# :content_length => content_length }) do
|
|
234
|
-
# response.send_status(opts[:content_length])
|
|
235
|
-
# response.send_header
|
|
236
249
|
# AWS::S3::S3Object.stream(user.folder_name + "-" + user_file.unique_id, bucket_name) do |chunk|
|
|
237
|
-
#
|
|
250
|
+
# response.write chunk
|
|
238
251
|
# end
|
|
239
252
|
# end
|
|
240
253
|
def stream_file(opts={}, &stream)
|
|
@@ -247,6 +260,8 @@ module Merb
|
|
|
247
260
|
'Content-Transfer-Encoding' => 'binary',
|
|
248
261
|
'CONTENT-LENGTH' => opts[:content_length]
|
|
249
262
|
)
|
|
263
|
+
response.send_status(opts[:content_length])
|
|
264
|
+
response.send_header
|
|
250
265
|
stream
|
|
251
266
|
end
|
|
252
267
|
|
|
@@ -261,8 +276,12 @@ module Merb
|
|
|
261
276
|
|
|
262
277
|
# Sets a cookie to be included in the response.
|
|
263
278
|
def set_cookie(name, value, expires)
|
|
264
|
-
(headers['Set-Cookie'] ||='') <<
|
|
265
|
-
|
|
279
|
+
(headers['Set-Cookie'] ||='') << (Merb::Const::SET_COOKIE % [
|
|
280
|
+
name.to_s,
|
|
281
|
+
escape(value.to_s),
|
|
282
|
+
# Cookie expiration time must be GMT. See RFC 2109
|
|
283
|
+
expires.gmtime.strftime(Merb::Const::COOKIE_EXPIRATION_FORMAT)
|
|
284
|
+
])
|
|
266
285
|
end
|
|
267
286
|
|
|
268
287
|
# Marks a cookie as deleted. The cookie is given an expires stamp in
|