padrino-core 0.9.6 → 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,9 +1,33 @@
1
1
  module Padrino
2
+ ##
3
+ # Padrino enhances the Sinatra ‘render’ method to have support for automatic template engine detection,
4
+ # among other more advanced features.
5
+ #
2
6
  module Rendering
3
7
  def self.registered(app)
4
8
  app.send(:include, Padrino::Rendering)
5
9
  end
6
10
 
11
+ def self.included(base)
12
+ base.extend(ClassMethods)
13
+ end
14
+
15
+ module ClassMethods
16
+ ##
17
+ # Use layout like rails does or if a block given then like sinatra.
18
+ # If used without a block, sets the current layout for the route.
19
+ #
20
+ # By default, searches in your +app+/+views+/+layouts+/+application+.(+haml+|+erb+|+xxx+)
21
+ #
22
+ # If you define +layout+ :+custom+ then searches for your layouts in
23
+ # +app+/+views+/+layouts+/+custom+.(+haml+|+erb+|+xxx+)
24
+ #
25
+ def layout(name=:layout, &block)
26
+ return super(name, &block) if block_given?
27
+ @_layout = name
28
+ end
29
+ end
30
+
7
31
  private
8
32
  ##
9
33
  # Hijacking the sinatra render for:
@@ -12,6 +36,7 @@ module Padrino
12
36
  # * Use render 'path/to/my/template' (without symbols)
13
37
  # * Use render 'path/to/my/template' (with auto enegine lookup)
14
38
  # * Use render 'path/to/template', :layout => false
39
+ # * Use render 'path/to/template', :layout => false, :engine => 'haml'
15
40
  # * Use render { :a => 1, :b => 2, :c => 3 } # => return a json string
16
41
  #
17
42
  def render(engine, data=nil, options={}, locals={}, &block)
@@ -31,11 +56,10 @@ module Padrino
31
56
 
32
57
  # Use layout as rails do
33
58
  if (options[:layout].nil? || options[:layout] == true) && !self.class.templates.has_key?(:layout)
34
- layout = self.class.instance_variable_defined?(:@_layout) ? self.class.instance_variable_get(:@_layout) : :application
35
- if layout
36
- # We look first for views/layout_name.ext then then for views/layouts/layout_name.ext
37
- options[:layout] = Dir["#{self.options.views}/#{layout}.*"].present? ? layout.to_sym : File.join('layouts', layout.to_s).to_sym
38
- logger.debug "Rendering layout #{options[:layout]}" if defined?(logger)
59
+ if layout = self.class.instance_variable_defined?(:@_layout) ? self.class.instance_variable_get(:@_layout) : :application
60
+ layout = Dir["#{self.options.views}/#{layout}.*"].any? ? layout.to_sym : File.join('layouts', layout.to_s).to_sym
61
+ options[:layout] = resolve_template(layout)[0] rescue nil
62
+ logger.debug "Rendering layout #{options[:layout]}" if defined?(logger) && options[:layout]
39
63
  end
40
64
  end
41
65
  super(engine, data, options, locals, &block)
@@ -43,27 +67,30 @@ module Padrino
43
67
 
44
68
  ##
45
69
  # Returns the template path and engine that match (if presents) content_type, I18n.locale.
46
- #
70
+ #
47
71
  # ==== Example
48
- #
72
+ #
49
73
  # get "/foo", :respond_to => [:html, :js] do; render 'path/to/foo'; end
50
74
  # # If you request "/foo.js" with I18n.locale == :ru => [:"/path/to/foo.ru.js", :erb]
51
75
  # # If you request "/foo" with I18n.locale == :de => [:"/path/to/foo.de.haml", :haml]
52
- #
76
+ #
53
77
  def resolve_template(template_path, options={})
54
78
  view_path = options.delete(:views) || self.options.views || self.class.views || "./views"
55
- template_path = File.join(view_path, template_path.to_s)
56
- regexs = [/^[^\.]+\.[^\.]+$/]
57
- regexs.unshift(/^[^\.]+\.#{content_type}\.[^\.]+$/) if content_type.present?
58
- if defined?(I18n) && I18n.locale.present?
59
- regexs.unshift(/^[^\.]+\.#{I18n.locale}\.[^\.]+$/)
60
- regexs.unshift(/^[^\.]+\.#{I18n.locale}\.#{content_type}\.[^\.]+$/) if content_type.present?
79
+ template_path = "/#{template_path}" unless template_path.to_s =~ /^\//
80
+ templates = Dir[File.join(view_path, template_path) + ".*"].map do |file|
81
+ template_file = file.sub(view_path, '').chomp(File.extname(file)).to_sym # retrieves relative file path
82
+ template_engine = options[:engine] || File.extname(file)[1..-1].to_sym # retrieves engine extension
83
+ [template_file, template_engine]
61
84
  end
62
- template_file = regexs.map { |regex| Dir[template_path + ".*"].find { |file| File.basename(file) =~ regex } }.compact.first
63
- raise "Template path '#{template_path}' could not be located in views!" unless template_file
64
- engine = File.extname(template_file)[1..-1]
65
- template = template_file.gsub(view_path, '').gsub(/\.#{engine}$/, '')
66
- [template.to_sym, engine.to_sym]
85
+
86
+ located_template =
87
+ templates.find { |file, e| defined?(I18n) && file.to_s == "#{template_path}.#{I18n.locale}.#{content_type}" } ||
88
+ templates.find { |file, e| defined?(I18n) && file.to_s == "#{template_path}.#{I18n.locale}" && content_type == :html } ||
89
+ templates.find { |file, e| file.to_s == "#{template_path}.#{content_type}" } ||
90
+ templates.find { |file, e| file.to_s == "#{template_path}" && content_type == :html }
91
+
92
+ raise "Template path '#{template_path}' could not be located and rendered!" unless located_template
93
+ located_template
67
94
  end
68
95
 
69
96
  ##
@@ -76,5 +103,5 @@ module Padrino
76
103
  is_in_development = (defined?(Padrino) && Padrino.respond_to?(:env) && Padrino.env != :production)
77
104
  @template_cache.clear if is_in_development && can_clear_cache
78
105
  end
79
- end
80
- end
106
+ end # Rendering
107
+ end # Padrino
@@ -2,7 +2,17 @@ require 'usher' unless defined?(Usher)
2
2
  require 'padrino-core/support_lite' unless String.method_defined?(:blank!)
3
3
 
4
4
  module Padrino
5
+ ##
6
+ # Padrino provides advanced routing definition support to make routes and url generation much easier.
7
+ # This routing system supports named route aliases and easy access to url paths.
8
+ # The benefits of this is that instead of having to hard-code route urls into every area of your application,
9
+ # now we can just define the urls in a single spot and then attach an alias which can be used to refer
10
+ # to the url throughout the application.
11
+ #
5
12
  module Routing
13
+ class UnrecognizedException < RuntimeError #:nodoc:
14
+ end
15
+
6
16
  def self.registered(app)
7
17
  app.send(:include, Padrino::Routing)
8
18
  end
@@ -170,6 +180,9 @@ module Padrino
170
180
  url = router.generator.generate(name, params)
171
181
  url = uri_root + url if defined?(uri_root) && uri_root != "/"
172
182
  url
183
+ rescue Usher::UnrecognizedException
184
+ route_error = "route mapping for url(#{name.inspect}) could not be found!"
185
+ raise Padrino::Routing::UnrecognizedException.new(route_error)
173
186
  end
174
187
  alias :url_for :url
175
188
 
@@ -238,8 +251,9 @@ module Padrino
238
251
  end
239
252
 
240
253
  # Little reformats
241
- path.sub!(%r{\bindex$}, "") # If the route end with /index we remove them
242
- path = (uri_root == "/" ? "/" : "(/)") if path.blank? # Add a trailing delimiter if path is empty
254
+ path.sub!(%r{\bindex$}, "") # If the route end with /index we remove them
255
+ path.sub!(%r^/index(\(.\{:format[\,\w\$\|]*\}\))$^, '\1') # Remove index from formatted routes
256
+ path = (uri_root == "/" ? "/" : "(/)") if path.blank? # Add a trailing delimiter if path is empty
243
257
 
244
258
  # We need to have a path that start with / in some circumstances and that don't end with /
245
259
  if path != "(/)" && path != "/"
@@ -306,8 +320,8 @@ module Padrino
306
320
  container % match
307
321
  else ".{:format,#{format_params}}"
308
322
  end
309
- path << format_suffix
323
+ path + format_suffix
310
324
  end
311
- end
312
- end
313
- end
325
+ end # ClassMethods
326
+ end # Routing
327
+ end # Padrino
@@ -0,0 +1,25 @@
1
+ module Padrino
2
+ ##
3
+ # This module extend Sinatra::ShowExceptions adding Padrino as "Framework"
4
+ #
5
+ module ShowExceptions
6
+
7
+ def self.included(base)
8
+ base.alias_method_chain :frame_class, :padrino
9
+ end
10
+
11
+ def frame_class_with_padrino(frame)
12
+ if frame.filename =~ /lib\/sinatra.*\.rb|lib\/padrino.*\.rb/
13
+ "framework"
14
+ elsif (defined?(Gem) && frame.filename.include?(Gem.dir)) ||
15
+ frame.filename =~ /\/bin\/(\w+)$/ ||
16
+ frame.filename =~ /Ruby\/Gems/
17
+ "system"
18
+ else
19
+ "app"
20
+ end
21
+ end
22
+ end # ShowExceptions
23
+ end # Padrino
24
+
25
+ Sinatra::ShowExceptions.send(:include, Padrino::ShowExceptions)
@@ -1,46 +1,45 @@
1
1
  module Padrino
2
2
  PADRINO_IGNORE_CALLERS = [
3
- %r{lib/padrino-.*$}, # all padrino code
4
- %r{/padrino-.*/(lib|bin)}, # all padrino code
5
- %r{/bin/padrino$}, # all padrino code
6
- %r{/sinatra}, # all sinatra code
7
- %r{lib/tilt.*\.rb$}, # all tilt code
8
- %r{lib/rack.*\.rb$}, # all rack code
9
- %r{lib/mongrel.*\.rb$}, # all mongrel code
10
- %r{lib/shotgun.*\.rb$}, # all shotgun lib
11
- %r{bin/shotgun$}, # shotgun binary
12
- %r{\(.*\)}, # generated code
13
- %r{shoulda/context\.rb$}, # shoulda hacks
14
- %r{mocha/integration}, # mocha hacks
15
- %r{test/unit}, # test unit hacks
16
- %r{rake_test_loader\.rb}, # rake hacks
17
- %r{custom_require\.rb$}, # rubygems require hacks
18
- %r{active_support}, # active_support require hacks
19
- %r{/thor}, # thor require hacks
3
+ %r{lib/padrino-.*$}, # all padrino code
4
+ %r{/padrino-.*/(lib|bin)}, # all padrino code
5
+ %r{/bin/padrino$}, # all padrino code
6
+ %r{/sinatra(/(base|main|showexceptions))?\.rb$}, # all sinatra code
7
+ %r{lib/tilt.*\.rb$}, # all tilt code
8
+ %r{lib/rack.*\.rb$}, # all rack code
9
+ %r{lib/mongrel.*\.rb$}, # all mongrel code
10
+ %r{lib/shotgun.*\.rb$}, # all shotgun lib
11
+ %r{bin/shotgun$}, # shotgun binary
12
+ %r{\(.*\)}, # generated code
13
+ %r{shoulda/context\.rb$}, # shoulda hacks
14
+ %r{mocha/integration}, # mocha hacks
15
+ %r{test/unit}, # test unit hacks
16
+ %r{rake_test_loader\.rb}, # rake hacks
17
+ %r{custom_require\.rb$}, # rubygems require hacks
18
+ %r{active_support}, # active_support require hacks
19
+ %r{/thor}, # thor require hacks
20
20
  ] unless defined?(PADRINO_IGNORE_CALLERS)
21
21
 
22
22
  ##
23
23
  # Add rubinius (and hopefully other VM impls) ignore patterns ...
24
- #
24
+ #
25
25
  PADRINO_IGNORE_CALLERS.concat(RUBY_IGNORE_CALLERS) if defined?(RUBY_IGNORE_CALLERS)
26
26
 
27
27
  private
28
+ ##
29
+ # Returns the filename for the file that is the direct caller (first caller)
30
+ #
31
+ def self.first_caller
32
+ caller_files.first
33
+ end
28
34
 
29
- ##
30
- # Returns the filename for the file that is the direct caller (first caller)
31
- #
32
- def self.first_caller
33
- caller_files.first
34
- end
35
-
36
- ##
37
- # Like Kernel#caller but excluding certain magic entries and without
38
- # line / method information; the resulting array contains filenames only.
39
- #
40
- def self.caller_files
41
- caller(1).
42
- map { |line| line.split(/:(?=\d|in )/)[0,2] }.
43
- reject { |file,line| PADRINO_IGNORE_CALLERS.any? { |pattern| file =~ pattern } }.
44
- map { |file,line| file }
45
- end
46
- end # Padrino
35
+ ##
36
+ # Like Kernel#caller but excluding certain magic entries and without
37
+ # line / method information; the resulting array contains filenames only.
38
+ #
39
+ def self.caller_files
40
+ caller(1).
41
+ map { |line| line.split(/:(?=\d|in )/)[0,2] }.
42
+ reject { |file,line| PADRINO_IGNORE_CALLERS.any? { |pattern| file =~ pattern } }.
43
+ map { |file,line| file }
44
+ end
45
+ end # Padrino
@@ -46,8 +46,7 @@ module Padrino
46
46
  puts " done."
47
47
  end
48
48
  end
49
-
50
- end
51
- end
52
- end
53
- end
49
+ end # self
50
+ end # Adapter
51
+ end # Cli
52
+ end # Padrino
@@ -105,7 +105,7 @@ module Padrino
105
105
  eval "$#{stream} = StringIO.new"
106
106
  yield
107
107
  result = eval("$#{stream}").string
108
- ensure
108
+ ensure
109
109
  eval("$#{stream} = #{stream.upcase}")
110
110
  end
111
111
 
@@ -1,6 +1,5 @@
1
1
  require File.dirname(__FILE__) + '/../tasks'
2
2
  require 'rake'
3
-
4
3
  Rake.application.instance_variable_set(:@rakefile, __FILE__)
5
4
 
6
5
  module PadrinoTasks
@@ -2,7 +2,7 @@ module Padrino
2
2
  class << self
3
3
  ##
4
4
  # Requires necessary dependencies as well as application files from root lib and models
5
- #
5
+ #
6
6
  def load!
7
7
  return false if loaded?
8
8
  @_called_from = first_caller
@@ -17,7 +17,7 @@ module Padrino
17
17
 
18
18
  ##
19
19
  # Method for reloading required applications and their files
20
- #
20
+ #
21
21
  def reload!
22
22
  return unless Reloader::Stat.changed?
23
23
  Reloader::Stat.reload! # detects the modified files
@@ -26,14 +26,14 @@ module Padrino
26
26
 
27
27
  ##
28
28
  # This adds the ablity to instantiate Padrino.load! after Padrino::Application definition.
29
- #
29
+ #
30
30
  def called_from
31
31
  @_called_from || first_caller
32
32
  end
33
33
 
34
34
  ##
35
35
  # Return true if Padrino was loaded with Padrino.load!
36
- #
36
+ #
37
37
  def loaded?
38
38
  Thread.current[:padrino_loaded]
39
39
  end
@@ -42,23 +42,23 @@ module Padrino
42
42
  # Attempts to require all dependency libs that we need.
43
43
  # If you use this method we can perform correctly a Padrino.reload!
44
44
  # Another good thing that this method are dependency check, for example:
45
- #
45
+ #
46
46
  # models
47
47
  # \-- a.rb => require something of b.rb
48
48
  # \-- b.rb
49
- #
49
+ #
50
50
  # In the example above if we do:
51
- #
51
+ #
52
52
  # Dir["/models/*.rb"].each { |r| require r }
53
- #
53
+ #
54
54
  # we get an error, because we try to require first a.rb that need +something+ of b.rb.
55
- #
55
+ #
56
56
  # With +require_dependencies+ we don't have this problem.
57
- #
57
+ #
58
58
  # ==== Examples
59
59
  # # For require all our app libs we need to do:
60
60
  # require_dependencies("#{Padrino.root}/lib/**/*.rb")
61
- #
61
+ #
62
62
  def require_dependencies(*paths)
63
63
  # Extract all files to load
64
64
  files = paths.map { |path| Dir[path] }.flatten
@@ -101,7 +101,7 @@ module Padrino
101
101
 
102
102
  ##
103
103
  # Concat to $LOAD_PATH the given paths
104
- #
104
+ #
105
105
  def set_load_paths(*paths)
106
106
  $:.concat(paths)
107
107
  $:.uniq!
@@ -21,7 +21,7 @@ en:
21
21
  long: "%B %d, %Y %H:%M"
22
22
  am: "am"
23
23
  pm: "pm"
24
-
24
+
25
25
  # Used in array.to_sentence.
26
26
  support:
27
27
  array:
@@ -8,13 +8,13 @@ it:
8
8
  short: "%d %b"
9
9
  long: "%d %B %Y"
10
10
  only_day: "%e"
11
-
11
+
12
12
  day_names: [Domenica, Lunedì, Martedì, Mercoledì, Giovedì, Venerdì, Sabato]
13
13
  abbr_day_names: [Dom, Lun, Mar, Mer, Gio, Ven, Sab]
14
14
  month_names: [~, Gennaio, Febbraio, Marzo, Aprile, Maggio, Giugno, Luglio, Agosto, Settembre, Ottobre, Novembre, Dicembre]
15
15
  abbr_month_names: [~, Gen, Feb, Mar, Apr, Mag, Giu, Lug, Ago, Set, Ott, Nov, Dic]
16
16
  order: [ :day, :month, :year ]
17
-
17
+
18
18
  time:
19
19
  formats:
20
20
  default: "%a %d %b %Y, %H:%M:%S %z"
@@ -22,11 +22,11 @@ it:
22
22
  short: "%d %b %H:%M"
23
23
  long: "%d %B %Y %H:%M"
24
24
  only_second: "%S"
25
-
25
+
26
26
  datetime:
27
27
  formats:
28
28
  default: "%d-%m-%YT%H:%M:%S%Z"
29
-
29
+
30
30
  am: 'am'
31
31
  pm: 'pm'
32
32
 
@@ -5,24 +5,24 @@ module Padrino
5
5
 
6
6
  ##
7
7
  # Returns the padrino logger
8
- #
8
+ #
9
9
  # ==== Examples
10
- #
10
+ #
11
11
  # logger.debug "foo"
12
12
  # logger.warn "bar"
13
- #
13
+ #
14
14
  def self.logger
15
15
  Thread.current[:padrino_logger] ||= Padrino::Logger.setup!
16
16
  end
17
17
 
18
18
  ##
19
19
  # Extensions to the built in Ruby logger.
20
- #
20
+ #
21
21
  # ==== Examples
22
- #
22
+ #
23
23
  # logger.debug "foo"
24
24
  # logger.warn "bar"
25
- #
25
+ #
26
26
  class Logger
27
27
 
28
28
  attr_accessor :level
@@ -33,13 +33,13 @@ module Padrino
33
33
 
34
34
  ##
35
35
  # Ruby (standard) logger levels:
36
- #
36
+ #
37
37
  # :fatal:: An unhandleable error that results in a program crash
38
38
  # :error:: A handleable error condition
39
39
  # :warn:: A warning
40
40
  # :info:: generic (useful) information about system operation
41
41
  # :debug:: low-level information for developers
42
- #
42
+ #
43
43
  Levels = {
44
44
  :fatal => 7,
45
45
  :error => 6,
@@ -52,7 +52,7 @@ module Padrino
52
52
 
53
53
  ##
54
54
  # Configuration for a given environment, possible options are:
55
- #
55
+ #
56
56
  # :log_level:: Once of [:fatal, :error, :warn, :info, :debug]
57
57
  # :stream:: Once of [:to_file, :null, :stdout, :stderr] our your custom stream
58
58
  # :log_level::
@@ -63,21 +63,21 @@ module Padrino
63
63
  # added. Defaults to true.
64
64
  # :format_datetime:: Format of datetime. Defaults to: "%d/%b/%Y %H:%M:%S"
65
65
  # :format_message:: Format of message. Defaults to: ""%s - - [%s] \"%s\"""
66
- #
66
+ #
67
67
  # ==== Examples
68
- #
68
+ #
69
69
  # Padrino::Logger::Config[:development] = { :log_level => :debug, :to_file }
70
70
  # # or you can edit our defaults
71
71
  # Padrino::Logger::Config[:development][:log_level] = :error
72
72
  # # or you can use your stream
73
73
  # Padrino::Logger::Config[:development][:stream] = StringIO.new
74
- #
74
+ #
75
75
  # Defaults are:
76
- #
76
+ #
77
77
  # :production => { :log_level => :warn, :stream => :to_file }
78
78
  # :development => { :log_level => :debug, :stream => :stdout }
79
79
  # :test => { :log_level => :fatal, :stream => :null }
80
- #
80
+ #
81
81
  Config = {
82
82
  :production => { :log_level => :warn, :stream => :to_file },
83
83
  :development => { :log_level => :debug, :stream => :stdout },
@@ -86,7 +86,7 @@ module Padrino
86
86
 
87
87
  ##
88
88
  # Setup a new logger
89
- #
89
+ #
90
90
  def self.setup!
91
91
  config_level = (PADRINO_LOG_LEVEL || Padrino.env || :test).to_sym # need this for PADRINO_LOG_LEVEL
92
92
  config = Config[config_level]
@@ -108,7 +108,7 @@ module Padrino
108
108
  # To initialize the logger you create a new object, proxies to set_log.
109
109
  #
110
110
  # ==== Options
111
- #
111
+ #
112
112
  # :stream:: Either an IO object or a name of a logfile. Defaults to $stdout
113
113
  # :log_level::
114
114
  # The log level from, e.g. :fatal or :info. Defaults to :debug in the
@@ -118,7 +118,7 @@ module Padrino
118
118
  # added. Defaults to true.
119
119
  # :format_datetime:: Format of datetime. Defaults to: "%d/%b/%Y %H:%M:%S"
120
120
  # :format_message:: Format of message. Defaults to: ""%s - - [%s] \"%s\"""
121
- #
121
+ #
122
122
  def initialize(options={})
123
123
  @buffer = []
124
124
  @auto_flush = options.has_key?(:auto_flush) ? options[:auto_flush] : true
@@ -132,7 +132,7 @@ module Padrino
132
132
 
133
133
  ##
134
134
  # Flush the entire buffer to the log object.
135
- #
135
+ #
136
136
  def flush
137
137
  return unless @buffer.size > 0
138
138
  @mutex.synchronize do
@@ -142,7 +142,7 @@ module Padrino
142
142
 
143
143
  ##
144
144
  # Close and remove the current log object.
145
- #
145
+ #
146
146
  def close
147
147
  flush
148
148
  @log.close if @log.respond_to?(:close) && !@log.tty?
@@ -159,7 +159,7 @@ module Padrino
159
159
 
160
160
  ##
161
161
  # Directly append message to the log.
162
- #
162
+ #
163
163
  def <<(message = nil)
164
164
  message << "\n" unless message[-1] == ?\n
165
165
  @buffer << message
@@ -169,7 +169,7 @@ module Padrino
169
169
 
170
170
  ##
171
171
  # Generate the logging methods for Padrino.logger for each log level.
172
- #
172
+ #
173
173
  Levels.each_pair do |name, number|
174
174
  class_eval <<-LEVELMETHODS, __FILE__, __LINE__
175
175
 
@@ -219,13 +219,13 @@ module Padrino
219
219
  # Padrino::Loggger::Rack forwards every request to an +app+ given, and
220
220
  # logs a line in the Apache common log format to the +logger+, or
221
221
  # rack.errors by default.
222
- #
222
+ #
223
223
  class Rack
224
224
  ##
225
225
  # Common Log Format: http://httpd.apache.org/docs/1.3/logs.html#common
226
226
  # "lilith.local - - GET / HTTP/1.1 500 -"
227
227
  # %{%s - %s %s %s%s %s - %d %s %0.4f}
228
- #
228
+ #
229
229
  FORMAT = %{%s - %s %s %s%s %s - %d %s %0.4f}
230
230
 
231
231
  def initialize(app)
@@ -271,7 +271,7 @@ end # Padrino
271
271
  module Kernel #:nodoc:
272
272
  ##
273
273
  # Define a logger available every where in our app
274
- #
274
+ #
275
275
  def logger
276
276
  Padrino.logger
277
277
  end