padrino-core 0.9.6 → 0.9.7

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.
@@ -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