padrino-core 0.9.10 → 0.9.11

Sign up to get free protection for your applications and to get access to all the features.
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