diff options
Diffstat (limited to 'actionpack/lib/action_view')
-rw-r--r-- | actionpack/lib/action_view/helpers/number_helper.rb | 2 | ||||
-rw-r--r-- | actionpack/lib/action_view/helpers/prototype_helper.rb | 16 | ||||
-rw-r--r-- | actionpack/lib/action_view/helpers/scriptaculous_helper.rb | 10 | ||||
-rw-r--r-- | actionpack/lib/action_view/paths.rb | 6 | ||||
-rw-r--r-- | actionpack/lib/action_view/render/partials.rb | 7 | ||||
-rw-r--r-- | actionpack/lib/action_view/render/rendering.rb | 4 | ||||
-rw-r--r-- | actionpack/lib/action_view/template/handlers.rb | 4 | ||||
-rw-r--r-- | actionpack/lib/action_view/template/path.rb | 151 | ||||
-rw-r--r-- | actionpack/lib/action_view/template/template.rb | 2 |
9 files changed, 127 insertions, 75 deletions
diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb index dea958deaf..c02692b09a 100644 --- a/actionpack/lib/action_view/helpers/number_helper.rb +++ b/actionpack/lib/action_view/helpers/number_helper.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/float/rounding' + module ActionView module Helpers #:nodoc: # Provides methods for converting numbers into formatted strings. diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb index 6bad11e354..fb8122af35 100644 --- a/actionpack/lib/action_view/helpers/prototype_helper.rb +++ b/actionpack/lib/action_view/helpers/prototype_helper.rb @@ -973,7 +973,7 @@ module ActionView def loop_on_multiple_args(method, ids) record(ids.size>1 ? "#{javascript_object_for(ids)}.each(#{method})" : - "#{method}(#{ids.first.to_json})") + "#{method}(#{ActiveSupport::JSON.encode(ids.first)})") end def page @@ -997,7 +997,7 @@ module ActionView end def javascript_object_for(object) - object.respond_to?(:to_json) ? object.to_json : object.inspect + ActiveSupport::JSON.encode(object) end def arguments_for_call(arguments, block = nil) @@ -1139,7 +1139,7 @@ module ActionView class JavaScriptElementProxy < JavaScriptProxy #:nodoc: def initialize(generator, id) @id = id - super(generator, "$(#{id.to_json})") + super(generator, "$(#{ActiveSupport::JSON.encode(id)})") end # Allows access of element attributes through +attribute+. Examples: @@ -1184,10 +1184,12 @@ module ActionView true end - def to_json(options = nil) + def rails_to_json(options = nil) @variable end + alias to_json rails_to_json + private def append_to_function_chain!(call) @generator << @variable if @empty @@ -1211,7 +1213,7 @@ module ActionView enumerate :eachSlice, :variable => variable, :method_args => [number], :yield_args => %w(value index), :return => true, &block else add_variable_assignment!(variable) - append_enumerable_function!("eachSlice(#{number.to_json});") + append_enumerable_function!("eachSlice(#{ActiveSupport::JSON.encode(number)});") end end @@ -1232,7 +1234,7 @@ module ActionView def pluck(variable, property) add_variable_assignment!(variable) - append_enumerable_function!("pluck(#{property.to_json});") + append_enumerable_function!("pluck(#{ActiveSupport::JSON.encode(property)});") end def zip(variable, *arguments, &block) @@ -1296,7 +1298,7 @@ module ActionView class JavaScriptElementCollectionProxy < JavaScriptCollectionProxy #:nodoc:\ def initialize(generator, pattern) - super(generator, "$$(#{pattern.to_json})") + super(generator, "$$(#{ActiveSupport::JSON.encode(pattern)})") end end end diff --git a/actionpack/lib/action_view/helpers/scriptaculous_helper.rb b/actionpack/lib/action_view/helpers/scriptaculous_helper.rb index e16935ea87..04af2781d7 100644 --- a/actionpack/lib/action_view/helpers/scriptaculous_helper.rb +++ b/actionpack/lib/action_view/helpers/scriptaculous_helper.rb @@ -43,7 +43,7 @@ module ActionView # You can change the behaviour with various options, see # http://script.aculo.us for more documentation. def visual_effect(name, element_id = false, js_options = {}) - element = element_id ? element_id.to_json : "element" + element = element_id ? ActiveSupport::JSON.encode(element_id) : "element" js_options[:queue] = if js_options[:queue].is_a?(Hash) '{' + js_options[:queue].map {|k, v| k == :limit ? "#{k}:#{v}" : "#{k}:'#{v}'" }.join(',') + '}' @@ -138,7 +138,7 @@ module ActionView end def sortable_element_js(element_id, options = {}) #:nodoc: - options[:with] ||= "Sortable.serialize(#{element_id.to_json})" + options[:with] ||= "Sortable.serialize(#{ActiveSupport::JSON.encode(element_id)})" options[:onUpdate] ||= "function(){" + remote_function(options) + "}" options.delete_if { |key, value| PrototypeHelper::AJAX_OPTIONS.include?(key) } @@ -149,7 +149,7 @@ module ActionView options[:containment] = array_or_string_for_javascript(options[:containment]) if options[:containment] options[:only] = array_or_string_for_javascript(options[:only]) if options[:only] - %(Sortable.create(#{element_id.to_json}, #{options_for_javascript(options)});) + %(Sortable.create(#{ActiveSupport::JSON.encode(element_id)}, #{options_for_javascript(options)});) end # Makes the element with the DOM ID specified by +element_id+ draggable. @@ -164,7 +164,7 @@ module ActionView end def draggable_element_js(element_id, options = {}) #:nodoc: - %(new Draggable(#{element_id.to_json}, #{options_for_javascript(options)});) + %(new Draggable(#{ActiveSupport::JSON.encode(element_id)}, #{options_for_javascript(options)});) end # Makes the element with the DOM ID specified by +element_id+ receive @@ -219,7 +219,7 @@ module ActionView # Confirmation happens during the onDrop callback, so it can be removed from the options options.delete(:confirm) if options[:confirm] - %(Droppables.add(#{element_id.to_json}, #{options_for_javascript(options)});) + %(Droppables.add(#{ActiveSupport::JSON.encode(element_id)}, #{options_for_javascript(options)});) end end end diff --git a/actionpack/lib/action_view/paths.rb b/actionpack/lib/action_view/paths.rb index 1d0279889c..e48088f344 100644 --- a/actionpack/lib/action_view/paths.rb +++ b/actionpack/lib/action_view/paths.rb @@ -33,18 +33,18 @@ module ActionView #:nodoc: super(*objs.map { |obj| self.class.type_cast(obj) }) end - def find_by_parts(path, extension = nil, prefix = nil, partial = false) + def find_by_parts(path, details = {}, prefix = nil, partial = false) template_path = path.sub(/^\//, '') each do |load_path| - if template = load_path.find_by_parts(template_path, extension, prefix, partial) + if template = load_path.find_by_parts(template_path, details, prefix, partial) return template end end Template.new(path, self) rescue ActionView::MissingTemplate => e - extension ||= [] + extension = details[:formats] || [] raise ActionView::MissingTemplate.new(self, "#{prefix}/#{path}.{#{extension.join(",")}}") end diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb index e337dcb63b..43f8a1edf8 100644 --- a/actionpack/lib/action_view/render/partials.rb +++ b/actionpack/lib/action_view/render/partials.rb @@ -187,6 +187,7 @@ module ActionView path = ActionController::RecordIdentifier.partial_path(object, controller_path) end _, _, prefix, object = parts = partial_parts(path, options) + parts[1] = {:formats => parts[1]} template = find_by_parts(*parts) _render_partial_object(template, options, (object unless object == true)) end @@ -225,7 +226,7 @@ module ActionView def _render_partial_with_layout(layout, options) if layout prefix = controller && !layout.include?("/") ? controller.controller_path : nil - layout = find_by_parts(layout, formats, prefix, true) + layout = find_by_parts(layout, {:formats => formats}, prefix, true) end content = _render_partial(options) return _render_content_with_layout(content, layout, options[:locals]) @@ -253,7 +254,7 @@ module ActionView def _render_partial_with_layout(layout, options) if layout prefix = controller && !layout.include?("/") ? controller.controller_path : nil - layout = find_by_parts(layout, formats, prefix, true) + layout = find_by_parts(layout, {:formats => formats}, prefix, true) end content = _render_partial(options) return _render_content_with_layout(content, layout, options[:locals]) @@ -321,7 +322,7 @@ module ActionView def _pick_partial_template(partial_path) #:nodoc: prefix = controller_path unless partial_path.include?('/') - find_by_parts(partial_path, formats, prefix, true) + find_by_parts(partial_path, {:formats => formats}, prefix, true) end memoize :_pick_partial_template end diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb index a9b2acecd5..4213b09e48 100644 --- a/actionpack/lib/action_view/render/rendering.rb +++ b/actionpack/lib/action_view/render/rendering.rb @@ -23,10 +23,10 @@ module ActionView return _render_partial_with_layout(layout, options) if options.key?(:partial) return _render_partial_with_block(layout, block, options) if block_given? - layout = find_by_parts(layout, formats) if layout + layout = find_by_parts(layout, {:formats => formats}) if layout if file = options[:file] - template = find_by_parts(file, formats) + template = find_by_parts(file, {:formats => formats}) _render_template_with_layout(template, layout, :locals => options[:locals]) elsif inline = options[:inline] _render_inline(inline, layout, options) diff --git a/actionpack/lib/action_view/template/handlers.rb b/actionpack/lib/action_view/template/handlers.rb index fb85f28851..448ab6731b 100644 --- a/actionpack/lib/action_view/template/handlers.rb +++ b/actionpack/lib/action_view/template/handlers.rb @@ -16,6 +16,10 @@ module ActionView #:nodoc: @@template_handlers = {} @@default_template_handlers = nil + + def self.extensions + @@template_handlers.keys + end # Register a class that knows how to handle template files with the given # extension. This can be used to implement new template types. diff --git a/actionpack/lib/action_view/template/path.rb b/actionpack/lib/action_view/template/path.rb index 9709549b70..660a7e91a2 100644 --- a/actionpack/lib/action_view/template/path.rb +++ b/actionpack/lib/action_view/template/path.rb @@ -1,13 +1,81 @@ module ActionView class Template + # Abstract super class class Path - attr_reader :path, :paths - delegate :hash, :inspect, :to => :path - def initialize(options) - @cache = options[:cache] + @cache = options[:cache] + @cached = {} end - + + # Normalizes the arguments and passes it on to find_template + def find_by_parts(*args) + find_all_by_parts(*args).first + end + + def find_all_by_parts(name, details = {}, prefix = nil, partial = nil) + details[:locales] = [I18n.locale] + name = name.to_s.gsub(handler_matcher, '').split("/") + find_templates(name.pop, details, [prefix, *name].compact.join("/"), partial) + end + + private + + # This is what child classes implement. No defaults are needed + # because Path guarentees that the arguments are present and + # normalized. + def find_templates(name, details, prefix, partial) + raise NotImplementedError + end + + # TODO: Refactor this to abstract out the file system + def initialize_template(file) + t = Template.new(file.split("#{self}/").last, self) + t.load! + t + end + + def valid_handlers + @valid_handlers ||= TemplateHandlers.extensions + end + + def handler_matcher + @handler_matcher ||= begin + e = valid_handlers.join('|') + /\.(?:#{e})$/ + end + end + + def handler_glob + e = TemplateHandlers.extensions.join(',') + ".{#{e}}" + end + + def formats_glob + @formats_glob ||= begin + formats = Mime::SET.map { |m| m.symbol } + '{' + formats.map { |l| ".#{l}," }.join + '}' + end + end + + def cached(key) + return yield unless @cache + return @cached[key] if @cached.key?(key) + @cached[key] = yield + end + end + + class FileSystemPath < Path + + def initialize(path, options = {}) + raise ArgumentError, "path already is a Path class" if path.is_a?(Path) + super(options) + @path = path + end + + # TODO: This is the currently needed API. Make this suck less + # ==== <suck> + attr_reader :path + def to_s if defined?(RAILS_ROOT) path.to_s.sub(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}\//, '') @@ -27,61 +95,36 @@ module ActionView def eql?(path) to_str == path.to_str end - - def find_by_parts(name, extensions = nil, prefix = nil, partial = nil) - path = prefix ? "#{prefix}/" : "" + # ==== </suck> - name = name.to_s.split("/") - name[-1] = "_#{name[-1]}" if partial - - path << name.join("/") - - template = nil - - Array(extensions).each do |extension| - extensioned_path = extension ? "#{path}.#{extension}" : path - break if (template = find_template(extensioned_path)) + def find_templates(name, details, prefix, partial) + if glob = parts_to_glob(name, details, prefix, partial) + cached(glob) do + Dir[glob].map do |path| + initialize_template(path) unless File.directory?(path) + end.compact + end end - template || find_template(path) end - - private - def create_template(file) - Template.new(file.split("#{self}/").last, self) - end - end - - class FileSystemPath < Path - def initialize(path, options = {}) - raise ArgumentError, "path already is a Path class" if path.is_a?(Path) - - super(options) - @path, @paths = path, {} - - # **/*/** is a hax for symlinked directories - load_templates("#{@path}/{**/*,**}/**") if @cache - end - - private - - def load_template(template) - template.load! - template.accessible_paths.each do |path| - @paths[path] = template - end - end - - def find_template(path) - load_templates("#{@path}/#{path}{,.*}") unless @cache - @paths[path] - end - def load_templates(glob) - Dir[glob].each do |file| - load_template(create_template(file)) unless File.directory?(file) + private + + def parts_to_glob(name, details, prefix, partial) + path = "" + path << "#{prefix}/" unless prefix.empty? + path << (partial ? "_#{name}" : name) + + extensions = "" + [:locales, :formats].each do |k| + extensions << if exts = details[k] + '{' + exts.map {|e| ".#{e},"}.join + '}' + else + k == :formats ? formats_glob : '' + end end + + "#{@path}/#{path}#{extensions}#{handler_glob}" end - end end end
\ No newline at end of file diff --git a/actionpack/lib/action_view/template/template.rb b/actionpack/lib/action_view/template/template.rb index b6967a2013..e541336613 100644 --- a/actionpack/lib/action_view/template/template.rb +++ b/actionpack/lib/action_view/template/template.rb @@ -101,7 +101,7 @@ module ActionView #:nodoc: end def content_type - format.gsub('.', '/') + format && format.gsub('.', '/') end private |