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 CHANGED
@@ -1 +1 @@
1
- 0.4.0
1
+ 0.4.1
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{doozer}
8
- s.version = "0.4.0"
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{2009-11-05}
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",
@@ -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"
@@ -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
  }
@@ -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
- # => :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
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
- # => @cookies[:yum_yum]={:a=>'123',
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
- # => @cookies[:testing]=nil
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
- logger.info(" Params: #{@request.params.inspect}") if not @request.params.nil?
128
- logger.info(" Extra params: #{args[:extra_params].inspect}") if not args[:extra_params].nil?
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.
@@ -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
@@ -53,6 +53,7 @@ module Doozer
53
53
  load_partial(name) if @@partials[name].nil?
54
54
  erb = @@partials[name]
55
55
  if erb
56
+ puts " Partial: #{name}" if Doozer::Configs.rack_env == :development
56
57
  partial = Doozer::Partial.new(erb, locals, route)
57
58
  partial.bind()
58
59
  else
@@ -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
 
@@ -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 ""
@@ -3,7 +3,7 @@ module Doozer
3
3
  module Version
4
4
  MAJOR=0
5
5
  MINOR=4
6
- PATCH=0
6
+ PATCH=1
7
7
  STRING=[MAJOR, MINOR, PATCH].join('.')
8
8
  end
9
9
  end
@@ -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
@@ -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.0
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: 2009-11-05 00:00:00 -08:00
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