doozer 0.4.0 → 0.4.1

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/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