doozer 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/doozer.gemspec +4 -2
- data/lib/doozer.rb +2 -1
- data/lib/doozer/app.rb +37 -3
- data/lib/doozer/controller.rb +6 -7
- data/lib/doozer/lib.rb +12 -0
- data/lib/doozer/mailer.rb +263 -0
- data/lib/doozer/mailer_partial.rb +74 -0
- data/lib/doozer/partial.rb +1 -0
- data/lib/doozer/route.rb +4 -1
- data/lib/doozer/scripts/task.rb +29 -5
- data/lib/doozer/version.rb +1 -1
- data/lib/doozer/view_helpers.rb +18 -0
- data/lib/generator/generator.rb +67 -2
- metadata +4 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.4.
|
1
|
+
0.4.1
|
data/doozer.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{doozer}
|
8
|
-
s.version = "0.4.
|
8
|
+
s.version = "0.4.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["grippy"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2010-01-03}
|
13
13
|
s.default_executable = %q{doozer}
|
14
14
|
s.description = %q{This GEM provides a small, barebones framework for creating MVC Rack applications.}
|
15
15
|
s.email = %q{gmelton@whorde.com}
|
@@ -41,6 +41,8 @@ Gem::Specification.new do |s|
|
|
41
41
|
"lib/doozer/initializer.rb",
|
42
42
|
"lib/doozer/lib.rb",
|
43
43
|
"lib/doozer/logger.rb",
|
44
|
+
"lib/doozer/mailer.rb",
|
45
|
+
"lib/doozer/mailer_partial.rb",
|
44
46
|
"lib/doozer/middleware.rb",
|
45
47
|
"lib/doozer/orm/active_record.rb",
|
46
48
|
"lib/doozer/orm/data_mapper.rb",
|
data/lib/doozer.rb
CHANGED
@@ -27,10 +27,11 @@ module Doozer
|
|
27
27
|
autoload :Route, "doozer/exceptions"
|
28
28
|
end
|
29
29
|
|
30
|
+
autoload :Mailer, "doozer/mailer"
|
31
|
+
autoload :MailerPartial, "doozer/mailer_partial"
|
30
32
|
autoload :Middleware, "doozer/middleware"
|
31
33
|
autoload :MiddlewareBeforeDozerApp, "doozer/middleware"
|
32
34
|
|
33
|
-
|
34
35
|
autoload :Task, "doozer/task"
|
35
36
|
autoload :ViewHelpers, "doozer/view_helpers"
|
36
37
|
autoload :Version, "doozer/version"
|
data/lib/doozer/app.rb
CHANGED
@@ -64,10 +64,8 @@ module Doozer
|
|
64
64
|
#execution_time(nil,:end)
|
65
65
|
r.set_cookie('flash',{:value=>nil, :path=>'/'})
|
66
66
|
r.set_cookie('session',{:value=>controller.session_to_cookie(), :path=>'/'})
|
67
|
-
|
68
67
|
r = controller.write_response_cookies(r)
|
69
68
|
|
70
|
-
|
71
69
|
# finalize the request
|
72
70
|
controller.finished!
|
73
71
|
controller = nil
|
@@ -133,6 +131,7 @@ module Doozer
|
|
133
131
|
load_models
|
134
132
|
puts "=> Caching files"
|
135
133
|
@@controllers = {}
|
134
|
+
@@mailers = {}
|
136
135
|
@@layouts={}
|
137
136
|
@@views={}
|
138
137
|
@@errors={}
|
@@ -224,6 +223,39 @@ module Doozer
|
|
224
223
|
end
|
225
224
|
}
|
226
225
|
}
|
226
|
+
|
227
|
+
mailer_files = Dir.glob(File.join(app_path,'app/mailers/*_mailer.rb'))
|
228
|
+
mailer_files.each { |f|
|
229
|
+
require f
|
230
|
+
key = f.split("mailers/")[1].split("_mailer.rb")[0]
|
231
|
+
if key.index("_")
|
232
|
+
value = key.split('_').each{ | k | k.capitalize! }.join('')
|
233
|
+
else
|
234
|
+
value = key.capitalize
|
235
|
+
end
|
236
|
+
klass_name = "#{value}Mailer"
|
237
|
+
@@mailers[key.to_sym] = klass_name
|
238
|
+
# puts "cache mailer: #{key.to_sym}"
|
239
|
+
# importing view helpers into controller
|
240
|
+
mailer_klass = Object.const_get(klass_name)
|
241
|
+
# automatically ads the application helper to the class
|
242
|
+
mailer_klass.include_view_helper('application_helper')
|
243
|
+
mailer_klass.include_view_helpers
|
244
|
+
}
|
245
|
+
|
246
|
+
mail_key = :mail
|
247
|
+
mailer_files = Dir.glob(File.join(app_path,"app/views/#{mail_key.to_s}/*.erb"))
|
248
|
+
mailer_files.each { | f |
|
249
|
+
#!!!don't cache partials here!!!
|
250
|
+
view = f.split("#{mail_key.to_s}/")[1].split(".erb")[0].gsub(/\./,'_')
|
251
|
+
if not /^_/.match( view )
|
252
|
+
# puts "cache view: #{view}"
|
253
|
+
results = []
|
254
|
+
File.new(f, "r").each { |line| results << line }
|
255
|
+
@@views[mail_key] = {} if @@views[mail_key].nil?
|
256
|
+
@@views[mail_key][view.to_sym] = ERB.new(results.join(""))
|
257
|
+
end
|
258
|
+
}
|
227
259
|
end
|
228
260
|
|
229
261
|
# Load application routes
|
@@ -256,22 +288,24 @@ module Doozer
|
|
256
288
|
watcher.addDirectory( app_path + '/static/', "*.*")
|
257
289
|
watcher.addDirectory( app_path + '/static/', "**/**/*")
|
258
290
|
|
259
|
-
|
260
291
|
watcher.sleepTime = 1
|
261
292
|
watcher.start { |status, file|
|
262
293
|
if(status == FileSystemWatcher::CREATED) then
|
263
294
|
puts "created: #{file}"
|
264
295
|
load_files
|
265
296
|
Doozer::Partial.clear_loaded_partials
|
297
|
+
Doozer::MailerPartial.clear_loaded_partials
|
266
298
|
elsif(status == FileSystemWatcher::MODIFIED) then
|
267
299
|
puts "modified: #{file}"
|
268
300
|
load_files
|
269
301
|
Doozer::Partial.clear_loaded_partials
|
302
|
+
Doozer::MailerPartial.clear_loaded_partials
|
270
303
|
Doozer::Configs.clear_static_files
|
271
304
|
elsif(status == FileSystemWatcher::DELETED) then
|
272
305
|
puts "deleted: #{file}"
|
273
306
|
load_files
|
274
307
|
Doozer::Partial.clear_loaded_partials
|
308
|
+
Doozer::MailerPartial.clear_loaded_partials
|
275
309
|
Doozer::Configs.clear_static_files
|
276
310
|
end
|
277
311
|
}
|
data/lib/doozer/controller.rb
CHANGED
@@ -28,17 +28,17 @@ module Doozer
|
|
28
28
|
#
|
29
29
|
# To save cookies: All hash keys must be symbols and value strings.
|
30
30
|
# Reserved hash keys per cookie:
|
31
|
-
#
|
32
|
-
#
|
31
|
+
# :expires - Time.now + some duration. This default to 30 days if not defined
|
32
|
+
# :path - The path for the cookie. This defaults to '/' if not defined
|
33
33
|
#
|
34
34
|
# Example:
|
35
|
-
#
|
35
|
+
# @cookies[:yum_yum]={:a=>'123',
|
36
36
|
# :b=>'abc',
|
37
37
|
# :expires=>Time.now + 3.day
|
38
38
|
# :path=>'/path'}
|
39
39
|
# To delete a cookie, set it to nil or delete it from @cookies
|
40
40
|
#
|
41
|
-
#
|
41
|
+
# @cookies[:testing]=nil
|
42
42
|
attr_accessor :cookies
|
43
43
|
# @session variable containing a hash of strings which are persisted in the session cookie until the browser session expires.
|
44
44
|
attr_accessor :session
|
@@ -124,8 +124,8 @@ module Doozer
|
|
124
124
|
|
125
125
|
#turn extra params into instance variables...
|
126
126
|
args[:extra_params].each { |key, value| self.instance_variable_set("@#{key}".to_sym, value)}
|
127
|
-
|
128
|
-
|
127
|
+
puts " Params: #{@request.params.inspect}" if not @request.params.nil?
|
128
|
+
puts " Extra params: #{args[:extra_params].inspect}" if not args[:extra_params].nil?
|
129
129
|
end
|
130
130
|
|
131
131
|
# Renders an action with any of the following overridable parameters:
|
@@ -169,7 +169,6 @@ module Doozer
|
|
169
169
|
change_layout(args[:layout]) if args[:layout]
|
170
170
|
change_view(args[:view]) if args[:view]
|
171
171
|
change_view(ERB.new(args[:text])) if args[:text]
|
172
|
-
|
173
172
|
end
|
174
173
|
|
175
174
|
# This method is called from the appserver controller handler.
|
data/lib/doozer/lib.rb
CHANGED
@@ -16,6 +16,17 @@ module Doozer
|
|
16
16
|
end
|
17
17
|
return klass
|
18
18
|
end
|
19
|
+
|
20
|
+
#Return an underscored string from a ClassName string.
|
21
|
+
# example: input "ExampleClass" > "example_class"
|
22
|
+
def self.underscore(s)
|
23
|
+
while true do
|
24
|
+
m = /[A-Z]/.match(s)
|
25
|
+
break if m.to_s == ''
|
26
|
+
s.gsub!(/#{m.to_s}/,"_#{m.to_s.downcase}")
|
27
|
+
end
|
28
|
+
s.gsub(/^_/,'') # move the first underscore
|
29
|
+
end
|
19
30
|
|
20
31
|
#Returns a one-level deep folder/file structure and preservers underscores for filename.
|
21
32
|
# example: input "folder_some_file_name" > "folder/some_file_name"
|
@@ -28,5 +39,6 @@ module Doozer
|
|
28
39
|
end
|
29
40
|
s
|
30
41
|
end
|
42
|
+
|
31
43
|
end
|
32
44
|
end
|
@@ -0,0 +1,263 @@
|
|
1
|
+
# load gems
|
2
|
+
%w(rack erb).each { |dep| require dep }
|
3
|
+
|
4
|
+
module Doozer
|
5
|
+
|
6
|
+
# The Mailer class operates in many ways like a Controller.
|
7
|
+
#
|
8
|
+
# Mailers have access to all ViewHelpers methods.
|
9
|
+
#
|
10
|
+
# Mailers can also load partials.
|
11
|
+
#
|
12
|
+
# Limitations:
|
13
|
+
# - The current send implemntation must be overridden by your application.
|
14
|
+
# - Create multipart messages but only handles html content types. No text or attachment capabilities.
|
15
|
+
#
|
16
|
+
class Mailer
|
17
|
+
|
18
|
+
# @controller variable containing the name of the mailer
|
19
|
+
attr_accessor :controller
|
20
|
+
# @action variable containing the name of the mailer action to deliver
|
21
|
+
attr_accessor :action
|
22
|
+
# @from variable which contains either a string or list of senders. Example: ['some@email.com', 'Some guy <some@guy.com>']
|
23
|
+
attr_accessor :from
|
24
|
+
# @to variable which contains either a string or list of recipients. Example: ['some@email.com', 'Some guy <some@guy.com>']
|
25
|
+
attr_accessor :to
|
26
|
+
# @cc variable which contains either a string or list of recipients which should be cc'd on the email. Example: ['some@email.com', 'Some guy <some@guy.com>']
|
27
|
+
attr_accessor :cc
|
28
|
+
# @bcc variable which contains either a string or list of recipients which should be bcc'd on the email. Example: ['some@email.com', 'Some guy <some@guy.com>']
|
29
|
+
attr_accessor :bcc
|
30
|
+
# @subject variable which contains the subject of the mail.
|
31
|
+
attr_accessor :subject
|
32
|
+
# @date variable which contains the date of the email. Must be a Time object. Defaults to Time.now.
|
33
|
+
attr_accessor :date
|
34
|
+
# @envelope variable which holds the TMail object for the mail.
|
35
|
+
attr_accessor :envelope
|
36
|
+
# @message_id variable which holds the unique message identifier of the mail.
|
37
|
+
attr_accessor :message_id
|
38
|
+
# @charset variable which holds the character set of the mail. Defaults to "ISO-8859-1"
|
39
|
+
attr_accessor :charset
|
40
|
+
# @render_args variable containing a hash of values to use while rendering the message
|
41
|
+
attr_accessor :render_args
|
42
|
+
|
43
|
+
include Doozer::Util::Logger
|
44
|
+
include Doozer::ViewHelpers
|
45
|
+
|
46
|
+
self.class_inheritable_accessor :require_view_helpers, :view_dir, :layout
|
47
|
+
|
48
|
+
# Array of helper methods to include inside the view.
|
49
|
+
#
|
50
|
+
# Example: self.require_view_helpers=[:application, :helper_1]
|
51
|
+
self.require_view_helpers=[]
|
52
|
+
|
53
|
+
# Default directory where the views should be looked up for the mail.
|
54
|
+
#
|
55
|
+
self.view_dir = 'mail'
|
56
|
+
|
57
|
+
# Default mail layout symbol to use for the mail.
|
58
|
+
#
|
59
|
+
self.layout = :default_mail
|
60
|
+
|
61
|
+
# Create a new Mailer object
|
62
|
+
# action: a symbol of the action to call
|
63
|
+
# args: optional list of arguments
|
64
|
+
#
|
65
|
+
def initialize(action, args={})
|
66
|
+
@controller = self.class.to_s
|
67
|
+
@action = action
|
68
|
+
|
69
|
+
#holds all variables for template binding
|
70
|
+
@view={}
|
71
|
+
@to = args[:to]
|
72
|
+
@from = args[:from]
|
73
|
+
@cc = args[:cc]
|
74
|
+
@bcc = args[:bcc]
|
75
|
+
@subject = args[:subject] || ''
|
76
|
+
@date = args[:date] || Time.now()
|
77
|
+
@charset = args[:charset] || "ISO-8859-1"
|
78
|
+
|
79
|
+
@message_id = "#{DateTime.now().strftime('%Y%m%d%H%M%S')}.#{(rand(1000) * 1024).to_s}"
|
80
|
+
@envelope = nil
|
81
|
+
@render_args = {:layout=>nil, :view=>nil, :text=>nil}
|
82
|
+
render({
|
83
|
+
:view=>args[:view] || action,
|
84
|
+
:layout=>args[:layout] || mailer_class.layout,
|
85
|
+
:text=>args[:text]
|
86
|
+
})
|
87
|
+
|
88
|
+
# turn the rest of the args into instance variables
|
89
|
+
args.delete(:view) if args[:view]
|
90
|
+
args.delete(:layout) if args[:delete]
|
91
|
+
args.delete(:text) if args[:text]
|
92
|
+
args.each { |key, value| self.instance_variable_set("@#{key}".to_sym, value)}
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
# Erb binding
|
97
|
+
def bind
|
98
|
+
@erb.result(binding)
|
99
|
+
end
|
100
|
+
|
101
|
+
# This method is called prior to #send and handles the creation of envelope.
|
102
|
+
def package
|
103
|
+
raise "Missing from address" if self.from.nil?
|
104
|
+
|
105
|
+
begin
|
106
|
+
@envelope = TMail::Mail.new()
|
107
|
+
rescue => e
|
108
|
+
begin
|
109
|
+
require 'tmail'
|
110
|
+
@envelope = TMail::Mail.new()
|
111
|
+
rescue MissingSourceFile, Gem::LoadError => e
|
112
|
+
logger.error("TMail Gem wasn't found. Please install if you want to send mail.")
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# http://tmail.rubyforge.org/rdoc/index.html
|
117
|
+
@envelope.mime_version = "1.0"
|
118
|
+
@envelope.charset = self.charset
|
119
|
+
@envelope.message_id = self.message_id
|
120
|
+
@envelope.from = [self.from]
|
121
|
+
@envelope.to = [self.to] if self.to
|
122
|
+
@envelope.cc = [self.cc] if self.cc
|
123
|
+
@envelope.bcc = [self.bcc] if self.bcc
|
124
|
+
@envelope.date = self.date
|
125
|
+
@envelope.subject = self.subject
|
126
|
+
|
127
|
+
html = TMail::Mail.new()
|
128
|
+
html.body = self.render_result
|
129
|
+
html.set_content_type('text','html')
|
130
|
+
|
131
|
+
@envelope.parts << html
|
132
|
+
@envelope.set_content_type('multipart', 'mixed') # needs to be set last or throws an error
|
133
|
+
end
|
134
|
+
|
135
|
+
# Call this method to receive the list of only :to addresses. Use this when sending through SMTP.
|
136
|
+
def to_address
|
137
|
+
out = []; @envelope.to_addrs.each{|a| out.push(a.address)}
|
138
|
+
return out
|
139
|
+
end
|
140
|
+
|
141
|
+
# Call this method to receive the list of only :from addresses. Use this when sending through SMTP.
|
142
|
+
def from_address
|
143
|
+
out = []; @envelope.from_addrs.each{|a| out.push(a.address)}
|
144
|
+
return out
|
145
|
+
end
|
146
|
+
|
147
|
+
# Helper method for initializing partials from views.
|
148
|
+
def partial(file=nil, locals={})
|
149
|
+
locals[:view_dir] = mailer_class.view_dir
|
150
|
+
Doozer::MailerPartial.partial(file, locals)
|
151
|
+
end
|
152
|
+
|
153
|
+
# Renders an action with any of the following overridable parameters:
|
154
|
+
#
|
155
|
+
# args={
|
156
|
+
# :view=>Symbol, String or ERB,
|
157
|
+
# :layout=>Symbol,
|
158
|
+
# :text=>'this is the text to render'
|
159
|
+
# }
|
160
|
+
#
|
161
|
+
def render(args={})
|
162
|
+
change_layout(args[:layout]) if args[:layout]
|
163
|
+
change_view(args[:view]) if args[:view]
|
164
|
+
change_view(ERB.new(args[:text])) if args[:text]
|
165
|
+
end
|
166
|
+
|
167
|
+
# This method creates the html part of the mail.
|
168
|
+
def render_result
|
169
|
+
layout = @render_args[:layout]
|
170
|
+
view = @render_args[:view]
|
171
|
+
if layout.kind_of? Symbol # this handles the layout(:none)
|
172
|
+
view.result(binding)
|
173
|
+
else
|
174
|
+
@view[:timestamp] = "<!-- rendered: #{Time.now()} / env: #{rack_env} -->"
|
175
|
+
@view[:body] = view.result(binding)
|
176
|
+
# layout = @layout if layout.nil? # this handles the layout(:some_other_layout) case for formats
|
177
|
+
layout.result(binding)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
# Sequel ORM db connection
|
182
|
+
def db
|
183
|
+
Doozer::Configs.db_conn
|
184
|
+
end
|
185
|
+
|
186
|
+
# Global teardown called at the end of every request. Hooks ORM.teardown
|
187
|
+
def finished!
|
188
|
+
Doozer::ORM.after_request if Doozer::Configs.orm_loaded
|
189
|
+
end
|
190
|
+
|
191
|
+
# Returns the Mailer object
|
192
|
+
def mailer_class
|
193
|
+
Object.const_get(self.class.to_s)
|
194
|
+
end
|
195
|
+
|
196
|
+
# Include additional view helpers declared for the class.
|
197
|
+
#
|
198
|
+
# This method automatically appends '_helper' to each required helper symbol
|
199
|
+
def self.include_view_helpers
|
200
|
+
# importing view helpers into controller
|
201
|
+
self.require_view_helpers.each { | sym |
|
202
|
+
self.include_view_helper("#{sym.to_s}_helper")
|
203
|
+
}
|
204
|
+
end
|
205
|
+
|
206
|
+
# Include the app/helpers file_name. Expects helper as a string.
|
207
|
+
#
|
208
|
+
# You must pass the full file name if you use this method.
|
209
|
+
#
|
210
|
+
# Example: self.include_view_helper('application_helper')
|
211
|
+
def self.include_view_helper(helper)
|
212
|
+
# importing view helpers into controller
|
213
|
+
include Object.const_get(Doozer::Lib.classify("#{helper}"))
|
214
|
+
end
|
215
|
+
|
216
|
+
# Call this method to deliver a Mailer#action
|
217
|
+
#
|
218
|
+
# Arguments
|
219
|
+
# - action: The action of the mailer to call passed as a symbol.
|
220
|
+
# - args: The mail arguments to initialize the email with.
|
221
|
+
# All remaining arguments are turned into instance variables and bound to the view.
|
222
|
+
|
223
|
+
# Note: The send mechanism is empty and must be overriden in the calling application.
|
224
|
+
def self.deliver(action, args={})
|
225
|
+
# puts "deliver.."
|
226
|
+
mailer = self.new(action, args)
|
227
|
+
mailer.method(action).call()
|
228
|
+
mailer.finished! #close the db connections
|
229
|
+
mailer.package
|
230
|
+
send(mailer)
|
231
|
+
end
|
232
|
+
|
233
|
+
# The send method must be overriden by the calling class.
|
234
|
+
#
|
235
|
+
# => The mailer object passed to this mehod of the instance of the mailer.
|
236
|
+
# => You can access the mailer.envelope.encoded (tmail) object which handles all the encoding.
|
237
|
+
def self.send(mailer); end
|
238
|
+
|
239
|
+
private
|
240
|
+
def change_layout(sym)
|
241
|
+
if sym == :none
|
242
|
+
layout=sym
|
243
|
+
else
|
244
|
+
#this needs to look up the layout and reset layout to this erb template
|
245
|
+
lay = Doozer::App.layouts[sym]
|
246
|
+
raise "Can't find layout for #{sym}" if lay.nil?
|
247
|
+
layout = lay
|
248
|
+
end
|
249
|
+
@render_args[:layout] = layout
|
250
|
+
end
|
251
|
+
|
252
|
+
def change_view(args)
|
253
|
+
if args.kind_of? Symbol
|
254
|
+
# implies we're using the same controller as the current controller with a view name of :view_name
|
255
|
+
view = Doozer::App.views[mailer_class.view_dir.to_sym]["#{args.to_s}_html".to_sym]
|
256
|
+
elsif args.kind_of? ERB
|
257
|
+
view = args
|
258
|
+
end
|
259
|
+
view = ERB.new("Missing view for goes here") if view.nil?
|
260
|
+
@render_args[:view] = view
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Doozer
|
2
|
+
# The MailerPartial is really similar to Doozer::Partial.
|
3
|
+
class MailerPartial
|
4
|
+
attr_accessor :erb
|
5
|
+
|
6
|
+
include ERB::Util
|
7
|
+
include Doozer::Util::Logger
|
8
|
+
include Doozer::ViewHelpers
|
9
|
+
|
10
|
+
@@partials={}
|
11
|
+
|
12
|
+
def initialize(erb, locals)
|
13
|
+
@erb = erb
|
14
|
+
if locals.kind_of? Hash
|
15
|
+
locals.each_pair {|key, value|
|
16
|
+
#p "#{key}:#{value}"
|
17
|
+
self.instance_variable_set("@#{key}".to_sym, value) # :@a, value
|
18
|
+
}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def bind
|
23
|
+
@erb.result(binding)
|
24
|
+
end
|
25
|
+
|
26
|
+
# This class method lazy loads and caches the erb templates of the requested partials
|
27
|
+
def self.partial(file=nil, locals={})
|
28
|
+
#p "Class method: Doozer::Partial#partial"
|
29
|
+
dir = locals[:view_dir]
|
30
|
+
if file.index("/").nil?
|
31
|
+
name = "#{dir}/_#{file}"
|
32
|
+
else
|
33
|
+
name = "#{file.gsub(/\//,'/_')}"
|
34
|
+
end
|
35
|
+
load_partial(name) if @@partials[name].nil?
|
36
|
+
erb = @@partials[name]
|
37
|
+
if erb
|
38
|
+
partial = Doozer::MailerPartial.new(erb, locals)
|
39
|
+
partial.bind()
|
40
|
+
else
|
41
|
+
puts "ERROR => no partial exists for #{file}\n"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def partial(file=nil, locals={})
|
46
|
+
locals[:view_dir] = @view_dir if not @view_dir.nil?
|
47
|
+
Doozer::MailerPartial.partial(file, locals)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Load and cache partial ERB template with the given file_name.
|
51
|
+
def self.load_partial(name)
|
52
|
+
|
53
|
+
file = File.join(Doozer::Configs.app_path,"app/views/#{name}.html.erb")
|
54
|
+
results = []
|
55
|
+
begin
|
56
|
+
File.new(file, "r").each { |line| results << line }
|
57
|
+
@@partials[name] = ERB.new(results.join(""))
|
58
|
+
rescue
|
59
|
+
puts "ERROR => sorry couldn't load partial #{name} (#{file})"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Class methods for clearing all cached partials. Mainly a dispatcher for the file watcher to pick up new changes without having to restart the appserver in development mode.
|
64
|
+
def self.clear_loaded_partials
|
65
|
+
@@partials = {}
|
66
|
+
end
|
67
|
+
|
68
|
+
# Class method for including a view helper.
|
69
|
+
def self.include_view_helper(helper)
|
70
|
+
m = Doozer::Lib.classify(helper)
|
71
|
+
include Object.const_get(m)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/lib/doozer/partial.rb
CHANGED
data/lib/doozer/route.rb
CHANGED
@@ -300,7 +300,9 @@ module Doozer
|
|
300
300
|
return hashish
|
301
301
|
end
|
302
302
|
|
303
|
-
# Parses route tokens and returns a helper method which evntually module_eval'd into Doozer::ViewHelpers
|
303
|
+
# Parses route tokens and returns a helper method which evntually is module_eval'd into Doozer::ViewHelpers
|
304
|
+
#
|
305
|
+
# => creates helper methods for route_name_url (relative) and route_name_aurl (absolute)
|
304
306
|
def url_helper_method
|
305
307
|
method_name=[@name]
|
306
308
|
# method_name.push(@format) if @format != :html
|
@@ -334,6 +336,7 @@ module Doozer
|
|
334
336
|
end
|
335
337
|
url_method.push("})")
|
336
338
|
method = """def #{method_name.join('_')}#{signature.join('')}; #{url_method} end"""
|
339
|
+
method += "\n#{method.gsub(/url\(/, 'aurl(')}"
|
337
340
|
return method
|
338
341
|
end
|
339
342
|
|
data/lib/doozer/scripts/task.rb
CHANGED
@@ -31,24 +31,29 @@ require 'optparse'
|
|
31
31
|
@task = nil
|
32
32
|
@args = nil
|
33
33
|
@help = false
|
34
|
+
@daemonize = false
|
34
35
|
|
35
36
|
opts = OptionParser.new("", 24, ' ') { |opts|
|
36
37
|
opts.banner = "Usage: script/task -T task_name -E (default: development || deployment || test)"
|
37
38
|
opts.separator ""
|
38
39
|
opts.separator "Command options:"
|
39
|
-
|
40
|
+
|
40
41
|
opts.on("-E", "--env ENVIRONMENT", "use ENVIRONMENT for defaults (default: development || deployment || test)") { |e|
|
41
42
|
@env = e.to_sym
|
42
43
|
}
|
43
|
-
|
44
|
+
|
44
45
|
opts.on("-T", "--task TASK", "run task_name") { | t |
|
45
46
|
@task = t
|
46
47
|
}
|
47
|
-
|
48
|
+
|
48
49
|
opts.on("-A", "--args ARGS", "args") { |a|
|
49
50
|
@args = eval(a) if a and a.length
|
50
51
|
}
|
51
|
-
|
52
|
+
|
53
|
+
opts.on("-D", "--daemonize") {
|
54
|
+
@daemonize = true
|
55
|
+
}
|
56
|
+
|
52
57
|
opts.on("-h", "--help", "Show this message") do
|
53
58
|
@help = true
|
54
59
|
end
|
@@ -68,8 +73,27 @@ if @task
|
|
68
73
|
raise "Can't find this task file #{@task}" if file.nil?
|
69
74
|
task, file_name = file_to_task(file, @args)
|
70
75
|
if not @help
|
71
|
-
puts "Running #{@task}
|
76
|
+
puts "=> Running #{@task}"
|
72
77
|
Doozer::Initializer.boot(@env)
|
78
|
+
if @daemonize
|
79
|
+
puts "=> Daemonize"
|
80
|
+
log_file = "#{APP_PATH}/log/task/#{@task}.log"
|
81
|
+
error_file = "#{APP_PATH}/log/task/#{@task}_errors.log"
|
82
|
+
puts "=> Writing to log: #{log_file}"
|
83
|
+
exit if fork
|
84
|
+
Process.setsid
|
85
|
+
exit if fork
|
86
|
+
# Dir.chdir "/"
|
87
|
+
File.umask 0000
|
88
|
+
file = File.open(log_file, File::RDWR|File::APPEND|File::CREAT, 0600)
|
89
|
+
STDIN.reopen(file)
|
90
|
+
STDOUT.reopen(file)
|
91
|
+
file = File.open(error_file, File::RDWR|File::APPEND|File::CREAT, 0600)
|
92
|
+
STDERR.reopen(file)
|
93
|
+
# STDIN.reopen "/dev/null"
|
94
|
+
# STDOUT.reopen "/dev/null", "a"
|
95
|
+
# STDERR.reopen "/dev/null", "a"
|
96
|
+
end
|
73
97
|
task.run
|
74
98
|
else
|
75
99
|
puts ""
|
data/lib/doozer/version.rb
CHANGED
data/lib/doozer/view_helpers.rb
CHANGED
@@ -58,6 +58,13 @@ module Doozer
|
|
58
58
|
return url
|
59
59
|
end
|
60
60
|
|
61
|
+
# A wrapper method for #url which automatically sets the base_url to the one configured for the application
|
62
|
+
#
|
63
|
+
def aurl(opt)
|
64
|
+
opt[:base_url] = base_url if opt.kind_of? Hash
|
65
|
+
url(opt)
|
66
|
+
end
|
67
|
+
|
61
68
|
# Creates an html anchor tag.
|
62
69
|
#
|
63
70
|
# text - the text of the anchor tag
|
@@ -69,6 +76,17 @@ module Doozer
|
|
69
76
|
"<a href=\"#{url(opt)}\"#{hash_to_props(prop)}>#{text}</a>"
|
70
77
|
end
|
71
78
|
|
79
|
+
# Creates an html anchor tag with an absolute url.
|
80
|
+
#
|
81
|
+
# text - the text of the anchor tag
|
82
|
+
#
|
83
|
+
# opt - a hash of options which are passed to url(opt)
|
84
|
+
#
|
85
|
+
# prop - a hash of anchor tag attributes to add to the link
|
86
|
+
def alink(text='', opt={}, prop={})
|
87
|
+
"<a href=\"#{aurl(opt)}\"#{hash_to_props(prop)}>#{text}</a>"
|
88
|
+
end
|
89
|
+
|
72
90
|
# Creates an img tag.
|
73
91
|
#
|
74
92
|
# path - the src of the image tag
|
data/lib/generator/generator.rb
CHANGED
@@ -63,7 +63,14 @@ module Doozer
|
|
63
63
|
task(name.downcase)
|
64
64
|
else
|
65
65
|
help?(:help, :task)
|
66
|
-
end
|
66
|
+
end
|
67
|
+
when :mailer, :"-E"
|
68
|
+
if args.length == 3
|
69
|
+
name = args[2]
|
70
|
+
mailer(name.downcase)
|
71
|
+
else
|
72
|
+
help?(:help, :mailer)
|
73
|
+
end
|
67
74
|
else
|
68
75
|
help_all
|
69
76
|
end
|
@@ -85,6 +92,7 @@ module Doozer
|
|
85
92
|
help(:helper)
|
86
93
|
help(:migrate)
|
87
94
|
help(:task)
|
95
|
+
help(:mailer)
|
88
96
|
end
|
89
97
|
|
90
98
|
def self.controller(name)
|
@@ -308,6 +316,42 @@ end
|
|
308
316
|
end
|
309
317
|
end
|
310
318
|
|
319
|
+
def self.mailer(name)
|
320
|
+
return if help?(name, :mailer)
|
321
|
+
path = "#{APP_PATH}/app/mailers"
|
322
|
+
if not File.exist?(path)
|
323
|
+
puts "Creating directory for mailers..."
|
324
|
+
system("mkdir #{path}")
|
325
|
+
end
|
326
|
+
|
327
|
+
puts "Generating file..."
|
328
|
+
path = "#{path}/#{name}_mailer.rb"
|
329
|
+
if not File.exist?(path)
|
330
|
+
puts "=> Generating mailer: #{path}"
|
331
|
+
file = File.new(path, "w+")
|
332
|
+
if file
|
333
|
+
klass = Doozer::Lib.classify(name)
|
334
|
+
template = """
|
335
|
+
#= #{klass}Mailer
|
336
|
+
class #{klass}Mailer < Doozer::Mailer
|
337
|
+
\"\"\"Default configuration options for mailers
|
338
|
+
self.require_view_helpers=[]
|
339
|
+
self.view_dir = 'mail'
|
340
|
+
self.layout = :default_mail
|
341
|
+
\"\"\"
|
342
|
+
end
|
343
|
+
"""
|
344
|
+
file.syswrite(template)
|
345
|
+
else
|
346
|
+
puts "ERROR => Unable to open file!"
|
347
|
+
end
|
348
|
+
else
|
349
|
+
puts "Skipping: #{path} (already exists)"
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
|
354
|
+
|
311
355
|
def self.help?(name, action=nil)
|
312
356
|
if name.to_sym == :"-h" or name == :help
|
313
357
|
puts "Commands:"
|
@@ -355,10 +399,15 @@ Migration - Create a migration file in project/db with the next available versio
|
|
355
399
|
Task - Create a task file in project/tasks with the class name of TaskName.
|
356
400
|
Command: doozer generate (task or -T) task_name
|
357
401
|
Example: doozer generate task task_name\n"""
|
402
|
+
when :mailer, :mail :"-E"
|
403
|
+
h += """
|
404
|
+
Mailer - Create a mailer file in project/app/mailers with the class name of NameMailer. '_mailer' is automatically appended to the name.
|
405
|
+
Command: doozer generate (mailer or -E) mailer_name
|
406
|
+
Example: doozer generate mailer mailer_name\n"""
|
358
407
|
end
|
359
408
|
puts h
|
360
409
|
end
|
361
|
-
|
410
|
+
|
362
411
|
# TODO: Dry this up...
|
363
412
|
def self.skeleton(name)
|
364
413
|
|
@@ -387,6 +436,14 @@ Task - Create a task file in project/tasks with the class name of TaskName.
|
|
387
436
|
puts "Skipping #{name}/app/controllers directory (already exists)"
|
388
437
|
end
|
389
438
|
|
439
|
+
#copy mailers
|
440
|
+
if not File.exist?("#{name}/app/mailers")
|
441
|
+
puts "=> Creating #{name}/app/mailers directory"
|
442
|
+
system("mkdir #{name}/app/mailers")
|
443
|
+
else
|
444
|
+
puts "Skipping #{name}/app/mailers directory (already exists)"
|
445
|
+
end
|
446
|
+
|
390
447
|
#copy models
|
391
448
|
if not File.exist?("#{name}/app/models")
|
392
449
|
puts "=> Creating #{name}/app/models directory and files"
|
@@ -420,6 +477,14 @@ Task - Create a task file in project/tasks with the class name of TaskName.
|
|
420
477
|
else
|
421
478
|
puts "Skipping #{name}/app/views/index directory (already exists)"
|
422
479
|
end
|
480
|
+
|
481
|
+
#copy views/mail
|
482
|
+
if not File.exist?("#{name}/app/views/mail")
|
483
|
+
puts "=> Creating #{name}/app/views/mail directory"
|
484
|
+
system("mkdir #{name}/app/views/mail")
|
485
|
+
else
|
486
|
+
puts "Skipping #{name}/app/views/mail directory (already exists)"
|
487
|
+
end
|
423
488
|
|
424
489
|
#copy views/global
|
425
490
|
if not File.exist?("#{name}/app/views/global")
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: doozer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- grippy
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2010-01-03 00:00:00 -08:00
|
13
13
|
default_executable: doozer
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -45,6 +45,8 @@ files:
|
|
45
45
|
- lib/doozer/initializer.rb
|
46
46
|
- lib/doozer/lib.rb
|
47
47
|
- lib/doozer/logger.rb
|
48
|
+
- lib/doozer/mailer.rb
|
49
|
+
- lib/doozer/mailer_partial.rb
|
48
50
|
- lib/doozer/middleware.rb
|
49
51
|
- lib/doozer/orm/active_record.rb
|
50
52
|
- lib/doozer/orm/data_mapper.rb
|