padrino-core 0.9.10 → 0.9.11

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/README.rdoc CHANGED
@@ -150,7 +150,7 @@ and even configure the respond_to for each route:
150
150
 
151
151
  # app/controllers/example.rb
152
152
  SimpleApp.controllers :admin do
153
- get :show, :with => :id, :respond_to => :js do
153
+ get :show, :with => :id, :provides => :js do
154
154
  "Url is /admin/show/#{params[:id]}.#{params[:format]}"
155
155
  end
156
156
 
@@ -166,7 +166,7 @@ or auto lookup for current locale or content_type
166
166
 
167
167
  # app/controllers/example.rb
168
168
  SimpleApp.controllers :admin do
169
- get :show, :with => :id, :respond_to => [html, :js] do
169
+ get :show, :with => :id, :provides => [html, :js] do
170
170
  render "admin/show"
171
171
  end
172
172
  end
data/Rakefile CHANGED
@@ -1,57 +1,5 @@
1
- require 'rubygems'
2
- require 'rake'
3
- require File.expand_path("../lib/padrino-core/version.rb", __FILE__)
4
-
5
- begin
6
- require 'jeweler'
7
- Jeweler::Tasks.new do |gem|
8
- gem.name = "padrino-core"
9
- gem.summary = "The required Padrino core gem"
10
- gem.description = "The Padrino core gem required for use of this framework"
11
- gem.email = "padrinorb@gmail.com"
12
- gem.homepage = "http://github.com/padrino/padrino-framework/tree/master/padrino-core"
13
- gem.authors = ["Padrino Team", "Nathan Esquenazi", "Davide D'Agostino", "Arthur Chiu"]
14
- gem.executables = ["padrino"]
15
- gem.rubyforge_project = 'padrino-core'
16
- gem.version = Padrino.version
17
- gem.add_runtime_dependency "sinatra", ">= 1.0.0"
18
- gem.add_runtime_dependency "i18n", ">= 0.3.2"
19
- gem.add_runtime_dependency "usher", ">= 0.6.2"
20
- gem.add_runtime_dependency "thor", ">= 0.13.0"
21
- gem.add_runtime_dependency "bundler", ">= 0.9.7"
22
- gem.add_runtime_dependency "activesupport", "= 2.3.5"
23
- gem.add_development_dependency "shoulda", ">= 2.10.3"
24
- gem.add_development_dependency "mocha", ">= 0.9.7"
25
- gem.add_development_dependency "rack-test", ">= 0.5.0"
26
- gem.add_development_dependency "webrat", ">= 0.5.1"
27
- gem.add_development_dependency "haml", ">= 2.2.22"
28
- # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
29
- end
30
- Jeweler::GemcutterTasks.new
31
- Jeweler::RubyforgeTasks.new { |r| r.doc_task = :none }
32
- rescue LoadError
33
- puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
34
- end
35
-
36
- require 'rake/testtask'
37
- Rake::TestTask.new(:test) do |test|
38
- test.libs << 'test'
39
- test.pattern = 'test/**/test_*.rb'
40
- test.verbose = true
41
- end
1
+ # coding:utf-8
2
+ RAKE_ROOT = __FILE__
42
3
 
43
- begin
44
- require 'rcov/rcovtask'
45
- Rcov::RcovTask.new do |rcov|
46
- rcov.libs << 'test'
47
- rcov.pattern = 'test/**/test_*.rb'
48
- rcov.verbose = true
49
- rcov.rcov_opts << ['--exclude /Gems/1.8/gems/,padrino-admin,padrino-cache,padrino-gen,padrino-helpers,padrino-mailer']
50
- end
51
- rescue LoadError
52
- task :rcov do
53
- abort "RCov is not available. In order to run rcov, you must: sudo gem install relevance-rcov"
54
- end
55
- end
56
-
57
- task :default => :test
4
+ require 'rubygems'
5
+ require File.expand_path(File.dirname(__FILE__) + '/../gem_rake_helper')
data/bin/padrino CHANGED
@@ -1,27 +1,24 @@
1
1
  #!/usr/bin/env ruby
2
- require 'rubygems'
3
2
 
3
+ # We load Padrino libs
4
4
  padrino_core_path = File.expand_path('../../lib', __FILE__)
5
5
  $:.unshift(padrino_core_path) if File.directory?(padrino_core_path) && !$:.include?(padrino_core_path)
6
6
 
7
- padrino_local_path = Dir.pwd
8
- $:.unshift(padrino_local_path) if File.directory?(padrino_local_path) && !$:.include?(padrino_local_path)
9
-
10
- require 'padrino-core/cli/base'
11
- require 'padrino-core/support_lite'
12
-
7
+ # Build Padrino g as an alias of padrino-gen
13
8
  if %w(g gen).include?(ARGV[0])
14
9
  ARGV.shift
15
10
  begin
16
11
  # We try to load the vendored padrino-gen if exist
17
12
  padrino_gen_path = File.expand_path('../../../padrino-gen/lib', __FILE__)
18
13
  $:.unshift(padrino_gen_path) if File.directory?(padrino_gen_path) && !$:.include?(padrino_gen_path)
19
- require 'padrino-gen'
14
+ require 'padrino-core/command'
15
+ require 'padrino-gen/command'
20
16
  Padrino.bin_gen(ARGV)
21
17
  rescue
22
18
  puts "<= You need padrino-gen! Run: gem install padrino-gen"
23
19
  end
24
- exit(0)
25
- end
26
-
27
- Padrino::Cli::Base.start(ARGV)
20
+ else
21
+ # We load our cli
22
+ require 'padrino-core/cli/base'
23
+ Padrino::Cli::Base.start(ARGV)
24
+ end
data/lib/padrino-core.rb CHANGED
@@ -1,11 +1,12 @@
1
1
  require 'sinatra/base'
2
- require 'padrino-core/support_lite'
2
+ require 'padrino-core/support_lite' unless defined?(SupportLite)
3
3
 
4
- Dir[File.dirname(__FILE__) + '/padrino-core/application/*.rb'].each {|file| require file }
5
- Dir[File.dirname(__FILE__) + '/padrino-core/*.rb'].each {|file| require file }
4
+ FileSet.glob_require('padrino-core/application/*.rb', __FILE__)
5
+ FileSet.glob_require('padrino-core/*.rb', __FILE__)
6
6
 
7
- # Defines our PADRINO_ENV
8
- PADRINO_ENV = ENV["PADRINO_ENV"] ||= ENV["RACK_ENV"] ||= "development" unless defined?(PADRINO_ENV)
7
+ # Defines our Constants
8
+ PADRINO_ENV = ENV["PADRINO_ENV"] ||= ENV["RACK_ENV"] ||= "development" unless defined?(PADRINO_ENV)
9
+ PADRINO_ROOT = ENV["PADRINO_ROOT"] ||= File.dirname(Padrino.first_caller) unless defined?(PADRINO_ROOT)
9
10
 
10
11
  module Padrino
11
12
  class ApplicationLoadError < RuntimeError #:nodoc:
@@ -36,7 +37,7 @@ module Padrino
36
37
  # Returns the resulting rack builder mapping each 'mounted' application
37
38
  #
38
39
  def application
39
- raise ApplicationLoadError.new("At least one app must be mounted!") unless self.mounted_apps && self.mounted_apps.any?
40
+ raise ApplicationLoadError, "At least one app must be mounted!" unless self.mounted_apps && self.mounted_apps.any?
40
41
  router = Padrino::Router.new
41
42
  self.mounted_apps.each { |app| app.map_onto(router) }
42
43
  router
@@ -43,9 +43,16 @@ module Padrino
43
43
  # MyApp.reload!
44
44
  #
45
45
  def reload!
46
- reset_routes! # remove all existing user-defined application routes
47
- Padrino.load_dependency(self.app_file) # reload the app file
48
- load_paths.each { |path| Padrino.load_dependencies(File.join(self.root, path)) } # reload dependencies
46
+ reset! # Reset sinatra app
47
+ reset_routes! # Remove all existing user-defined application routes
48
+ Padrino.require_dependencies(File.join(self.root, "/models.rb")) # Reload models class
49
+ Padrino.require_dependencies(File.join(self.root, "/models/**/*.rb")) # Reload all models
50
+ Padrino.require_dependencies(self.app_file) # Reload the app file
51
+ register_initializers # Reload our middlewares
52
+ require_load_paths # Reload dependencies
53
+ default_filters! # Reload filters
54
+ default_errors! # Reload our errors
55
+ I18n.reload! if defined?(I18n) # Reload also our translations
49
56
  end
50
57
 
51
58
  ##
@@ -60,6 +67,13 @@ module Padrino
60
67
  default_routes!
61
68
  end
62
69
 
70
+ ##
71
+ # Returns the routes of our app
72
+ #
73
+ def routes
74
+ router.routes
75
+ end
76
+
63
77
  ##
64
78
  # Setup the application by registering initializers, load paths and logger
65
79
  # Invoked automatically when an application is first instantiated
@@ -67,25 +81,48 @@ module Padrino
67
81
  def setup_application!
68
82
  return if @_configured
69
83
  self.calculate_paths
70
- self.register_framework_extensions
71
84
  self.register_initializers
72
85
  self.require_load_paths
73
86
  self.disable :logging # We need do that as default because Sinatra use commonlogger.
74
87
  self.default_filters!
75
88
  self.default_routes!
76
89
  self.default_errors!
77
- I18n.load_path += self.locale_path
78
- I18n.reload!
90
+ if defined?(I18n)
91
+ I18n.load_path += self.locale_path
92
+ I18n.reload!
93
+ end
79
94
  @_configured = true
80
95
  end
81
96
 
97
+ ##
98
+ # Run the Padrino app as a self-hosted server using
99
+ # Thin, Mongrel or WEBrick (in that order)
100
+ #
101
+ def run!(options={})
102
+ return unless Padrino.load!
103
+ set options
104
+ handler = detect_rack_handler
105
+ handler_name = handler.name.gsub(/.*::/, '')
106
+ puts "=> #{self.name}/#{Padrino.version} has taken the stage #{Padrino.env} on #{port}" unless handler_name =~/cgi/i
107
+ handler.run self, :Host => bind, :Port => port do |server|
108
+ trap(:INT) do
109
+ ## Use thins' hard #stop! if available, otherwise just #stop
110
+ server.respond_to?(:stop!) ? server.stop! : server.stop
111
+ puts "<= #{self.name} has ended his set (crowd applauds)" unless handler_name =~/cgi/i
112
+ end
113
+ set :running, true
114
+ end
115
+ rescue Errno::EADDRINUSE => e
116
+ puts "<= Someone is already performing on port #{port}!"
117
+ end
118
+
82
119
  protected
83
120
  ##
84
121
  # Defines default settings for Padrino application
85
122
  #
86
123
  def default_configuration!
87
124
  # Overwriting Sinatra defaults
88
- set :app_file, caller_files.first || $0 # Assume app file is first caller
125
+ set :app_file, File.expand_path(caller_files.first || $0) # Assume app file is first caller
89
126
  set :environment, Padrino.env
90
127
  set :raise_errors, true if development?
91
128
  set :reload, true if development?
@@ -101,9 +138,6 @@ module Padrino
101
138
  set :authentication, false
102
139
  # Padrino locale
103
140
  set :locale_path, Proc.new { Dir[File.join(self.root, "/locale/**/*.{rb,yml}")] }
104
- # Plugin specific
105
- set :padrino_mailer, defined?(Padrino::Mailer)
106
- set :padrino_helpers, defined?(Padrino::Helpers)
107
141
  end
108
142
 
109
143
  ##
@@ -162,15 +196,6 @@ module Padrino
162
196
  use Rack::Flash if flash? && sessions?
163
197
  end
164
198
 
165
- ##
166
- # Registers all desired padrino extension helpers
167
- #
168
- def register_framework_extensions
169
- register Padrino::Mailer if padrino_mailer?
170
- register Padrino::Helpers if padrino_helpers?
171
- register Padrino::Admin::AccessControl if authentication?
172
- end
173
-
174
199
  ##
175
200
  # Returns the load_paths for the application (relative to the application root)
176
201
  #
@@ -9,12 +9,16 @@ module Padrino
9
9
  # Mounter.new("blog_app", :app_file => "/path/to/blog/app.rb").to("/blog")
10
10
  #
11
11
  class Mounter
12
+ class MounterException < RuntimeError #:nodoc:
13
+ end
14
+
12
15
  attr_accessor :name, :uri_root, :app_file, :app_class, :app_root, :app_obj, :app_host
13
16
 
14
17
  def initialize(name, options={})
15
18
  @name = name.underscore
16
19
  @app_class = options[:app_class] || name.classify
17
20
  @app_file = options[:app_file] || locate_app_file
21
+ raise MounterException, "Unable to locate app file for #{name}, try with :app_file => /path" unless @app_file
18
22
  @app_root = options[:app_root] || File.dirname(@app_file)
19
23
  @app_obj = self.app_object
20
24
  @uri_root = "/"
@@ -70,16 +74,26 @@ module Padrino
70
74
  # Return the class for the app
71
75
  #
72
76
  def app_object
73
- app_class.constantize rescue Padrino.require_dependency(app_file)
74
- app_class.constantize
77
+ begin
78
+ app_class.constantize
79
+ rescue
80
+ if app_file
81
+ Padrino.require_dependencies(app_file)
82
+ app_class.constantize
83
+ end
84
+ end
75
85
  end
76
86
 
77
87
  ##
78
88
  # Returns the determined location of the mounted application main file
79
89
  #
80
90
  def locate_app_file
81
- callers_are_identical = File.identical?(Padrino.first_caller.to_s, Padrino.called_from.to_s)
82
- callers_are_identical ? Padrino.first_caller : Padrino.mounted_root(name, "app.rb")
91
+ candidates = []
92
+ candidates << app_object.app_file if app_object.respond_to?(:app_file) && File.exist?(app_object.app_file)
93
+ candidates << Padrino.first_caller if File.identical?(Padrino.first_caller.to_s, Padrino.called_from.to_s)
94
+ candidates << Padrino.mounted_root(name, "app.rb")
95
+ candidates << Padrino.root("app", "app.rb")
96
+ candidates.find { |candidate| File.exist?(candidate) }
83
97
  end
84
98
 
85
99
  ##
@@ -126,7 +140,7 @@ module Padrino
126
140
  def mount_core(*args)
127
141
  options = args.extract_options!
128
142
  app_class = args.size > 0 ? args.first.to_s.camelize : nil
129
- options.reverse_merge!(:app_class => app_class, :app_file => Padrino.root("app", "app.rb"))
143
+ options.reverse_merge!(:app_class => app_class)
130
144
  mount("core", options).to("/")
131
145
  end
132
146
 
@@ -1,3 +1,5 @@
1
+ require 'padrino-core/support_lite' unless defined?(SupportLite)
2
+
1
3
  module Padrino
2
4
  ##
3
5
  # Padrino enhances the Sinatra ‘render’ method to have support for automatic template engine detection,
@@ -17,12 +19,20 @@ module Padrino
17
19
  /~$/ # This is for Gedit
18
20
  ]
19
21
 
20
- def self.registered(app)
21
- app.send(:include, Padrino::Rendering)
22
- end
22
+ ##
23
+ # Default rendering options used in the #render-method
24
+ #
25
+ DEFAULT_RENDERING_OPTIONS = { :strict_format => false, :raise_exceptions => true }
23
26
 
24
- def self.included(base)
25
- base.extend(ClassMethods)
27
+ ##
28
+ # Main class that register this extension
29
+ #
30
+ class << self
31
+ def registered(app)
32
+ app.send(:include, InstanceMethods)
33
+ app.extend(ClassMethods)
34
+ end
35
+ alias :included :registered
26
36
  end
27
37
 
28
38
  module ClassMethods
@@ -58,6 +68,9 @@ module Padrino
58
68
  (@_cached_templates ||= {})[render_options] = template_file || []
59
69
  end
60
70
 
71
+ ##
72
+ # Retunrs the cached layout path.
73
+ #
61
74
  def fetch_layout_path
62
75
  layout_name = @layout || :application
63
76
  @_cached_layout ||= {}
@@ -70,107 +83,116 @@ module Padrino
70
83
  end
71
84
  end
72
85
 
73
- private
74
- ##
75
- # Enhancing Sinatra render functionality for:
76
- #
77
- # * Using layout similar to rails
78
- # * Use render 'path/to/my/template' (without symbols)
79
- # * Use render 'path/to/my/template' (with engine lookup)
80
- # * Use render 'path/to/template.haml' (with explicit engine lookup)
81
- # * Use render 'path/to/template', :layout => false
82
- # * Use render 'path/to/template', :layout => false, :engine => 'haml'
83
- # * Use render { :a => 1, :b => 2, :c => 3 } # => return a json string
84
- #
85
- def render(engine, data=nil, options={}, locals={}, &block)
86
- # If engine is a hash then render data converted to json
87
- return engine.to_json if engine.is_a?(Hash)
88
-
89
- # Data can actually be a hash of options in certain cases
90
- options.merge!(data) && data = nil if data.is_a?(Hash)
91
-
92
- # If an engine is a string then this is a likely a path to be resolved
93
- data, engine = *resolve_template(engine, options) if data.nil?
94
-
95
- # Sinatra 1.0 requires an outvar for erb and erubis templates
96
- options[:outvar] ||= '@_out_buf' if [:erb, :erubis] & [engine]
97
-
98
- # Resolve layouts similar to in Rails
99
- if (options[:layout].nil? || options[:layout] == true) && !self.class.templates.has_key?(:layout)
100
- options[:layout] = resolved_layout || false # We need to force layout false so sinatra don't try to render it
101
- logger.debug "Resolving layout #{options[:layout]}" if defined?(logger) && options[:layout].present?
102
- end
103
-
104
- # Pass arguments to Sinatra render method
105
- super(engine, data, options.dup, locals, &block)
86
+ module InstanceMethods
87
+ def content_type(type=nil, params={}) #:nodoc:
88
+ type.nil? ? @_content_type : super(type, params)
106
89
  end
107
90
 
108
- ##
109
- # Returns the located layout to be used for the rendered template (if available)
110
- #
111
- # ==== Example
112
- #
113
- # resolve_layout(true)
114
- # => "/layouts/custom"
115
- #
116
- def resolved_layout
117
- located_layout = resolve_template(self.class.fetch_layout_path, :strict_format => true, :raise_exceptions => false)
118
- located_layout ? located_layout[0] : false
119
- end
91
+ private
92
+ ##
93
+ # Enhancing Sinatra render functionality for:
94
+ #
95
+ # * Using layout similar to rails
96
+ # * Use render 'path/to/my/template' (without symbols)
97
+ # * Use render 'path/to/my/template' (with engine lookup)
98
+ # * Use render 'path/to/template.haml' (with explicit engine lookup)
99
+ # * Use render 'path/to/template', :layout => false
100
+ # * Use render 'path/to/template', :layout => false, :engine => 'haml'
101
+ # * Use render { :a => 1, :b => 2, :c => 3 } # => return a json string
102
+ #
103
+ def render(engine, data=nil, options={}, locals={}, &block)
104
+ # If engine is a hash then render data converted to json
105
+ return engine.to_json if engine.is_a?(Hash)
106
+
107
+ # Data can actually be a hash of options in certain cases
108
+ options.merge!(data) && data = nil if data.is_a?(Hash)
109
+
110
+ # If an engine is a string then this is a likely a path to be resolved
111
+ data, engine = *resolve_template(engine, options) if data.nil?
112
+
113
+ # Sinatra 1.0 requires an outvar for erb and erubis templates
114
+ options[:outvar] ||= '@_out_buf' if [:erb, :erubis] & [engine]
115
+
116
+ # Resolve layouts similar to in Rails
117
+ if (options[:layout].nil? || options[:layout] == true) && !settings.templates.has_key?(:layout)
118
+ options[:layout] = resolved_layout || false # We need to force layout false so sinatra don't try to render it
119
+ logger.debug "Resolving layout #{options[:layout]}" if defined?(logger) && options[:layout].present?
120
+ end
121
+
122
+ # Pass arguments to Sinatra render method
123
+ super(engine, data, options.dup, locals, &block)
124
+ end
120
125
 
121
- ##
122
- # Returns the template path and engine that match content_type (if present), I18n.locale.
123
- #
124
- # === Options
125
- #
126
- # :strict_format:: The resolved template must match the content_type of the request (defaults to false)
127
- # :raise_exceptions:: Raises a +TemplateNotFound+ exception if the template cannot be located.
128
- #
129
- # ==== Example
130
- #
131
- # get "/foo", :respond_to => [:html, :js] do; render 'path/to/foo'; end
132
- # # If you request "/foo.js" with I18n.locale == :ru => [:"/path/to/foo.ru.js", :erb]
133
- # # If you request "/foo" with I18n.locale == :de => [:"/path/to/foo.de.haml", :haml]
134
- #
135
- def resolve_template(template_path, options={})
136
- # Fetch cached template for rendering options
137
- template_path = "/#{template_path}" unless template_path.to_s[0] == ?/
138
- rendering_options = [template_path, content_type, locale]
139
- cached_template = self.class.fetch_template_file(rendering_options)
140
- return cached_template if cached_template
141
-
142
- # Resolve view path and options
143
- options.reverse_merge!(:strict_format => false, :raise_exceptions => true)
144
- view_path = options.delete(:views) || self.options.views || self.class.views || "./views"
145
- target_extension = File.extname(template_path)[1..-1] || "none" # retrieves explicit template extension
146
- template_path = template_path.chomp(".#{target_extension}")
147
-
148
- # Generate potential template candidates
149
- templates = Dir[File.join(view_path, template_path) + ".*"].map do |file|
150
- template_engine = File.extname(file)[1..-1].to_sym # retrieves engine extension
151
- template_file = file.sub(view_path, '').chomp(".#{template_engine}").to_sym # retrieves template filename
152
- [template_file, template_engine] unless IGNORE_FILE_PATTERN.any? { |pattern| template_engine.to_s =~ pattern }
126
+ ##
127
+ # Returns the located layout to be used for the rendered template (if available)
128
+ #
129
+ # ==== Example
130
+ #
131
+ # resolve_layout(true)
132
+ # => "/layouts/custom"
133
+ #
134
+ def resolved_layout
135
+ located_layout = resolve_template(settings.fetch_layout_path, :strict_format => true, :raise_exceptions => false)
136
+ located_layout ? located_layout[0] : false
153
137
  end
154
138
 
155
- # Resolve final template to render
156
- located_template =
157
- templates.find { |file, e| file.to_s == "#{template_path}.#{locale}.#{content_type}" } ||
158
- templates.find { |file, e| file.to_s == "#{template_path}.#{locale}" && content_type == :html } ||
159
- templates.find { |file, e| File.extname(file.to_s) == ".#{target_extension}" or e.to_s == target_extension.to_s } ||
160
- templates.find { |file, e| file.to_s == "#{template_path}.#{content_type}" } ||
161
- templates.find { |file, e| file.to_s == "#{template_path}" && content_type == :html } ||
162
- templates.any? && !options[:strict_format] && templates.first # If not strict, fall back to the first located template
163
-
164
- self.class.cache_template_file!(located_template, rendering_options) unless settings.reload_templates?
165
- raise TemplateNotFound.new("Template path '#{template_path}' could not be located!") if !located_template && options[:raise_exceptions]
166
- located_template
167
- end
139
+ ##
140
+ # Returns the template path and engine that match content_type (if present), I18n.locale.
141
+ #
142
+ # === Options
143
+ #
144
+ # :strict_format:: The resolved template must match the content_type of the request (defaults to false)
145
+ # :raise_exceptions:: Raises a +TemplateNotFound+ exception if the template cannot be located.
146
+ #
147
+ # ==== Example
148
+ #
149
+ # get "/foo", :provides => [:html, :js] do; render 'path/to/foo'; end
150
+ # # If you request "/foo.js" with I18n.locale == :ru => [:"/path/to/foo.ru.js", :erb]
151
+ # # If you request "/foo" with I18n.locale == :de => [:"/path/to/foo.de.haml", :haml]
152
+ #
153
+ def resolve_template(template_path, options={})
154
+ # Fetch cached template for rendering options
155
+ template_path = "/#{template_path}" unless template_path.to_s[0] == ?/
156
+ rendering_options = [template_path, content_type, locale]
157
+ cached_template = settings.fetch_template_file(rendering_options)
158
+ return cached_template if cached_template
159
+
160
+ # Resolve view path and options
161
+ options.reverse_merge!(DEFAULT_RENDERING_OPTIONS)
162
+ view_path = options.delete(:views) || settings.views || settings.views || "./views"
163
+ target_extension = File.extname(template_path)[1..-1] || "none" # retrieves explicit template extension
164
+ template_path = template_path.chomp(".#{target_extension}")
165
+
166
+ # Generate potential template candidates
167
+ templates = Dir[File.join(view_path, template_path) + ".*"].map do |file|
168
+ template_engine = File.extname(file)[1..-1].to_sym # retrieves engine extension
169
+ template_file = file.sub(view_path, '').chomp(".#{template_engine}").to_sym # retrieves template filename
170
+ [template_file, template_engine] unless IGNORE_FILE_PATTERN.any? { |pattern| template_engine.to_s =~ pattern }
171
+ end
172
+
173
+ # Check if we have a valid content type
174
+ valid_content_type = [:html, :plain].include?(content_type)
175
+
176
+ # Resolve final template to render
177
+ located_template =
178
+ templates.find { |file, e| file.to_s == "#{template_path}.#{locale}.#{content_type}" } ||
179
+ templates.find { |file, e| file.to_s == "#{template_path}.#{locale}" && valid_content_type } ||
180
+ templates.find { |file, e| File.extname(file.to_s) == ".#{target_extension}" or e.to_s == target_extension.to_s } ||
181
+ templates.find { |file, e| file.to_s == "#{template_path}.#{content_type}" } ||
182
+ templates.find { |file, e| file.to_s == "#{template_path}" && valid_content_type } ||
183
+ templates.any? && !options[:strict_format] && templates.first # If not strict, fall back to the first located template
184
+
185
+ settings.cache_template_file!(located_template, rendering_options) unless settings.reload_templates?
186
+ raise TemplateNotFound, "Template path '#{template_path}' could not be located in '#{view_path}'!" if !located_template && options[:raise_exceptions]
187
+ located_template
188
+ end
168
189
 
169
- ##
170
- # Return the I18n.locale if I18n is defined
171
- #
172
- def locale
173
- I18n.locale if defined?(I18n)
174
- end
190
+ ##
191
+ # Return the I18n.locale if I18n is defined
192
+ #
193
+ def locale
194
+ I18n.locale if defined?(I18n)
195
+ end
196
+ end # InstanceMethods
175
197
  end # Rendering
176
198
  end # Padrino