aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib')
-rw-r--r--actionpack/lib/abstract_controller/callbacks.rb2
-rw-r--r--actionpack/lib/action_controller/caching/actions.rb13
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb2
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb11
-rw-r--r--actionpack/lib/action_dispatch/routing/route.rb23
-rw-r--r--actionpack/lib/action_view/helpers/number_helper.rb2
-rw-r--r--actionpack/lib/action_view/template/resolver.rb105
-rw-r--r--actionpack/lib/action_view/testing/resolvers.rb12
8 files changed, 120 insertions, 50 deletions
diff --git a/actionpack/lib/abstract_controller/callbacks.rb b/actionpack/lib/abstract_controller/callbacks.rb
index 95992c2698..1943ca4436 100644
--- a/actionpack/lib/abstract_controller/callbacks.rb
+++ b/actionpack/lib/abstract_controller/callbacks.rb
@@ -14,7 +14,7 @@ module AbstractController
# Override AbstractController::Base's process_action to run the
# process_action callbacks around the normal behavior.
def process_action(method_name, *args)
- run_callbacks(:process_action, method_name) do
+ run_callbacks(:process_action, action_name) do
super
end
end
diff --git a/actionpack/lib/action_controller/caching/actions.rb b/actionpack/lib/action_controller/caching/actions.rb
index 2c8a6e4d4d..5fc6956266 100644
--- a/actionpack/lib/action_controller/caching/actions.rb
+++ b/actionpack/lib/action_controller/caching/actions.rb
@@ -56,19 +56,18 @@ module ActionController #:nodoc:
#
# caches_page :public
#
- # caches_action :index, :if => proc do |c|
- # !c.request.format.json? # cache if is not a JSON request
+ # caches_action :index, :if => proc do
+ # !request.format.json? # cache if is not a JSON request
# end
#
# caches_action :show, :cache_path => { :project => 1 },
# :expires_in => 1.hour
#
- # caches_action :feed, :cache_path => proc do |c|
- # if c.params[:user_id]
- # c.send(:user_list_url,
- # c.params[:user_id], c.params[:id])
+ # caches_action :feed, :cache_path => proc do
+ # if params[:user_id]
+ # user_list_url(params[:user_id, params[:id])
# else
- # c.send(:list_url, c.params[:id])
+ # list_url(params[:id])
# end
# end
# end
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb
index 50d8ca9484..2099fd069a 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb
@@ -1,7 +1,7 @@
<h1>
<%=h @exception.class.to_s %>
<% if @request.parameters['controller'] %>
- in <%=h @request.parameters['controller'].humanize %>Controller<% if @request.parameters['action'] %>#<%=h @request.parameters['action'] %><% end %>
+ in <%=h @request.parameters['controller'].classify.pluralize %>Controller<% if @request.parameters['action'] %>#<%=h @request.parameters['action'] %><% end %>
<% end %>
</h1>
<pre><%=h @exception.message %></pre>
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 64368ca28f..14c424f24b 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -107,7 +107,7 @@ module ActionDispatch
if @options[:format] == false
@options.delete(:format)
path
- elsif path.include?(":format") || path.end_with?('/')
+ elsif path.include?(":format") || path.end_with?('/') || path.match(/^\/?\*/)
path
else
"#{path}(.:format)"
@@ -195,8 +195,8 @@ module ActionDispatch
def request_method_condition
if via = @options[:via]
- via = Array(via).map { |m| m.to_s.dasherize.upcase }
- { :request_method => %r[^#{via.join('|')}$] }
+ list = Array(via).map { |m| m.to_s.dasherize.upcase }
+ { :request_method => list }
else
{ }
end
@@ -372,8 +372,9 @@ module ActionDispatch
# # Matches any request starting with 'path'
# match 'path' => 'c#a', :anchor => false
def match(path, options=nil)
- mapping = Mapping.new(@set, @scope, path, options || {}).to_route
- @set.add_route(*mapping)
+ mapping = Mapping.new(@set, @scope, path, options || {})
+ app, conditions, requirements, defaults, as, anchor = mapping.to_route
+ @set.add_route(app, conditions, requirements, defaults, as, anchor)
self
end
diff --git a/actionpack/lib/action_dispatch/routing/route.rb b/actionpack/lib/action_dispatch/routing/route.rb
index eae9d4ea6d..a049510182 100644
--- a/actionpack/lib/action_dispatch/routing/route.rb
+++ b/actionpack/lib/action_dispatch/routing/route.rb
@@ -12,6 +12,8 @@ module ActionDispatch
@defaults = defaults
@name = name
+ # FIXME: we should not be doing this much work in a constructor.
+
@requirements = requirements.merge(defaults)
@requirements.delete(:controller) if @requirements[:controller].is_a?(Regexp)
@requirements.delete_if { |k, v|
@@ -23,21 +25,22 @@ module ActionDispatch
conditions[:path_info] = ::Rack::Mount::Strexp.compile(path, requirements, SEPARATORS, anchor)
end
- @conditions = Hash[conditions.map { |k,v| [k, Rack::Mount::RegexpWithNamedGroups.new(v)] }]
+ @verbs = conditions[:request_method] || []
+
+ @conditions = conditions.dup
+
+ # Rack-Mount requires that :request_method be a regular expression.
+ # :request_method represents the HTTP verb that matches this route.
+ #
+ # Here we munge values before they get sent on to rack-mount.
+ @conditions[:request_method] = %r[^#{verb}$] unless @verbs.empty?
+ @conditions[:path_info] = Rack::Mount::RegexpWithNamedGroups.new(@conditions[:path_info]) if @conditions[:path_info]
@conditions.delete_if{ |k,v| k != :path_info && !valid_condition?(k) }
@requirements.delete_if{ |k,v| !valid_condition?(k) }
end
def verb
- if method = conditions[:request_method]
- case method
- when Regexp
- source = method.source.upcase
- source =~ /\A\^[-A-Z|]+\$\Z/ ? source[1..-2] : source
- else
- method.to_s.upcase
- end
- end
+ @verbs.join '|'
end
def segment_keys
diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb
index 4e44843c4b..05a9c5b4f1 100644
--- a/actionpack/lib/action_view/helpers/number_helper.rb
+++ b/actionpack/lib/action_view/helpers/number_helper.rb
@@ -472,7 +472,7 @@ module ActionView
end.keys.map{|e_name| inverted_du[e_name] }.sort_by{|e| -e}
number_exponent = number != 0 ? Math.log10(number.abs).floor : 0
- display_exponent = unit_exponents.find{|e| number_exponent >= e }
+ display_exponent = unit_exponents.find{ |e| number_exponent >= e } || 0
number /= 10 ** display_exponent
unit = case units
diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb
index 589b2a1a76..6c1063592f 100644
--- a/actionpack/lib/action_view/template/resolver.rb
+++ b/actionpack/lib/action_view/template/resolver.rb
@@ -5,6 +5,25 @@ require "action_view/template"
module ActionView
# = Action View Resolver
class Resolver
+ # Keeps all information about view path and builds virtual path.
+ class Path < String
+ attr_reader :name, :prefix, :partial, :virtual
+ alias_method :partial?, :partial
+
+ def initialize(name, prefix, partial)
+ @name, @prefix, @partial = name, prefix, partial
+ rebuild(@name, @prefix, @partial)
+ end
+
+ def rebuild(name, prefix, partial)
+ @virtual = ""
+ @virtual << "#{prefix}/" unless prefix.empty?
+ @virtual << (partial ? "_#{name}" : name)
+
+ self.replace(@virtual)
+ end
+ end
+
cattr_accessor :caching
self.caching = true
@@ -41,10 +60,7 @@ module ActionView
# Helpers that builds a path. Useful for building virtual paths.
def build_path(name, prefix, partial)
- path = ""
- path << "#{prefix}/" unless prefix.empty?
- path << (partial ? "_#{name}" : name)
- path
+ Path.new(name, prefix, partial)
end
# Handles templates caching. If a key is given and caching is on
@@ -97,25 +113,24 @@ module ActionView
end
class PathResolver < Resolver
- EXTENSION_ORDER = [:locale, :formats, :handlers]
+ EXTENSIONS = [:locale, :formats, :handlers]
+ DEFAULT_PATTERN = ":prefix/:action{.:locale,}{.:formats,}{.:handlers,}"
+
+ def initialize(pattern=nil)
+ @pattern = pattern || DEFAULT_PATTERN
+ super()
+ end
private
def find_templates(name, prefix, partial, details)
path = build_path(name, prefix, partial)
- query(path, EXTENSION_ORDER.map { |ext| details[ext] }, details[:formats])
+ extensions = Hash[EXTENSIONS.map { |ext| [ext, details[ext]] }.flatten(0)]
+ query(path, extensions, details[:formats])
end
def query(path, exts, formats)
- query = File.join(@path, path)
-
- query << exts.map { |ext|
- "{#{ext.compact.map { |e| ".#{e}" }.join(',')},}"
- }.join
-
- query.gsub!(/\{\.html,/, "{.html,.text.html,")
- query.gsub!(/\{\.text,/, "{.text,.text.plain,")
-
+ query = build_query(path, exts)
templates = []
sanitizer = Hash.new { |h,k| h[k] = Dir["#{File.dirname(k)}/*"] }
@@ -126,12 +141,28 @@ module ActionView
contents = File.open(p, "rb") {|io| io.read }
templates << Template.new(contents, File.expand_path(p), handler,
- :virtual_path => path, :format => format, :updated_at => mtime(p))
+ :virtual_path => path.virtual, :format => format, :updated_at => mtime(p))
end
templates
end
+ # Helper for building query glob string based on resolver's pattern.
+ def build_query(path, exts)
+ query = @pattern.dup
+ query.gsub!(/\:prefix(\/)?/, path.prefix.empty? ? "" : "#{path.prefix}\\1") # prefix can be empty...
+ query.gsub!(/\:action/, path.partial? ? "_#{path.name}" : path.name)
+
+ exts.each { |ext, variants|
+ query.gsub!(/\:#{ext}/, "{#{variants.compact.uniq.join(',')}}")
+ }
+
+ query.gsub!(/\.{html,/, ".{html,text.html,")
+ query.gsub!(/\.{text,/, ".{text,text.plain,")
+
+ File.expand_path(query, @path)
+ end
+
# Returns the file mtime from the filesystem.
def mtime(p)
File.stat(p).mtime
@@ -149,11 +180,47 @@ module ActionView
end
end
- # A resolver that loads files from the filesystem.
+ # A resolver that loads files from the filesystem. It allows to set your own
+ # resolving pattern. Such pattern can be a glob string supported by some variables.
+ #
+ # ==== Examples
+ #
+ # Default pattern, loads views the same way as previous versions of rails, eg. when you're
+ # looking for `users/new` it will produce query glob: `users/new{.{en},}{.{html,js},}{.{erb,haml,rjs},}`
+ #
+ # FileSystemResolver.new("/path/to/views", ":prefix/:action{.:locale,}{.:formats,}{.:handlers,}")
+ #
+ # This one allows you to keep files with different formats in seperated subdirectories,
+ # eg. `users/new.html` will be loaded from `users/html/new.erb` or `users/new.html.erb`,
+ # `users/new.js` from `users/js/new.erb` or `users/new.js.erb`, etc.
+ #
+ # FileSystemResolver.new("/path/to/views", ":prefix/{:formats/,}:action{.:locale,}{.:formats,}{.:handlers,}")
+ #
+ # If you don't specify pattern then the default will be used.
+ #
+ # In order to use any of the customized resolvers above in a Rails application, you just need
+ # to configure ActionController::Base.view_paths in an initializer, for example:
+ #
+ # ActionController::Base.view_paths = FileSystemResolver.new(
+ # Rails.root.join("app/views"),
+ # ":prefix{/:locale}/:action{.:formats,}{.:handlers,}"
+ # )
+ #
+ # ==== Pattern format and variables
+ #
+ # Pattern have to be a valid glob string, and it allows you to use the
+ # following variables:
+ #
+ # * <tt>:prefix</tt> - usualy the controller path
+ # * <tt>:action</tt> - name of the action
+ # * <tt>:locale</tt> - possible locale versions
+ # * <tt>:formats</tt> - possible request formats (for example html, json, xml...)
+ # * <tt>:handlers</tt> - possible handlers (for example erb, haml, builder...)
+ #
class FileSystemResolver < PathResolver
- def initialize(path)
+ def initialize(path, pattern=nil)
raise ArgumentError, "path already is a Resolver class" if path.is_a?(Resolver)
- super()
+ super(pattern)
@path = File.expand_path(path)
end
diff --git a/actionpack/lib/action_view/testing/resolvers.rb b/actionpack/lib/action_view/testing/resolvers.rb
index 5c5cab7c7d..773dfcbb1d 100644
--- a/actionpack/lib/action_view/testing/resolvers.rb
+++ b/actionpack/lib/action_view/testing/resolvers.rb
@@ -8,8 +8,8 @@ module ActionView #:nodoc:
class FixtureResolver < PathResolver
attr_reader :hash
- def initialize(hash = {})
- super()
+ def initialize(hash = {}, pattern=nil)
+ super(pattern)
@hash = hash
end
@@ -21,8 +21,8 @@ module ActionView #:nodoc:
def query(path, exts, formats)
query = ""
- exts.each do |ext|
- query << '(' << ext.map {|e| e && Regexp.escape(".#{e}") }.join('|') << '|)'
+ EXTENSIONS.each do |ext|
+ query << '(' << exts[ext].map {|e| e && Regexp.escape(".#{e}") }.join('|') << '|)'
end
query = /^(#{Regexp.escape(path)})#{query}$/
@@ -32,9 +32,9 @@ module ActionView #:nodoc:
next unless _path =~ query
handler, format = extract_handler_and_format(_path, formats)
templates << Template.new(source, _path, handler,
- :virtual_path => $1, :format => format, :updated_at => updated_at)
+ :virtual_path => path.virtual, :format => format, :updated_at => updated_at)
end
-
+
templates.sort_by {|t| -t.identifier.match(/^#{query}$/).captures.reject(&:blank?).size }
end
end