From 8bf74c30fe276606214850ae2de76fe0efb08d94 Mon Sep 17 00:00:00 2001 From: rick Date: Sun, 8 Jun 2008 22:26:30 -0400 Subject: change some more TimeZone references to ActiveSupport::TimeZone --- actionpack/lib/action_view/helpers/form_options_helper.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb index e0a097e367..90bd99a861 100644 --- a/actionpack/lib/action_view/helpers/form_options_helper.rb +++ b/actionpack/lib/action_view/helpers/form_options_helper.rb @@ -304,7 +304,7 @@ module ActionView # # NOTE: Only the option tags are returned, you have to wrap this call in # a regular HTML select tag. - def time_zone_options_for_select(selected = nil, priority_zones = nil, model = TimeZone) + def time_zone_options_for_select(selected = nil, priority_zones = nil, model = ActiveSupport::TimeZone) zone_options = "" zones = model.all @@ -417,7 +417,7 @@ module ActionView value = value(object) content_tag("select", add_options( - time_zone_options_for_select(value || options[:default], priority_zones, options[:model] || TimeZone), + time_zone_options_for_select(value || options[:default], priority_zones, options[:model] || ActiveSupport::TimeZone), options, value ), html_options ) -- cgit v1.2.3 From 64637da284ed4685591c178202ee103e6bee71cf Mon Sep 17 00:00:00 2001 From: rick Date: Mon, 9 Jun 2008 12:06:23 -0400 Subject: add deprecation for the #concat helper's 2nd argument, which is no longer needed --- actionpack/lib/action_view/helpers/text_helper.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index f81f7eded6..3077c8f970 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -25,7 +25,10 @@ module ActionView # end # # will either display "Logged in!" or a login link # %> - def concat(string) + def concat(string, unused_binding = nil) + if unused_binding + ActiveSupport::Deprecation.warn("The binding argument of #concat is no longer needed. Please remove it from your views and helpers.") + end if @output_buffer && string @output_buffer << string else -- cgit v1.2.3 From c440c9b199d7474e356472616ef03f9c7e17c405 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 19 Jun 2008 17:18:07 -0700 Subject: Move erb_trim_mode setting to the ERB template handler. Keep a Base.erb_trim_mode= delegator around. --- actionpack/lib/action_view/base.rb | 7 +++---- actionpack/lib/action_view/template_handlers/erb.rb | 7 ++++++- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 4f3cc46a14..197455a933 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -161,10 +161,9 @@ module ActionView #:nodoc: attr_accessor :output_buffer - # Specify trim mode for the ERB compiler. Defaults to '-'. - # See ERb documentation for suitable values. - @@erb_trim_mode = '-' - cattr_accessor :erb_trim_mode + class << self + delegate :erb_trim_mode=, :to => 'ActionView::TemplateHandlers::ERB' + end # Specify whether file modification times should be checked to see if a template needs recompilation @@cache_template_loading = false diff --git a/actionpack/lib/action_view/template_handlers/erb.rb b/actionpack/lib/action_view/template_handlers/erb.rb index ad4ccc7c42..0733b3e3c2 100644 --- a/actionpack/lib/action_view/template_handlers/erb.rb +++ b/actionpack/lib/action_view/template_handlers/erb.rb @@ -42,8 +42,13 @@ module ActionView class ERB < TemplateHandler include Compilable + # Specify trim mode for the ERB compiler. Defaults to '-'. + # See ERb documentation for suitable values. + cattr_accessor :erb_trim_mode + self.erb_trim_mode = '-' + def compile(template) - ::ERB.new(template.source, nil, @view.erb_trim_mode, '@output_buffer').src + ::ERB.new(template.source, nil, erb_trim_mode, '@output_buffer').src end def cache_fragment(block, name = {}, options = nil) #:nodoc: -- cgit v1.2.3 From 72f93b581f1d1a7496ccebbd90578714c171c5a5 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 19 Jun 2008 22:03:27 -0700 Subject: Check whether blocks are called from erb using a special __in_erb_template variable visible in block binding. --- .../lib/action_view/helpers/capture_helper.rb | 8 +++- .../lib/action_view/helpers/form_tag_helper.rb | 44 +++++++++++----------- actionpack/lib/action_view/helpers/tag_helper.rb | 32 ++++++++++++---- actionpack/lib/action_view/helpers/text_helper.rb | 6 +-- .../action_view/template_handlers/compilable.rb | 8 +++- .../lib/action_view/template_handlers/erb.rb | 3 +- 6 files changed, 62 insertions(+), 39 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/capture_helper.rb b/actionpack/lib/action_view/helpers/capture_helper.rb index 9cd9d3d06a..990c30b90d 100644 --- a/actionpack/lib/action_view/helpers/capture_helper.rb +++ b/actionpack/lib/action_view/helpers/capture_helper.rb @@ -31,10 +31,13 @@ module ActionView # # def capture(*args, &block) - if output_buffer + # Return captured buffer in erb. + if block_called_from_erb?(block) with_output_buffer { block.call(*args) } + + # Return block result otherwise, but protect buffer also. else - block.call(*args) + with_output_buffer { return block.call(*args) } end end @@ -117,6 +120,7 @@ module ActionView ivar = "@content_for_#{name}" content = capture(&block) if block_given? instance_variable_set(ivar, "#{instance_variable_get(ivar)}#{content}") + nil end private diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb index 3a97f1390f..ccebec3692 100644 --- a/actionpack/lib/action_view/helpers/form_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb @@ -6,7 +6,7 @@ module ActionView # Provides a number of methods for creating form tags that doesn't rely on an Active Record object assigned to the template like # FormHelper does. Instead, you provide the names and values manually. # - # NOTE: The HTML options disabled, readonly, and multiple can all be treated as booleans. So specifying + # NOTE: The HTML options disabled, readonly, and multiple can all be treated as booleans. So specifying # :disabled => true will give disabled="disabled". module FormTagHelper # Starts a form tag that points the action to an url configured with url_for_options just like @@ -20,15 +20,15 @@ module ActionView # * A list of parameters to feed to the URL the form will be posted to. # # ==== Examples - # form_tag('/posts') + # form_tag('/posts') # # =>
# - # form_tag('/posts/1', :method => :put) + # form_tag('/posts/1', :method => :put) # # => # - # form_tag('/upload', :multipart => true) + # form_tag('/upload', :multipart => true) # # => - # + # # <% form_tag '/posts' do -%> #
<%= submit_tag 'Save' %>
# <% end -%> @@ -88,7 +88,7 @@ module ActionView # * :size - The number of visible characters that will fit in the input. # * :maxlength - The maximum number of characters that the browser will allow the user to enter. # * Any other key creates standard HTML attributes for the tag. - # + # # ==== Examples # text_field_tag 'name' # # => @@ -146,13 +146,13 @@ module ActionView # # => # # hidden_field_tag 'collected_input', '', :onchange => "alert('Input collected!')" - # # => def hidden_field_tag(name, value = nil, options = {}) text_field_tag(name, value, options.stringify_keys.update("type" => "hidden")) end - # Creates a file upload field. If you are using file uploads then you will also need + # Creates a file upload field. If you are using file uploads then you will also need # to set the multipart option for the form tag: # # <%= form_tag { :action => "post" }, { :multipart => true } %> @@ -160,7 +160,7 @@ module ActionView # <%= submit_tag %> # <%= end_form_tag %> # - # The specified URL will then be passed a File object containing the selected file, or if the field + # The specified URL will then be passed a File object containing the selected file, or if the field # was left blank, a StringIO object. # # ==== Options @@ -181,7 +181,7 @@ module ActionView # # => # # file_field_tag 'user_pic', :accept => 'image/png,image/gif,image/jpeg' - # # => + # # => # # file_field_tag 'file', :accept => 'text/html', :class => 'upload', :value => 'index.html' # # => @@ -286,7 +286,7 @@ module ActionView tag :input, html_options end - # Creates a radio button; use groups of radio buttons named the same to allow users to + # Creates a radio button; use groups of radio buttons named the same to allow users to # select from a group of options. # # ==== Options @@ -313,14 +313,14 @@ module ActionView tag :input, html_options end - # Creates a submit button with the text value as the caption. + # Creates a submit button with the text value as the caption. # # ==== Options # * :confirm => 'question?' - This will add a JavaScript confirm # prompt with the question specified. If the user accepts, the form is # processed normally, otherwise no action is taken. # * :disabled - If true, the user will not be able to use this input. - # * :disable_with - Value of this parameter will be used as the value for a disabled version + # * :disable_with - Value of this parameter will be used as the value for a disabled version # of the submit button when the form is submitted. # * Any other key creates standard HTML options for the tag. # @@ -335,7 +335,7 @@ module ActionView # # => # # submit_tag "Complete sale", :disable_with => "Please wait..." - # # => # # submit_tag nil, :class => "form_submit" @@ -346,7 +346,7 @@ module ActionView # # name="commit" type="submit" value="Edit" /> def submit_tag(value = "Save changes", options = {}) options.stringify_keys! - + if disable_with = options.delete("disable_with") options["onclick"] = [ "this.setAttribute('originalValue', this.value)", @@ -358,15 +358,15 @@ module ActionView "return result;", ].join(";") end - + if confirm = options.delete("confirm") options["onclick"] ||= '' options["onclick"] += "return #{confirm_javascript_function(confirm)};" end - + tag :input, { "type" => "submit", "name" => "commit", "value" => value }.update(options.stringify_keys) end - + # Displays an image which when clicked will submit the form. # # source is passed to AssetTagHelper#image_path @@ -412,7 +412,7 @@ module ActionView concat(content) concat("") end - + private def html_options_for_form(url_for_options, options, *parameters_for_url) returning options.stringify_keys do |html_options| @@ -420,7 +420,7 @@ module ActionView html_options["action"] = url_for(url_for_options, *parameters_for_url) end end - + def extra_tags_for_form(html_options) case method = html_options.delete("method").to_s when /^get$/i # must be case-insentive, but can't use downcase as might be nil @@ -434,12 +434,12 @@ module ActionView content_tag(:div, tag(:input, :type => "hidden", :name => "_method", :value => method) + token_tag, :style => 'margin:0;padding:0') end end - + def form_tag_html(html_options) extra_tags = extra_tags_for_form(html_options) tag(:form, html_options, true) + extra_tags end - + def form_tag_in_block(html_options, &block) content = capture(&block) concat(form_tag_html(html_options)) diff --git a/actionpack/lib/action_view/helpers/tag_helper.rb b/actionpack/lib/action_view/helpers/tag_helper.rb index e1abec1847..649ec87a24 100644 --- a/actionpack/lib/action_view/helpers/tag_helper.rb +++ b/actionpack/lib/action_view/helpers/tag_helper.rb @@ -12,14 +12,14 @@ module ActionView BOOLEAN_ATTRIBUTES = %w(disabled readonly multiple).to_set BOOLEAN_ATTRIBUTES.merge(BOOLEAN_ATTRIBUTES.map(&:to_sym)) - # Returns an empty HTML tag of type +name+ which by default is XHTML - # compliant. Set +open+ to true to create an open tag compatible - # with HTML 4.0 and below. Add HTML attributes by passing an attributes + # Returns an empty HTML tag of type +name+ which by default is XHTML + # compliant. Set +open+ to true to create an open tag compatible + # with HTML 4.0 and below. Add HTML attributes by passing an attributes # hash to +options+. Set +escape+ to false to disable attribute value # escaping. # # ==== Options - # The +options+ hash is used with attributes with no value like (disabled and + # The +options+ hash is used with attributes with no value like (disabled and # readonly), which you can give a value of true in the +options+ hash. You can use # symbols or strings for the attribute names. # @@ -30,7 +30,7 @@ module ActionView # tag("br", nil, true) # # =>
# - # tag("input", { :type => 'text', :disabled => true }) + # tag("input", { :type => 'text', :disabled => true }) # # => # # tag("img", { :src => "open & shut.png" }) @@ -43,13 +43,13 @@ module ActionView end # Returns an HTML block tag of type +name+ surrounding the +content+. Add - # HTML attributes by passing an attributes hash to +options+. + # HTML attributes by passing an attributes hash to +options+. # Instead of passing the content as an argument, you can also use a block # in which case, you pass your +options+ as the second parameter. # Set escape to false to disable attribute value escaping. # # ==== Options - # The +options+ hash is used with attributes with no value like (disabled and + # The +options+ hash is used with attributes with no value like (disabled and # readonly), which you can give a value of true in the +options+ hash. You can use # symbols or strings for the attribute names. # @@ -68,7 +68,13 @@ module ActionView def content_tag(name, content_or_options_with_block = nil, options = nil, escape = true, &block) if block_given? options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash) - concat(content_tag_string(name, capture(&block), options, escape)) + content_tag = content_tag_string(name, capture(&block), options, escape) + + if block_called_from_erb?(block) + concat(content_tag) + else + content_tag + end else content_tag_string(name, content_or_options_with_block, options, escape) end @@ -102,6 +108,16 @@ module ActionView end private + BLOCK_CALLED_FROM_ERB = 'defined? __in_erb_template' + + # Check whether we're called from an erb template. + # We'd return a string in any other case, but erb <%= ... %> + # can't take an <% end %> later on, so we have to use <% ... %> + # and implicitly concat. + def block_called_from_erb?(block) + eval(BLOCK_CALLED_FROM_ERB, block) + end + def content_tag_string(name, content, options, escape = true) tag_options = tag_options(options, escape) if options "<#{name}#{tag_options}>#{content}" diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index a1a91f6b3d..d98c5bd0d5 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -30,11 +30,7 @@ module ActionView ActiveSupport::Deprecation.warn("The binding argument of #concat is no longer needed. Please remove it from your views and helpers.") end - if output_buffer && string - output_buffer << string - else - string - end + output_buffer << string end if RUBY_VERSION < '1.9' diff --git a/actionpack/lib/action_view/template_handlers/compilable.rb b/actionpack/lib/action_view/template_handlers/compilable.rb index 1aef81ba1a..783456ab53 100644 --- a/actionpack/lib/action_view/template_handlers/compilable.rb +++ b/actionpack/lib/action_view/template_handlers/compilable.rb @@ -106,7 +106,13 @@ module ActionView locals_code << "#{key} = local_assigns[:#{key}]\n" end - "def #{render_symbol}(local_assigns)\nold_output_buffer = output_buffer;#{locals_code}#{body}\nensure\nself.output_buffer = old_output_buffer\nend" + <<-end_src + def #{render_symbol}(local_assigns) + old_output_buffer = output_buffer;#{locals_code}#{body} + ensure + self.output_buffer = old_output_buffer + end + end_src end # Return true if the given template was compiled for a superset of the keys in local_assigns diff --git a/actionpack/lib/action_view/template_handlers/erb.rb b/actionpack/lib/action_view/template_handlers/erb.rb index 0733b3e3c2..458416b6cb 100644 --- a/actionpack/lib/action_view/template_handlers/erb.rb +++ b/actionpack/lib/action_view/template_handlers/erb.rb @@ -48,7 +48,8 @@ module ActionView self.erb_trim_mode = '-' def compile(template) - ::ERB.new(template.source, nil, erb_trim_mode, '@output_buffer').src + src = ::ERB.new(template.source, nil, erb_trim_mode, '@output_buffer').src + "__in_erb_template=true;#{src}" end def cache_fragment(block, name = {}, options = nil) #:nodoc: -- cgit v1.2.3 From f4ccc179530d5b9436da87d3c221dfa8fa89119a Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sat, 21 Jun 2008 14:54:10 -0700 Subject: Performance: javascript helper tweaks to speed up escaping and reduce object allocations when building options strings --- .../lib/action_view/helpers/javascript_helper.rb | 129 ++++++++++++--------- actionpack/lib/action_view/helpers/tag_helper.rb | 2 +- actionpack/lib/action_view/helpers/url_helper.rb | 2 +- 3 files changed, 73 insertions(+), 60 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb index 7404a251e4..31571de6c4 100644 --- a/actionpack/lib/action_view/helpers/javascript_helper.rb +++ b/actionpack/lib/action_view/helpers/javascript_helper.rb @@ -4,10 +4,10 @@ require 'action_view/helpers/prototype_helper' module ActionView module Helpers # Provides functionality for working with JavaScript in your views. - # + # # == Ajax, controls and visual effects - # - # * For information on using Ajax, see + # + # * For information on using Ajax, see # ActionView::Helpers::PrototypeHelper. # * For information on using controls and visual effects, see # ActionView::Helpers::ScriptaculousHelper. @@ -20,22 +20,22 @@ module ActionView # and ActionView::Helpers::ScriptaculousHelper), you must do one of the # following: # - # * Use <%= javascript_include_tag :defaults %> in the HEAD - # section of your page (recommended): This function will return + # * Use <%= javascript_include_tag :defaults %> in the HEAD + # section of your page (recommended): This function will return # references to the JavaScript files created by the +rails+ command in # your public/javascripts directory. Using it is recommended as - # the browser can then cache the libraries instead of fetching all the + # the browser can then cache the libraries instead of fetching all the # functions anew on every request. - # * Use <%= javascript_include_tag 'prototype' %>: As above, but + # * Use <%= javascript_include_tag 'prototype' %>: As above, but # will only include the Prototype core library, which means you are able - # to use all basic AJAX functionality. For the Scriptaculous-based - # JavaScript helpers, like visual effects, autocompletion, drag and drop + # to use all basic AJAX functionality. For the Scriptaculous-based + # JavaScript helpers, like visual effects, autocompletion, drag and drop # and so on, you should use the method described above. # * Use <%= define_javascript_functions %>: this will copy all the # JavaScript support functions within a single script block. Not # recommended. # - # For documentation on +javascript_include_tag+ see + # For documentation on +javascript_include_tag+ see # ActionView::Helpers::AssetTagHelper. module JavaScriptHelper unless const_defined? :JAVASCRIPT_PATH @@ -43,13 +43,13 @@ module ActionView end include PrototypeHelper - - # Returns a link that will trigger a JavaScript +function+ using the + + # Returns a link that will trigger a JavaScript +function+ using the # onclick handler and return false after the fact. # # The +function+ argument can be omitted in favor of an +update_page+ # block, which evaluates to a string when the template is rendered - # (instead of making an Ajax request first). + # (instead of making an Ajax request first). # # Examples: # link_to_function "Greeting", "alert('Hello world!')" @@ -70,36 +70,31 @@ module ActionView # Show me more # def link_to_function(name, *args, &block) - html_options = args.extract_options! - function = args[0] || '' - - html_options.symbolize_keys! - function = update_page(&block) if block_given? - content_tag( - "a", name, - html_options.merge({ - :href => html_options[:href] || "#", - :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function}; return false;" - }) - ) + html_options = args.extract_options!.symbolize_keys! + + function = block_given? ? update_page(&block) : args[0] || '' + onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function}; return false;" + href = html_options[:href] || '#' + + content_tag(:a, name, html_options.merge(:href => href, :onclick => onclick)) end - - # Returns a button that'll trigger a JavaScript +function+ using the + + # Returns a button that'll trigger a JavaScript +function+ using the # onclick handler. # # The +function+ argument can be omitted in favor of an +update_page+ # block, which evaluates to a string when the template is rendered - # (instead of making an Ajax request first). + # (instead of making an Ajax request first). # # Examples: # button_to_function "Greeting", "alert('Hello world!')" @@ -111,45 +106,56 @@ module ActionView # page[:details].visual_effect :toggle_slide # end def button_to_function(name, *args, &block) - html_options = args.extract_options! - function = args[0] || '' - - html_options.symbolize_keys! - function = update_page(&block) if block_given? - tag(:input, html_options.merge({ - :type => "button", :value => name, - :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};" - })) + html_options = args.extract_options!.symbolize_keys! + + function = block_given? ? update_page(&block) : args[0] || '' + onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function};" + + tag(:input, html_options.merge(:type => 'button', :value => name, :onclick => onclick)) end - # Includes the Action Pack JavaScript libraries inside a single ' end + + JS_ESCAPE_MAP = { + '\\' => '\\\\', + ' '<\/', + "\r\n" => '\n', + "\n" => '\n', + "\r" => '\n', + '"' => '\\"', + "'" => "\\'" } + # Escape carrier returns and single and double quotes for JavaScript segments. def escape_javascript(javascript) - (javascript || '').gsub('\\','\0\0').gsub(' # # +html_options+ may be a hash of attributes for the # # Instead of passing the content as an argument, you can also use a block @@ -180,30 +186,37 @@ module ActionView content_or_options_with_block end - tag = content_tag("script", javascript_cdata_section(content), html_options.merge(:type => Mime::JS)) + tag = content_tag(:script, javascript_cdata_section(content), html_options.merge(:type => Mime::JS)) - block_given? ? concat(tag) : tag + if block_called_from_erb?(block) + concat(tag) + else + tag + end end def javascript_cdata_section(content) #:nodoc: "\n//#{cdata_section("\n#{content}\n//")}\n" end - + protected def options_for_javascript(options) - '{' + options.map {|k, v| "#{k}:#{v}"}.sort.join(', ') + '}' + if options.empty? + '{}' + else + "{#{options.keys.map { |k| "#{k}:#{options[k]}" }.sort.join(', ')}}" + end end - + def array_or_string_for_javascript(option) - js_option = if option.kind_of?(Array) + if option.kind_of?(Array) "['#{option.join('\',\'')}']" elsif !option.nil? "'#{option}'" end - js_option end end - + JavascriptHelper = JavaScriptHelper unless const_defined? :JavascriptHelper end end diff --git a/actionpack/lib/action_view/helpers/tag_helper.rb b/actionpack/lib/action_view/helpers/tag_helper.rb index 649ec87a24..aeafd3906d 100644 --- a/actionpack/lib/action_view/helpers/tag_helper.rb +++ b/actionpack/lib/action_view/helpers/tag_helper.rb @@ -115,7 +115,7 @@ module ActionView # can't take an <% end %> later on, so we have to use <% ... %> # and implicitly concat. def block_called_from_erb?(block) - eval(BLOCK_CALLED_FROM_ERB, block) + block && eval(BLOCK_CALLED_FROM_ERB, block) end def content_tag_string(name, content, options, escape = true) diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb index baecd304cd..d5b7255642 100644 --- a/actionpack/lib/action_view/helpers/url_helper.rb +++ b/actionpack/lib/action_view/helpers/url_helper.rb @@ -535,7 +535,7 @@ module ActionView when method "#{method_javascript_function(method, url, href)}return false;" when popup - popup_javascript_function(popup) + 'return false;' + "#{popup_javascript_function(popup)}return false;" else html_options["onclick"] end -- cgit v1.2.3 From bb6e8eea5a8190aaab67da0a7efedb3bb3d9fccb Mon Sep 17 00:00:00 2001 From: Tammer Saleh Date: Fri, 20 Jun 2008 15:21:04 -0400 Subject: Fixed polymorphic_url to be able to handle singleton resources. Example usage: polymorphic_url([:admin, @user, :blog, @post]) # => admin_user_blog_post_url(@user, @post) [#461 state:resolved] --- .../lib/action_controller/polymorphic_routes.rb | 37 +++++++++++++++------- 1 file changed, 25 insertions(+), 12 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/polymorphic_routes.rb b/actionpack/lib/action_controller/polymorphic_routes.rb index 509fa6a08e..7c30bf0778 100644 --- a/actionpack/lib/action_controller/polymorphic_routes.rb +++ b/actionpack/lib/action_controller/polymorphic_routes.rb @@ -48,6 +48,9 @@ module ActionController # # # calls post_url(post) # polymorphic_url(post) # => "http://example.com/posts/1" + # polymorphic_url([blog, post]) # => "http://example.com/blogs/1/posts/1" + # polymorphic_url([:admin, blog, post]) # => "http://example.com/admin/blogs/1/posts/1" + # polymorphic_url([user, :blog, post]) # => "http://example.com/users/1/blog/posts/1" # # ==== Options # @@ -83,8 +86,6 @@ module ActionController else [ record_or_hash_or_array ] end - args << format if format - inflection = case when options[:action].to_s == "new" @@ -96,6 +97,9 @@ module ActionController else :singular end + + args.delete_if {|arg| arg.is_a?(Symbol) || arg.is_a?(String)} + args << format if format named_route = build_named_route_call(record_or_hash_or_array, namespace, inflection, options) send!(named_route, *args) @@ -136,11 +140,19 @@ module ActionController else record = records.pop route = records.inject("") do |string, parent| - string << "#{RecordIdentifier.send!("singular_class_name", parent)}_" + if parent.is_a?(Symbol) || parent.is_a?(String) + string << "#{parent}_" + else + string << "#{RecordIdentifier.send!("singular_class_name", parent)}_" + end end end - route << "#{RecordIdentifier.send!("#{inflection}_class_name", record)}_" + if record.is_a?(Symbol) || record.is_a?(String) + route << "#{record}_" + else + route << "#{RecordIdentifier.send!("#{inflection}_class_name", record)}_" + end action_prefix(options) + namespace + route + routing_type(options).to_s end @@ -163,16 +175,17 @@ module ActionController end end + # Remove the first symbols from the array and return the url prefix + # implied by those symbols. def extract_namespace(record_or_hash_or_array) - returning "" do |namespace| - if record_or_hash_or_array.is_a?(Array) - record_or_hash_or_array.delete_if do |record_or_namespace| - if record_or_namespace.is_a?(String) || record_or_namespace.is_a?(Symbol) - namespace << "#{record_or_namespace}_" - end - end - end + return "" unless record_or_hash_or_array.is_a?(Array) + + namespace_keys = [] + while (key = record_or_hash_or_array.first) && key.is_a?(String) || key.is_a?(Symbol) + namespace_keys << record_or_hash_or_array.shift end + + namespace_keys.map {|k| "#{k}_"}.join end end end -- cgit v1.2.3 From b40947432540ad29abacaad9d9254bf70048190d Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Mon, 23 Jun 2008 23:41:21 -0700 Subject: link_to_function and button_to_function shouldn't modify their options hashes --- actionpack/lib/action_view/helpers/javascript_helper.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb index 31571de6c4..f89b6c2f70 100644 --- a/actionpack/lib/action_view/helpers/javascript_helper.rb +++ b/actionpack/lib/action_view/helpers/javascript_helper.rb @@ -80,7 +80,7 @@ module ActionView # return false;">Show me more # def link_to_function(name, *args, &block) - html_options = args.extract_options!.symbolize_keys! + html_options = args.extract_options!.symbolize_keys function = block_given? ? update_page(&block) : args[0] || '' onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function}; return false;" @@ -106,7 +106,7 @@ module ActionView # page[:details].visual_effect :toggle_slide # end def button_to_function(name, *args, &block) - html_options = args.extract_options!.symbolize_keys! + html_options = args.extract_options!.symbolize_keys function = block_given? ? update_page(&block) : args[0] || '' onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function};" -- cgit v1.2.3 From 69e72af62261dd8971890711b51c6eef2c68bc71 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Tue, 24 Jun 2008 11:53:49 -0700 Subject: Improve readability --- actionpack/lib/action_controller/caching/fragments.rb | 18 ++++++++++-------- actionpack/lib/action_view/template_handlers/erb.rb | 4 +++- 2 files changed, 13 insertions(+), 9 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/caching/fragments.rb b/actionpack/lib/action_controller/caching/fragments.rb index e4f5de44ab..57b31ec9d1 100644 --- a/actionpack/lib/action_controller/caching/fragments.rb +++ b/actionpack/lib/action_controller/caching/fragments.rb @@ -61,16 +61,18 @@ module ActionController #:nodoc: end def fragment_for(block, name = {}, options = nil) #:nodoc: - unless perform_caching then block.call; return end - - buffer = yield - - if cache = read_fragment(name, options) - buffer.concat(cache) + if perform_caching + buffer = yield + + if cache = read_fragment(name, options) + buffer.concat(cache) + else + pos = buffer.length + block.call + write_fragment(name, buffer[pos..-1], options) + end else - pos = buffer.length block.call - write_fragment(name, buffer[pos..-1], options) end end diff --git a/actionpack/lib/action_view/template_handlers/erb.rb b/actionpack/lib/action_view/template_handlers/erb.rb index 458416b6cb..ac715e30c2 100644 --- a/actionpack/lib/action_view/template_handlers/erb.rb +++ b/actionpack/lib/action_view/template_handlers/erb.rb @@ -53,7 +53,9 @@ module ActionView end def cache_fragment(block, name = {}, options = nil) #:nodoc: - @view.fragment_for(block, name, options) { @view.response.template.output_buffer ||= '' } + @view.fragment_for(block, name, options) do + @view.response.template.output_buffer + end end end end -- cgit v1.2.3 From 670e22e3724791f51d639f409930fba5af920081 Mon Sep 17 00:00:00 2001 From: Jimmy Baker Date: Tue, 24 Jun 2008 22:21:58 -0700 Subject: Patched HTML::Document#initialize call to Node.parse so that it includes the strict argument. [#330] --- actionpack/lib/action_controller/vendor/html-scanner/html/document.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/vendor/html-scanner/html/document.rb b/actionpack/lib/action_controller/vendor/html-scanner/html/document.rb index 607fd186b9..b8d73c350d 100644 --- a/actionpack/lib/action_controller/vendor/html-scanner/html/document.rb +++ b/actionpack/lib/action_controller/vendor/html-scanner/html/document.rb @@ -17,7 +17,7 @@ module HTML #:nodoc: @root = Node.new(nil) node_stack = [ @root ] while token = tokenizer.next - node = Node.parse(node_stack.last, tokenizer.line, tokenizer.position, token) + node = Node.parse(node_stack.last, tokenizer.line, tokenizer.position, token, strict) node_stack.last.children << node unless node.tag? && node.closing == :close if node.tag? -- cgit v1.2.3 From 6f5327013d6353c50cadfe2160d1b526ad687633 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Wed, 25 Jun 2008 05:47:01 -0500 Subject: Consolidate CustomHandlerTest, TemplateFileTest, and TemplateObjectTest and test them at a higher level of abstraction in ViewRenderTest. --- actionpack/lib/action_view/view_load_paths.rb | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/view_load_paths.rb b/actionpack/lib/action_view/view_load_paths.rb index e873d96aa0..f23ac665f1 100644 --- a/actionpack/lib/action_view/view_load_paths.rb +++ b/actionpack/lib/action_view/view_load_paths.rb @@ -6,19 +6,15 @@ module ActionView #:nodoc: class LoadPath #:nodoc: attr_reader :path, :paths - delegate :to_s, :inspect, :to => :path + delegate :to_s, :to_str, :inspect, :to => :path def initialize(path) @path = path.freeze reload! end - def eql?(view_path) - view_path.is_a?(ViewPath) && @path == view_path.path - end - - def hash - @path.hash + def ==(path) + to_str == path.to_str end # Rebuild load path directory cache -- cgit v1.2.3 From ad772402c46a79c2d38979cef754b26dbd868196 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Wed, 25 Jun 2008 05:57:24 -0500 Subject: Made ActionView::Base#render_file private --- actionpack/lib/action_controller/base.rb | 2 +- actionpack/lib/action_controller/layout.rb | 2 +- actionpack/lib/action_controller/rescue.rb | 2 +- .../templates/rescues/diagnostics.erb | 4 +-- .../templates/rescues/template_error.erb | 4 +-- actionpack/lib/action_view/base.rb | 40 +++++++++++----------- 6 files changed, 27 insertions(+), 27 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index bf34edcd85..c50c55dd05 100755 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -1095,7 +1095,7 @@ module ActionController #:nodoc: def render_for_file(template_path, status = nil, use_full_path = false, locals = {}) #:nodoc: add_variables_to_assigns logger.info("Rendering #{template_path}" + (status ? " (#{status})" : '')) if logger - render_for_text(@template.render_file(template_path, use_full_path, locals), status) + render_for_text(@template.render(:file => template_path, :use_full_path => use_full_path, :locals => locals), status) end def render_for_text(text = nil, status = nil, append_response = false) #:nodoc: diff --git a/actionpack/lib/action_controller/layout.rb b/actionpack/lib/action_controller/layout.rb index 0721f71498..d0c717ff67 100644 --- a/actionpack/lib/action_controller/layout.rb +++ b/actionpack/lib/action_controller/layout.rb @@ -254,7 +254,7 @@ module ActionController #:nodoc: @template.instance_variable_set("@content_for_layout", content_for_layout) response.layout = layout status = template_with_options ? options[:status] : nil - render_for_text(@template.render_file(layout, true), status) + render_for_text(@template.render(layout), status) else render_with_no_layout(options, extra_options, &block) end diff --git a/actionpack/lib/action_controller/rescue.rb b/actionpack/lib/action_controller/rescue.rb index 40ef4ea044..163ed87fbb 100644 --- a/actionpack/lib/action_controller/rescue.rb +++ b/actionpack/lib/action_controller/rescue.rb @@ -178,7 +178,7 @@ module ActionController #:nodoc: @template.instance_variable_set("@rescues_path", File.dirname(rescues_path("stub"))) @template.send!(:assign_variables_from_controller) - @template.instance_variable_set("@contents", @template.render_file(template_path_for_local_rescue(exception), false)) + @template.instance_variable_set("@contents", @template.render(:file => template_path_for_local_rescue(exception), :use_full_path => false)) response.content_type = Mime::HTML render_for_file(rescues_path("layout"), response_code_for_rescue(exception)) diff --git a/actionpack/lib/action_controller/templates/rescues/diagnostics.erb b/actionpack/lib/action_controller/templates/rescues/diagnostics.erb index 032f945ed2..385c6c1b09 100644 --- a/actionpack/lib/action_controller/templates/rescues/diagnostics.erb +++ b/actionpack/lib/action_controller/templates/rescues/diagnostics.erb @@ -6,6 +6,6 @@
<%=h @exception.clean_message %>
-<%= render_file(@rescues_path + "/_trace.erb", false) %> +<%= render(:file => @rescues_path + "/_trace.erb", :use_full_path => false) %> -<%= render_file(@rescues_path + "/_request_and_response.erb", false) %> +<%= render(:file => @rescues_path + "/_request_and_response.erb", :use_full_path => false) %> diff --git a/actionpack/lib/action_controller/templates/rescues/template_error.erb b/actionpack/lib/action_controller/templates/rescues/template_error.erb index eda64db3e9..4aecc68d18 100644 --- a/actionpack/lib/action_controller/templates/rescues/template_error.erb +++ b/actionpack/lib/action_controller/templates/rescues/template_error.erb @@ -15,7 +15,7 @@ <% @real_exception = @exception @exception = @exception.original_exception || @exception %> -<%= render_file(@rescues_path + "/_trace.erb", false) %> +<%= render(:file => @rescues_path + "/_trace.erb", :use_full_path => false) %> <% @exception = @real_exception %> -<%= render_file(@rescues_path + "/_request_and_response.erb", false) %> +<%= render(:file => @rescues_path + "/_request_and_response.erb", :use_full_path => false) %> diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 197455a933..84f2c45f4e 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -228,26 +228,6 @@ module ActionView #:nodoc: @view_paths = ViewLoadPaths.new(Array(paths)) end - # Renders the template present at template_path. If use_full_path is set to true, - # it's relative to the view_paths array, otherwise it's absolute. The hash in local_assigns - # is made available as local variables. - def render_file(template_path, use_full_path = true, local_assigns = {}) #:nodoc: - if defined?(ActionMailer) && defined?(ActionMailer::Base) && controller.is_a?(ActionMailer::Base) && !template_path.include?("/") - raise ActionViewError, <<-END_ERROR -Due to changes in ActionMailer, you need to provide the mailer_name along with the template name. - - render "user_mailer/signup" - render :file => "user_mailer/signup" - -If you are rendering a subtemplate, you must now use controller-like partial syntax: - - render :partial => 'signup' # no mailer_name necessary - END_ERROR - end - - Template.new(self, template_path, use_full_path, local_assigns).render_template - end - # Renders the template present at template_path (relative to the view_paths array). # The hash in local_assigns is made available as local variables. def render(options = {}, local_assigns = {}, &block) #:nodoc: @@ -323,6 +303,26 @@ If you are rendering a subtemplate, you must now use controller-like partial syn end private + # Renders the template present at template_path. If use_full_path is set to true, + # it's relative to the view_paths array, otherwise it's absolute. The hash in local_assigns + # is made available as local variables. + def render_file(template_path, use_full_path = true, local_assigns = {}) #:nodoc: + if defined?(ActionMailer) && defined?(ActionMailer::Base) && controller.is_a?(ActionMailer::Base) && !template_path.include?("/") + raise ActionViewError, <<-END_ERROR + Due to changes in ActionMailer, you need to provide the mailer_name along with the template name. + + render "user_mailer/signup" + render :file => "user_mailer/signup" + + If you are rendering a subtemplate, you must now use controller-like partial syntax: + + render :partial => 'signup' # no mailer_name necessary + END_ERROR + end + + Template.new(self, template_path, use_full_path, local_assigns).render_template + end + def wrap_content_for_layout(content) original_content_for_layout, @content_for_layout = @content_for_layout, content yield -- cgit v1.2.3 From a9259ccfe05690dc4cb7993d551603c39619c27f Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Wed, 25 Jun 2008 06:04:06 -0500 Subject: Hide InlineTemplate class from ActionController and use ActionView's render API --- actionpack/lib/action_controller/base.rb | 3 +-- actionpack/lib/action_view/base.rb | 11 +++++------ 2 files changed, 6 insertions(+), 8 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index c50c55dd05..7cc670289d 100755 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -859,8 +859,7 @@ module ActionController #:nodoc: elsif inline = options[:inline] add_variables_to_assigns - tmpl = ActionView::InlineTemplate.new(@template, options[:inline], options[:locals], options[:type]) - render_for_text(@template.render_template(tmpl), options[:status]) + render_for_text(@template.render(options), options[:status]) elsif action_name = options[:action] template = default_template_name(action_name.to_s) diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 84f2c45f4e..40b808a61e 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -256,16 +256,11 @@ module ActionView #:nodoc: elsif options[:partial] render_partial(options[:partial], ActionView::Base::ObjectWrapper.new(options[:object]), options[:locals]) elsif options[:inline] - template = InlineTemplate.new(self, options[:inline], options[:locals], options[:type]) - render_template(template) + render_inline(options[:inline], options[:locals], options[:type]) end end end - def render_template(template) #:nodoc: - template.render_template - end - # Returns true is the file may be rendered implicitly. def file_public?(template_path)#:nodoc: template_path.split('/').last[0,1] != '_' @@ -323,6 +318,10 @@ module ActionView #:nodoc: Template.new(self, template_path, use_full_path, local_assigns).render_template end + def render_inline(text, local_assigns = {}, type = nil) + InlineTemplate.new(self, text, local_assigns, type).render_template + end + def wrap_content_for_layout(content) original_content_for_layout, @content_for_layout = @content_for_layout, content yield -- cgit v1.2.3 From 3c1e8ab0fecd5ee7f9328578016ef1e61214eeee Mon Sep 17 00:00:00 2001 From: Cheah Chu Yeow Date: Mon, 23 Jun 2008 21:14:49 +0800 Subject: Allow single quote (the ' character) in the middle of URL when auto_link-ing. [#471 state:resolved] Signed-off-by: Pratik Naik --- actionpack/lib/action_view/helpers/text_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index d98c5bd0d5..a6c48737e9 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -468,7 +468,7 @@ module ActionView [-\w]+ # subdomain or domain (?:\.[-\w]+)* # remaining subdomains or domain (?::\d+)? # port - (?:/(?:(?:[~\w\+@%=\(\)-]|(?:[,.;:][^\s$]))+)?)* # path + (?:/(?:(?:[~\w\+@%=\(\)-]|(?:[,.;:'][^\s$]))+)?)* # path (?:\?[\w\+@%&=.;-]+)? # query string (?:\#[\w\-]*)? # trailing anchor ) -- cgit v1.2.3 From 029a7455846cde2654958358a6fe354f236ade35 Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Sun, 29 Jun 2008 00:35:30 +0100 Subject: Ensure FormBuilder date helpers respects html_options. [#506 state:resolved] [Pascal Ehlert] Signed-off-by: Pratik Naik --- actionpack/lib/action_view/helpers/date_helper.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb index 7ed6272898..1aee9ef0a2 100755 --- a/actionpack/lib/action_view/helpers/date_helper.rb +++ b/actionpack/lib/action_view/helpers/date_helper.rb @@ -696,15 +696,15 @@ module ActionView class FormBuilder def date_select(method, options = {}, html_options = {}) - @template.date_select(@object_name, method, options.merge(:object => @object)) + @template.date_select(@object_name, method, options.merge(:object => @object), html_options) end def time_select(method, options = {}, html_options = {}) - @template.time_select(@object_name, method, options.merge(:object => @object)) + @template.time_select(@object_name, method, options.merge(:object => @object), html_options) end def datetime_select(method, options = {}, html_options = {}) - @template.datetime_select(@object_name, method, options.merge(:object => @object)) + @template.datetime_select(@object_name, method, options.merge(:object => @object), html_options) end end end -- cgit v1.2.3 From d0092dc44d580f4179308c7394d9023098406f79 Mon Sep 17 00:00:00 2001 From: Ernie Miller Date: Sat, 28 Jun 2008 22:27:32 -0400 Subject: Added support for regexp matching of priority zones in time_zone_select [#195 state:resolved] --- actionpack/lib/action_view/helpers/form_options_helper.rb | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb index b3f8e63c1b..75220a2f66 100644 --- a/actionpack/lib/action_view/helpers/form_options_helper.rb +++ b/actionpack/lib/action_view/helpers/form_options_helper.rb @@ -150,7 +150,8 @@ module ActionView # You can also supply an array of TimeZone objects # as +priority_zones+, so that they will be listed above the rest of the # (long) list. (You can use TimeZone.us_zones as a convenience for - # obtaining a list of the US time zones.) + # obtaining a list of the US time zones, or a Regexp to select the zones + # of your choice) # # Finally, this method supports a :default option, which selects # a default TimeZone if the object's time zone is +nil+. @@ -164,6 +165,8 @@ module ActionView # # time_zone_select( "user", 'time_zone', [ TimeZone['Alaska'], TimeZone['Hawaii'] ]) # + # time_zone_select( "user", 'time_zone', /Australia/) + # # time_zone_select( "user", "time_zone", TZInfo::Timezone.all.sort, :model => TZInfo::Timezone) def time_zone_select(object, method, priority_zones = nil, options = {}, html_options = {}) InstanceTag.new(object, method, self, nil, options.delete(:object)).to_time_zone_select_tag(priority_zones, options, html_options) @@ -292,7 +295,8 @@ module ActionView # selected option tag. You can also supply an array of TimeZone objects # as +priority_zones+, so that they will be listed above the rest of the # (long) list. (You can use TimeZone.us_zones as a convenience for - # obtaining a list of the US time zones.) + # obtaining a list of the US time zones, or a Regexp to select the zones + # of your choice) # # The +selected+ parameter must be either +nil+, or a string that names # a TimeZone. @@ -311,6 +315,9 @@ module ActionView convert_zones = lambda { |list| list.map { |z| [ z.to_s, z.name ] } } if priority_zones + if priority_zones.is_a?(Regexp) + priority_zones = model.all.find_all {|z| z =~ priority_zones} + end zone_options += options_for_select(convert_zones[priority_zones], selected) zone_options += "\n" -- cgit v1.2.3 From 4cf93935b2478201863c01569e894c9dcf7e9074 Mon Sep 17 00:00:00 2001 From: gbuesing Date: Sun, 29 Jun 2008 13:46:07 -0500 Subject: Fix indentation and update changelogs for previous commit --- actionpack/lib/action_view/helpers/form_options_helper.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb index 75220a2f66..0ca5cebcba 100644 --- a/actionpack/lib/action_view/helpers/form_options_helper.rb +++ b/actionpack/lib/action_view/helpers/form_options_helper.rb @@ -315,9 +315,9 @@ module ActionView convert_zones = lambda { |list| list.map { |z| [ z.to_s, z.name ] } } if priority_zones - if priority_zones.is_a?(Regexp) + if priority_zones.is_a?(Regexp) priority_zones = model.all.find_all {|z| z =~ priority_zones} - end + end zone_options += options_for_select(convert_zones[priority_zones], selected) zone_options += "\n" -- cgit v1.2.3 From 7378e237342443addb1691795ac9457250b6db1e Mon Sep 17 00:00:00 2001 From: Scott Stewart Date: Wed, 2 Jul 2008 01:36:58 +0100 Subject: Ensure proper output when submit_tag is used with :disabled_with. [#388 state:resolved] Signed-off-by: Pratik Naik --- actionpack/lib/action_view/helpers/form_tag_helper.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb index ccebec3692..bdfb2eebd7 100644 --- a/actionpack/lib/action_view/helpers/form_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb @@ -348,11 +348,13 @@ module ActionView options.stringify_keys! if disable_with = options.delete("disable_with") + disable_with = "this.value='#{disable_with}'" + disable_with << ";#{options.delete('onclick')}" if options['onclick'] + options["onclick"] = [ "this.setAttribute('originalValue', this.value)", "this.disabled=true", - "this.value='#{disable_with}'", - "#{options["onclick"]}", + disable_with, "result = (this.form.onsubmit ? (this.form.onsubmit() ? this.form.submit() : false) : this.form.submit())", "if (result == false) { this.value = this.getAttribute('originalValue'); this.disabled = false }", "return result;", -- cgit v1.2.3 From aff2d331720a3143914a0fffd1eba613dc333bfc Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 1 Jul 2008 21:52:28 -0500 Subject: Improved test coverage and added RackRequest support for CGI environment variables. --- actionpack/lib/action_controller/rack_process.rb | 35 ++++++++++++++++++++---- 1 file changed, 30 insertions(+), 5 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/rack_process.rb b/actionpack/lib/action_controller/rack_process.rb index 9b4aa9b7cf..01bc1ebb26 100644 --- a/actionpack/lib/action_controller/rack_process.rb +++ b/actionpack/lib/action_controller/rack_process.rb @@ -24,6 +24,19 @@ module ActionController #:nodoc: super() end + %w[ AUTH_TYPE CONTENT_TYPE GATEWAY_INTERFACE PATH_INFO + PATH_TRANSLATED QUERY_STRING REMOTE_HOST + REMOTE_IDENT REMOTE_USER SCRIPT_NAME + SERVER_NAME SERVER_PROTOCOL + + HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_ACCEPT_ENCODING + HTTP_ACCEPT_LANGUAGE HTTP_CACHE_CONTROL HTTP_FROM HTTP_HOST + HTTP_NEGOTIATE HTTP_PRAGMA HTTP_REFERER HTTP_USER_AGENT ].each do |env| + define_method(env.sub(/^HTTP_/n, '').downcase) do + @env[env] + end + end + # The request body is an IO input stream. If the RAW_POST_DATA environment # variable is already set, wrap it in a StringIO. def body @@ -35,7 +48,7 @@ module ActionController #:nodoc: end def key?(key) - @env.key? key + @env.key?(key) end def query_parameters @@ -85,6 +98,18 @@ module ActionController #:nodoc: @env['REMOTE_ADDR'] end + def request_method + @env['REQUEST_METHOD'].downcase.to_sym + end + + def server_port + @env['SERVER_PORT'].to_i + end + + def server_software + @env['SERVER_SOFTWARE'].split("/").first + end + def session unless defined?(@session) if @session_options == false @@ -178,9 +203,9 @@ end_msg normalize_headers(@headers) if [204, 304].include?(@status.to_i) @headers.delete "Content-Type" - [status.to_i, @headers.to_hash, []] + [status, @headers.to_hash, []] else - [status.to_i, @headers.to_hash, self] + [status, @headers.to_hash, self] end end alias to_a out @@ -225,8 +250,8 @@ end_msg headers['Content-Language'] = options.delete('language') if options['language'] headers['Expires'] = options.delete('expires') if options['expires'] - @status = options.delete('Status') if options['Status'] - @status ||= 200 + @status = options['Status'] || "200 OK" + # Convert 'cookie' header to 'Set-Cookie' headers. # Because Set-Cookie header can appear more the once in the response body, # we store it in a line break seperated string that will be translated to -- cgit v1.2.3 From f5052dd8a39099e4930faafe9b01e63ced2f6391 Mon Sep 17 00:00:00 2001 From: Tim Haines Date: Wed, 2 Jul 2008 04:26:34 +0100 Subject: Make sure render :template works with :locals. [#524 state:resolved] Signed-off-by: Pratik Naik --- actionpack/lib/action_controller/base.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 7cc670289d..a7b2f147e8 100755 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -733,6 +733,9 @@ module ActionController #:nodoc: # # Renders the template located in [TEMPLATE_ROOT]/weblog/show.r(html|xml) (in Rails, app/views/weblog/show.erb) # render :template => "weblog/show" # + # # Renders the template with a local variable + # render :template => "weblog/show", :locals => {:customer => Customer.new} + # # === Rendering a file # # File rendering works just like action rendering except that it takes a filesystem path. By default, the path @@ -855,7 +858,7 @@ module ActionController #:nodoc: render_for_file(file, options[:status], options[:use_full_path], options[:locals] || {}) elsif template = options[:template] - render_for_file(template, options[:status], true) + render_for_file(template, options[:status], true, options[:locals] || {}) elsif inline = options[:inline] add_variables_to_assigns -- cgit v1.2.3 From 2b43620e3c1352028f19550fcde4632d65cbd191 Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Wed, 2 Jul 2008 16:38:50 +0100 Subject: Add :as option to render a collection of partials with a custom local variable name. [#509 state:resolved] [Simon Jefford, Pratik Naik] --- actionpack/lib/action_controller/base.rb | 5 ++++- actionpack/lib/action_view/base.rb | 2 +- actionpack/lib/action_view/partial_template.rb | 9 ++++++--- actionpack/lib/action_view/partials.rb | 14 +++++++------- 4 files changed, 18 insertions(+), 12 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index a7b2f147e8..209cdfa686 100755 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -702,6 +702,9 @@ module ActionController #:nodoc: # # builds the complete response. # render :partial => "person", :collection => @winners # + # # Renders a collection of partials but with a custom local variable name + # render :partial => "admin_person", :collection => @winners, :as => :person + # # # Renders the same collection of partials, but also renders the # # person_divider partial between each person partial. # render :partial => "person", :collection => @winners, :spacer_template => "person_divider" @@ -889,7 +892,7 @@ module ActionController #:nodoc: if collection = options[:collection] render_for_text( @template.send!(:render_partial_collection, partial, collection, - options[:spacer_template], options[:locals]), options[:status] + options[:spacer_template], options[:locals], options[:as]), options[:status] ) else render_for_text( diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 40b808a61e..40a3b16e9f 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -252,7 +252,7 @@ module ActionView #:nodoc: elsif options[:file] render_file(options[:file], use_full_path || false, options[:locals]) elsif options[:partial] && options[:collection] - render_partial_collection(options[:partial], options[:collection], options[:spacer_template], options[:locals]) + render_partial_collection(options[:partial], options[:collection], options[:spacer_template], options[:locals], options[:as]) elsif options[:partial] render_partial(options[:partial], ActionView::Base::ObjectWrapper.new(options[:object]), options[:locals]) elsif options[:inline] diff --git a/actionpack/lib/action_view/partial_template.rb b/actionpack/lib/action_view/partial_template.rb index 0cf996ca04..3513244ecb 100644 --- a/actionpack/lib/action_view/partial_template.rb +++ b/actionpack/lib/action_view/partial_template.rb @@ -1,9 +1,10 @@ module ActionView #:nodoc: class PartialTemplate < Template #:nodoc: - attr_reader :variable_name, :object + attr_reader :variable_name, :object, :as - def initialize(view, partial_path, object = nil, locals = {}) + def initialize(view, partial_path, object = nil, locals = {}, as = nil) @view_controller = view.controller if view.respond_to?(:controller) + @as = as set_path_and_variable_name!(partial_path) super(view, @path, true, locals) add_object_to_local_assigns!(object) @@ -22,10 +23,11 @@ module ActionView #:nodoc: end def render_member(object) - @locals[:object] = @locals[@variable_name] = object + @locals[:object] = @locals[@variable_name] = @locals[as] = object template = render_template @locals[@counter_name] += 1 + @locals.delete(as) @locals.delete(@variable_name) @locals.delete(:object) @@ -45,6 +47,7 @@ module ActionView #:nodoc: else object end || @view_controller.instance_variable_get("@#{variable_name}") + @locals[as] ||= @locals[:object] if as end def set_path_and_variable_name!(partial_path) diff --git a/actionpack/lib/action_view/partials.rb b/actionpack/lib/action_view/partials.rb index 6b294be6bd..7c6c98d611 100644 --- a/actionpack/lib/action_view/partials.rb +++ b/actionpack/lib/action_view/partials.rb @@ -123,32 +123,32 @@ module ActionView end end - def render_partial_collection(partial_path, collection, partial_spacer_template = nil, local_assigns = {}) #:nodoc: + def render_partial_collection(partial_path, collection, partial_spacer_template = nil, local_assigns = {}, as = nil) #:nodoc: return " " if collection.empty? local_assigns = local_assigns ? local_assigns.clone : {} spacer = partial_spacer_template ? render(:partial => partial_spacer_template) : '' if partial_path.nil? - render_partial_collection_with_unknown_partial_path(collection, local_assigns) + render_partial_collection_with_unknown_partial_path(collection, local_assigns, as) else - render_partial_collection_with_known_partial_path(collection, partial_path, local_assigns) + render_partial_collection_with_known_partial_path(collection, partial_path, local_assigns, as) end.join(spacer) end - def render_partial_collection_with_known_partial_path(collection, partial_path, local_assigns) - template = ActionView::PartialTemplate.new(self, partial_path, nil, local_assigns) + def render_partial_collection_with_known_partial_path(collection, partial_path, local_assigns, as) + template = ActionView::PartialTemplate.new(self, partial_path, nil, local_assigns, as) collection.map do |element| template.render_member(element) end end - def render_partial_collection_with_unknown_partial_path(collection, local_assigns) + def render_partial_collection_with_unknown_partial_path(collection, local_assigns, as) templates = Hash.new i = 0 collection.map do |element| partial_path = ActionController::RecordIdentifier.partial_path(element, controller.class.controller_path) - template = templates[partial_path] ||= ActionView::PartialTemplate.new(self, partial_path, nil, local_assigns) + template = templates[partial_path] ||= ActionView::PartialTemplate.new(self, partial_path, nil, local_assigns, as) template.counter = i i += 1 template.render_member(element) -- cgit v1.2.3 From 267d3964ebd7bbc8879d69ff5a323527179c497d Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Wed, 2 Jul 2008 17:19:41 +0100 Subject: Make sure render :collection doesnt set nil local when :as is absent --- actionpack/lib/action_view/partial_template.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/partial_template.rb b/actionpack/lib/action_view/partial_template.rb index 3513244ecb..a2129952c0 100644 --- a/actionpack/lib/action_view/partial_template.rb +++ b/actionpack/lib/action_view/partial_template.rb @@ -23,7 +23,8 @@ module ActionView #:nodoc: end def render_member(object) - @locals[:object] = @locals[@variable_name] = @locals[as] = object + @locals[:object] = @locals[@variable_name] = object + @locals[as] = object if as template = render_template @locals[@counter_name] += 1 -- cgit v1.2.3 From 8f640c381d9d1b74f6a0fc3648c21da373661914 Mon Sep 17 00:00:00 2001 From: Mike Subelsky Date: Wed, 2 Jul 2008 14:15:43 -0400 Subject: Added application/jsonrequest as a synonym for application/json [#536 state:resolved] --- actionpack/lib/action_controller/mime_types.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/mime_types.rb b/actionpack/lib/action_controller/mime_types.rb index 01a266d3fe..2d7fba1173 100644 --- a/actionpack/lib/action_controller/mime_types.rb +++ b/actionpack/lib/action_controller/mime_types.rb @@ -17,4 +17,5 @@ Mime::Type.register "multipart/form-data", :multipart_form Mime::Type.register "application/x-www-form-urlencoded", :url_encoded_form # http://www.ietf.org/rfc/rfc4627.txt -Mime::Type.register "application/json", :json, %w( text/x-json ) \ No newline at end of file +# http://www.json.org/JSONRequest.html +Mime::Type.register "application/json", :json, %w( text/x-json application/jsonrequest ) \ No newline at end of file -- cgit v1.2.3 From 3b3790a4351ba7c9d2711089c21f24fcedc11fc0 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Wed, 2 Jul 2008 21:38:58 -0500 Subject: Deprecate :use_full_path render option. The supplying the option no longer has an effect. --- actionpack/lib/action_controller/base.rb | 10 +++---- actionpack/lib/action_view/base.rb | 12 ++++---- actionpack/lib/action_view/partial_template.rb | 2 +- actionpack/lib/action_view/template.rb | 39 ++++++++++++++------------ actionpack/lib/action_view/template_file.rb | 10 +++---- 5 files changed, 37 insertions(+), 36 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 209cdfa686..02941bade9 100755 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -858,7 +858,7 @@ module ActionController #:nodoc: else if file = options[:file] - render_for_file(file, options[:status], options[:use_full_path], options[:locals] || {}) + render_for_file(file, options[:status], nil, options[:locals] || {}) elsif template = options[:template] render_for_file(template, options[:status], true, options[:locals] || {}) @@ -870,9 +870,9 @@ module ActionController #:nodoc: elsif action_name = options[:action] template = default_template_name(action_name.to_s) if options[:layout] && !template_exempt_from_layout?(template) - render_with_a_layout(:file => template, :status => options[:status], :use_full_path => true, :layout => true) + render_with_a_layout(:file => template, :status => options[:status], :layout => true) else - render_with_no_layout(:file => template, :status => options[:status], :use_full_path => true) + render_with_no_layout(:file => template, :status => options[:status]) end elsif xml = options[:xml] @@ -1097,10 +1097,10 @@ module ActionController #:nodoc: private - def render_for_file(template_path, status = nil, use_full_path = false, locals = {}) #:nodoc: + def render_for_file(template_path, status = nil, use_full_path = nil, locals = {}) #:nodoc: add_variables_to_assigns logger.info("Rendering #{template_path}" + (status ? " (#{status})" : '')) if logger - render_for_text(@template.render(:file => template_path, :use_full_path => use_full_path, :locals => locals), status) + render_for_text(@template.render(:file => template_path, :locals => locals), status) end def render_for_text(text = nil, status = nil, append_response = false) #:nodoc: diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 40a3b16e9f..a8c6e15ca3 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -232,12 +232,11 @@ module ActionView #:nodoc: # The hash in local_assigns is made available as local variables. def render(options = {}, local_assigns = {}, &block) #:nodoc: if options.is_a?(String) - render_file(options, true, local_assigns) + render_file(options, nil, local_assigns) elsif options == :update update_page(&block) elsif options.is_a?(Hash) - use_full_path = options[:use_full_path] - options = options.reverse_merge(:locals => {}, :use_full_path => true) + options = options.reverse_merge(:locals => {}) if partial_layout = options.delete(:layout) if block_given? @@ -250,7 +249,7 @@ module ActionView #:nodoc: end end elsif options[:file] - render_file(options[:file], use_full_path || false, options[:locals]) + render_file(options[:file], nil, options[:locals]) elsif options[:partial] && options[:collection] render_partial_collection(options[:partial], options[:collection], options[:spacer_template], options[:locals], options[:as]) elsif options[:partial] @@ -298,10 +297,9 @@ module ActionView #:nodoc: end private - # Renders the template present at template_path. If use_full_path is set to true, - # it's relative to the view_paths array, otherwise it's absolute. The hash in local_assigns + # Renders the template present at template_path. The hash in local_assigns # is made available as local variables. - def render_file(template_path, use_full_path = true, local_assigns = {}) #:nodoc: + def render_file(template_path, use_full_path = nil, local_assigns = {}) #:nodoc: if defined?(ActionMailer) && defined?(ActionMailer::Base) && controller.is_a?(ActionMailer::Base) && !template_path.include?("/") raise ActionViewError, <<-END_ERROR Due to changes in ActionMailer, you need to provide the mailer_name along with the template name. diff --git a/actionpack/lib/action_view/partial_template.rb b/actionpack/lib/action_view/partial_template.rb index a2129952c0..719199f19d 100644 --- a/actionpack/lib/action_view/partial_template.rb +++ b/actionpack/lib/action_view/partial_template.rb @@ -6,7 +6,7 @@ module ActionView #:nodoc: @view_controller = view.controller if view.respond_to?(:controller) @as = as set_path_and_variable_name!(partial_path) - super(view, @path, true, locals) + super(view, @path, nil, locals) add_object_to_local_assigns!(object) # This is needed here in order to compile template with knowledge of 'counter' diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 4c3f252c10..0cba1942f7 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -5,15 +5,19 @@ module ActionView #:nodoc: attr_accessor :locals attr_reader :handler, :path, :extension, :filename, :method - def initialize(view, path, use_full_path, locals = {}) + def initialize(view, path, use_full_path = nil, locals = {}) + unless use_full_path == nil + ActiveSupport::Deprecation.warn("use_full_path option has been deprecated and has no affect.", caller) + end + @view = view @paths = view.view_paths @original_path = path - @path = TemplateFile.from_path(path, !use_full_path) + @path = TemplateFile.from_path(path) @view.first_render ||= @path.to_s @source = nil # Don't read the source until we know that it is required - set_extension_and_file_name(use_full_path) + set_extension_and_file_name @locals = locals || {} @handler = self.class.handler_class_for_extension(@extension).new(@view) @@ -63,25 +67,24 @@ module ActionView #:nodoc: end private - def set_extension_and_file_name(use_full_path) + def set_extension_and_file_name @extension = @path.extension - if use_full_path - unless @extension - @path = @view.send(:template_file_from_name, @path) - raise_missing_template_exception unless @path - @extension = @path.extension - end - - if @path = @paths.find_template_file_for_path(path) - @filename = @path.full_path - @extension = @path.extension - end - else - @filename = @path.full_path + unless @extension + @path = @view.send(:template_file_from_name, @path) + raise_missing_template_exception unless @path + @extension = @path.extension end - raise_missing_template_exception if @filename.blank? + if p = @paths.find_template_file_for_path(path) + @path = p + @filename = @path.full_path + @extension = @path.extension + raise_missing_template_exception if @filename.blank? + else + @filename = @original_path + raise_missing_template_exception unless File.exist?(@filename) + end end def raise_missing_template_exception diff --git a/actionpack/lib/action_view/template_file.rb b/actionpack/lib/action_view/template_file.rb index dd66482b3c..c38e8ed122 100644 --- a/actionpack/lib/action_view/template_file.rb +++ b/actionpack/lib/action_view/template_file.rb @@ -4,8 +4,8 @@ module ActionView #:nodoc: # from the load path root e.g. "hello/index.html.erb" not # "app/views/hello/index.html.erb" class TemplateFile - def self.from_path(path, use_full_path = false) - path.is_a?(self) ? path : new(path, use_full_path) + def self.from_path(path) + path.is_a?(self) ? path : new(path) end def self.from_full_path(load_path, full_path) @@ -17,11 +17,11 @@ module ActionView #:nodoc: attr_accessor :load_path, :base_path, :name, :format, :extension delegate :to_s, :inspect, :to => :path - def initialize(path, use_full_path = false) + def initialize(path) path = path.dup - # Clear the forward slash in the beginning unless using full path - trim_forward_slash!(path) unless use_full_path + # Clear the forward slash in the beginning + trim_forward_slash!(path) @base_path, @name, @format, @extension = split(path) end -- cgit v1.2.3 From a37d065f85941e1fe746dff4d42f015e1618834f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tarmo=20T=C3=A4nav?= Date: Thu, 3 Jul 2008 17:49:12 +0300 Subject: Use :namespace instead of :path_prefix for finding controller. [#544 state:resolved] :namespace is supposed to be the module where controller exists. :path_prefix can contain anything, including variables, which makes it unsuitable for determining the module for a controller. Signed-off-by: Pratik Naik --- actionpack/lib/action_controller/routing/builder.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/routing/builder.rb b/actionpack/lib/action_controller/routing/builder.rb index 4740113ed0..b8323847fd 100644 --- a/actionpack/lib/action_controller/routing/builder.rb +++ b/actionpack/lib/action_controller/routing/builder.rb @@ -67,10 +67,9 @@ module ActionController options = options.dup if options[:namespace] - options[:controller] = "#{options[:path_prefix]}/#{options[:controller]}" + options[:controller] = "#{options.delete(:namespace).sub(/\/$/, '')}/#{options[:controller]}" options.delete(:path_prefix) options.delete(:name_prefix) - options.delete(:namespace) end requirements = (options.delete(:requirements) || {}).dup -- cgit v1.2.3 From 5501166dec84e1dd63800ea25eaf23290216cf80 Mon Sep 17 00:00:00 2001 From: Michael Koziarski Date: Mon, 30 Jun 2008 18:44:21 +0300 Subject: Remove strange alias for JavaScriptHelper --- actionpack/lib/action_view/helpers/javascript_helper.rb | 2 -- 1 file changed, 2 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb index f89b6c2f70..8caca5b23f 100644 --- a/actionpack/lib/action_view/helpers/javascript_helper.rb +++ b/actionpack/lib/action_view/helpers/javascript_helper.rb @@ -216,7 +216,5 @@ module ActionView end end end - - JavascriptHelper = JavaScriptHelper unless const_defined? :JavascriptHelper end end -- cgit v1.2.3 From e358b1fce8fdcbac896dde08286be020420e843e Mon Sep 17 00:00:00 2001 From: Michael Koziarski Date: Mon, 30 Jun 2008 18:46:53 +0300 Subject: Remove old method of including javascripts define_javascript_functions. javascript_include_tag and friends do a much better job. --- .../lib/action_view/helpers/javascript_helper.rb | 26 ---------------------- 1 file changed, 26 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb index 8caca5b23f..22bd5cb440 100644 --- a/actionpack/lib/action_view/helpers/javascript_helper.rb +++ b/actionpack/lib/action_view/helpers/javascript_helper.rb @@ -114,32 +114,6 @@ module ActionView tag(:input, html_options.merge(:type => 'button', :value => name, :onclick => onclick)) end - # Includes the Action Pack JavaScript libraries inside a single ' - end - - JS_ESCAPE_MAP = { '\\' => '\\\\', ' '<\/', -- cgit v1.2.3 From df36a6f7598a7e963fb3d79fb48fd1c073045a43 Mon Sep 17 00:00:00 2001 From: Michael Koziarski Date: Mon, 30 Jun 2008 21:39:22 +0300 Subject: Remove unneeded ObjectWrapper class. Was previously needed to work around the semantics of a deprecated (now removed) API to render :partial --- actionpack/lib/action_controller/base.rb | 2 +- actionpack/lib/action_view/base.rb | 5 +---- actionpack/lib/action_view/partial_template.rb | 7 +------ 3 files changed, 3 insertions(+), 11 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 02941bade9..009c9eec99 100755 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -897,7 +897,7 @@ module ActionController #:nodoc: else render_for_text( @template.send!(:render_partial, partial, - ActionView::Base::ObjectWrapper.new(options[:object]), options[:locals]), options[:status] + options[:object], options[:locals]), options[:status] ) end diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index a8c6e15ca3..9e255bd324 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -199,9 +199,6 @@ module ActionView #:nodoc: cattr_reader :computed_public_paths @@computed_public_paths = {} - class ObjectWrapper < Struct.new(:value) #:nodoc: - end - def self.helper_modules #:nodoc: helpers = [] Dir.entries(File.expand_path("#{File.dirname(__FILE__)}/helpers")).sort.each do |file| @@ -253,7 +250,7 @@ module ActionView #:nodoc: elsif options[:partial] && options[:collection] render_partial_collection(options[:partial], options[:collection], options[:spacer_template], options[:locals], options[:as]) elsif options[:partial] - render_partial(options[:partial], ActionView::Base::ObjectWrapper.new(options[:object]), options[:locals]) + render_partial(options[:partial], options[:object], options[:locals]) elsif options[:inline] render_inline(options[:inline], options[:locals], options[:type]) end diff --git a/actionpack/lib/action_view/partial_template.rb b/actionpack/lib/action_view/partial_template.rb index 719199f19d..6ebe165a15 100644 --- a/actionpack/lib/action_view/partial_template.rb +++ b/actionpack/lib/action_view/partial_template.rb @@ -42,12 +42,7 @@ module ActionView #:nodoc: private def add_object_to_local_assigns!(object) @locals[:object] ||= - @locals[@variable_name] ||= - if object.is_a?(ActionView::Base::ObjectWrapper) - object.value - else - object - end || @view_controller.instance_variable_get("@#{variable_name}") + @locals[@variable_name] ||= object || @view_controller.instance_variable_get("@#{variable_name}") @locals[as] ||= @locals[:object] if as end -- cgit v1.2.3 From 5dd10d60bbde906449882e39278be76f1f445a41 Mon Sep 17 00:00:00 2001 From: Michael Koziarski Date: Mon, 30 Jun 2008 22:15:12 +0300 Subject: Remove nested ternary operators from select_year in favour of conditionals. --- actionpack/lib/action_view/helpers/date_helper.rb | 31 +++++++++++++++-------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb index 1aee9ef0a2..fa3e612fc1 100755 --- a/actionpack/lib/action_view/helpers/date_helper.rb +++ b/actionpack/lib/action_view/helpers/date_helper.rb @@ -547,23 +547,32 @@ module ActionView # select_year(2006, :start_year => 2000, :end_year => 2010) # def select_year(date, options = {}, html_options = {}) - val = date ? (date.kind_of?(Fixnum) ? date : date.year) : '' + if !date || date == 0 + value = '' + middle_year = Date.today.year + elsif date.kind_of?(Fixnum) + value = middle_year = date + else + value = middle_year = date.year + end + if options[:use_hidden] - hidden_html(options[:field_name] || 'year', val, options) + hidden_html(options[:field_name] || 'year', value, options) else - year_options = [] - y = date ? (date.kind_of?(Fixnum) ? (y = (date == 0) ? Date.today.year : date) : date.year) : Date.today.year + year_options = '' + start_year = options[:start_year] || middle_year - 5 + end_year = options[:end_year] || middle_year + 5 + step_val = start_year < end_year ? 1 : -1 - start_year, end_year = (options[:start_year] || y-5), (options[:end_year] || y+5) - step_val = start_year < end_year ? 1 : -1 start_year.step(end_year, step_val) do |year| - year_options << ((val == year) ? - content_tag(:option, year, :value => year, :selected => "selected") : - content_tag(:option, year, :value => year) - ) + if value == year + year_options << content_tag(:option, year, :value => year, :selected => "selected") + else + year_options << content_tag(:option, year, :value => year) + end year_options << "\n" end - select_html(options[:field_name] || 'year', year_options.join, options, html_options) + select_html(options[:field_name] || 'year', year_options, options, html_options) end end -- cgit v1.2.3 From 7098143f07bd03223bbbeea8a9c23506a7b5dffc Mon Sep 17 00:00:00 2001 From: Michael Koziarski Date: Wed, 2 Jul 2008 19:53:04 +0300 Subject: Remove unused local_binding option to InstanceTag's Constructor --- actionpack/lib/action_view/helpers/date_helper.rb | 6 +++--- actionpack/lib/action_view/helpers/form_helper.rb | 20 ++++++++++---------- .../lib/action_view/helpers/form_options_helper.rb | 8 ++++---- 3 files changed, 17 insertions(+), 17 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb index fa3e612fc1..50ae27da61 100755 --- a/actionpack/lib/action_view/helpers/date_helper.rb +++ b/actionpack/lib/action_view/helpers/date_helper.rb @@ -153,7 +153,7 @@ module ActionView # Note: If the day is not included as an option but the month is, the day will be set to the 1st to ensure that all month # choices are valid. def date_select(object_name, method, options = {}, html_options = {}) - InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_date_select_tag(options, html_options) + InstanceTag.new(object_name, method, self, options.delete(:object)).to_date_select_tag(options, html_options) end # Returns a set of select tags (one for hour, minute and optionally second) pre-selected for accessing a specified @@ -188,7 +188,7 @@ module ActionView # Note: If the day is not included as an option but the month is, the day will be set to the 1st to ensure that all month # choices are valid. def time_select(object_name, method, options = {}, html_options = {}) - InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_time_select_tag(options, html_options) + InstanceTag.new(object_name, method, self, options.delete(:object)).to_time_select_tag(options, html_options) end # Returns a set of select tags (one for year, month, day, hour, and minute) pre-selected for accessing a specified datetime-based @@ -214,7 +214,7 @@ module ActionView # # The selects are prepared for multi-parameter assignment to an Active Record object. def datetime_select(object_name, method, options = {}, html_options = {}) - InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_datetime_select_tag(options, html_options) + InstanceTag.new(object_name, method, self, options.delete(:object)).to_datetime_select_tag(options, html_options) end # Returns a set of html select-tags (one for year, month, day, hour, and minute) pre-selected with the +datetime+. diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 63a932320e..fa5a9bfac6 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -333,7 +333,7 @@ module ActionView # # => # def label(object_name, method, text = nil, options = {}) - InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_label_tag(text, options) + InstanceTag.new(object_name, method, self, options.delete(:object)).to_label_tag(text, options) end # Returns an input tag of the "text" type tailored for accessing a specified attribute (identified by +method+) on an object @@ -355,7 +355,7 @@ module ActionView # # => # def text_field(object_name, method, options = {}) - InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("text", options) + InstanceTag.new(object_name, method, self, options.delete(:object)).to_input_field_tag("text", options) end # Returns an input tag of the "password" type tailored for accessing a specified attribute (identified by +method+) on an object @@ -377,7 +377,7 @@ module ActionView # # => # def password_field(object_name, method, options = {}) - InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("password", options) + InstanceTag.new(object_name, method, self, options.delete(:object)).to_input_field_tag("password", options) end # Returns a hidden input tag tailored for accessing a specified attribute (identified by +method+) on an object @@ -395,7 +395,7 @@ module ActionView # hidden_field(:user, :token) # # => def hidden_field(object_name, method, options = {}) - InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("hidden", options) + InstanceTag.new(object_name, method, self, options.delete(:object)).to_input_field_tag("hidden", options) end # Returns an file upload input tag tailored for accessing a specified attribute (identified by +method+) on an object @@ -414,7 +414,7 @@ module ActionView # # => # def file_field(object_name, method, options = {}) - InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("file", options) + InstanceTag.new(object_name, method, self, options.delete(:object)).to_input_field_tag("file", options) end # Returns a textarea opening and closing tag set tailored for accessing a specified attribute (identified by +method+) @@ -442,7 +442,7 @@ module ActionView # # #{@entry.body} # # def text_area(object_name, method, options = {}) - InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_text_area_tag(options) + InstanceTag.new(object_name, method, self, options.delete(:object)).to_text_area_tag(options) end # Returns a checkbox tag tailored for accessing a specified attribute (identified by +method+) on an object @@ -468,7 +468,7 @@ module ActionView # # # def check_box(object_name, method, options = {}, checked_value = "1", unchecked_value = "0") - InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_check_box_tag(options, checked_value, unchecked_value) + InstanceTag.new(object_name, method, self, options.delete(:object)).to_check_box_tag(options, checked_value, unchecked_value) end # Returns a radio button tag for accessing a specified attribute (identified by +method+) on an object @@ -488,7 +488,7 @@ module ActionView # # => # # def radio_button(object_name, method, tag_value, options = {}) - InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_radio_button_tag(tag_value, options) + InstanceTag.new(object_name, method, self, options.delete(:object)).to_radio_button_tag(tag_value, options) end end @@ -501,9 +501,9 @@ module ActionView DEFAULT_RADIO_OPTIONS = { }.freeze unless const_defined?(:DEFAULT_RADIO_OPTIONS) DEFAULT_TEXT_AREA_OPTIONS = { "cols" => 40, "rows" => 20 }.freeze unless const_defined?(:DEFAULT_TEXT_AREA_OPTIONS) - def initialize(object_name, method_name, template_object, local_binding = nil, object = nil) + def initialize(object_name, method_name, template_object, object = nil) @object_name, @method_name = object_name.to_s.dup, method_name.to_s.dup - @template_object, @local_binding = template_object, local_binding + @template_object= template_object @object = object if @object_name.sub!(/\[\]$/,"") if object ||= @template_object.instance_variable_get("@#{Regexp.last_match.pre_match}") and object.respond_to?(:to_param) diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb index 0ca5cebcba..ab9e174621 100644 --- a/actionpack/lib/action_view/helpers/form_options_helper.rb +++ b/actionpack/lib/action_view/helpers/form_options_helper.rb @@ -96,7 +96,7 @@ module ActionView # By default, post.person_id is the selected option. Specify :selected => value to use a different selection # or :selected => nil to leave all options unselected. def select(object, method, choices, options = {}, html_options = {}) - InstanceTag.new(object, method, self, nil, options.delete(:object)).to_select_tag(choices, options, html_options) + InstanceTag.new(object, method, self, options.delete(:object)).to_select_tag(choices, options, html_options) end # Returns def collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {}) - InstanceTag.new(object, method, self, nil, options.delete(:object)).to_collection_select_tag(collection, value_method, text_method, options, html_options) + InstanceTag.new(object, method, self, options.delete(:object)).to_collection_select_tag(collection, value_method, text_method, options, html_options) end # Return select and option tags for the given object and method, using country_options_for_select to generate the list of option tags. def country_select(object, method, priority_countries = nil, options = {}, html_options = {}) - InstanceTag.new(object, method, self, nil, options.delete(:object)).to_country_select_tag(priority_countries, options, html_options) + InstanceTag.new(object, method, self, options.delete(:object)).to_country_select_tag(priority_countries, options, html_options) end # Return select and option tags for the given object and method, using @@ -169,7 +169,7 @@ module ActionView # # time_zone_select( "user", "time_zone", TZInfo::Timezone.all.sort, :model => TZInfo::Timezone) def time_zone_select(object, method, priority_zones = nil, options = {}, html_options = {}) - InstanceTag.new(object, method, self, nil, options.delete(:object)).to_time_zone_select_tag(priority_zones, options, html_options) + InstanceTag.new(object, method, self, options.delete(:object)).to_time_zone_select_tag(priority_zones, options, html_options) end # Accepts a container (hash, array, enumerable, your type) and returns a string of option tags. Given a container -- cgit v1.2.3 From 12cf8f348b591b7bb0dc899345293a8e37ddad7c Mon Sep 17 00:00:00 2001 From: Michael Koziarski Date: Fri, 27 Jun 2008 21:24:21 +0300 Subject: Move template_format logic out to the request so it's alongside the 'regular' request format. Use xhr? instead of the expensive trip through Request#accepts. --- actionpack/lib/action_controller/request.rb | 13 +++++++++++++ actionpack/lib/action_view/base.rb | 12 +----------- 2 files changed, 14 insertions(+), 11 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/request.rb b/actionpack/lib/action_controller/request.rb index 9b02f2c8a1..c91a3387a0 100755 --- a/actionpack/lib/action_controller/request.rb +++ b/actionpack/lib/action_controller/request.rb @@ -116,6 +116,19 @@ module ActionController @format = Mime::Type.lookup_by_extension(parameters[:format]) end + def template_format + parameter_format = parameters[:format] + + case + when parameter_format.blank? && !xhr? + :html + when parameter_format.blank? && xhr? + :js + else + parameter_format.to_sym + end + end + # Returns true if the request's "X-Requested-With" header contains # "XMLHttpRequest". (The Prototype Javascript library sends this header with # every Ajax request.) diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 9e255bd324..e8e690abec 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -273,17 +273,7 @@ module ActionView #:nodoc: return @template_format if @template_format if controller && controller.respond_to?(:request) - parameter_format = controller.request.parameters[:format] - accept_format = controller.request.accepts.first - - case - when parameter_format.blank? && accept_format != :js - @template_format = :html - when parameter_format.blank? && accept_format == :js - @template_format = :js - else - @template_format = parameter_format.to_sym - end + @template_format = controller.request.template_format else @template_format = :html end -- cgit v1.2.3 From d79cde37ea9a14fc6625297f40050296af7f7630 Mon Sep 17 00:00:00 2001 From: Michael Koziarski Date: Tue, 1 Jul 2008 20:37:21 +0300 Subject: Move the file exists checks outside write_asset_file_contents. This lets us avoid the relatively costly trip through compute_*_paths if the file already exists. --- actionpack/lib/action_view/helpers/asset_tag_helper.rb | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb index e5a95a961c..0122de47af 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb @@ -243,7 +243,7 @@ module ActionView joined_javascript_name = (cache == true ? "all" : cache) + ".js" joined_javascript_path = File.join(JAVASCRIPTS_DIR, joined_javascript_name) - write_asset_file_contents(joined_javascript_path, compute_javascript_paths(sources)) + write_asset_file_contents(joined_javascript_path, compute_javascript_paths(sources)) unless File.exists?(joined_javascript_path) javascript_src_tag(joined_javascript_name, options) else expand_javascript_sources(sources).collect { |source| javascript_src_tag(source, options) }.join("\n") @@ -370,7 +370,7 @@ module ActionView joined_stylesheet_name = (cache == true ? "all" : cache) + ".css" joined_stylesheet_path = File.join(STYLESHEETS_DIR, joined_stylesheet_name) - write_asset_file_contents(joined_stylesheet_path, compute_stylesheet_paths(sources)) + write_asset_file_contents(joined_stylesheet_path, compute_stylesheet_paths(sources)) unless File.exists?(joined_stylesheet_path) stylesheet_tag(joined_stylesheet_name, options) else expand_stylesheet_sources(sources).collect { |source| stylesheet_tag(source, options) }.join("\n") @@ -601,10 +601,8 @@ module ActionView end def write_asset_file_contents(joined_asset_path, asset_paths) - unless file_exist?(joined_asset_path) - FileUtils.mkdir_p(File.dirname(joined_asset_path)) - File.open(joined_asset_path, "w+") { |cache| cache.write(join_asset_file_contents(asset_paths)) } - end + FileUtils.mkdir_p(File.dirname(joined_asset_path)) + File.open(joined_asset_path, "w+") { |cache| cache.write(join_asset_file_contents(asset_paths)) } end end end -- cgit v1.2.3 From 75e04b52956512d554c83e0134a81c980c15b4fa Mon Sep 17 00:00:00 2001 From: Michael Koziarski Date: Tue, 1 Jul 2008 20:43:57 +0300 Subject: Tighten the rescue clause when dealing with invalid instance variable names in form_helper. --- actionpack/lib/action_view/helpers/form_helper.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index fa5a9bfac6..bafc635ad2 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -601,7 +601,11 @@ module ActionView end def object - @object || (@template_object.instance_variable_get("@#{@object_name}") rescue nil) + @object || @template_object.instance_variable_get("@#{@object_name}") + rescue NameError + # As @object_name may contain the nested syntax (item[subobject]) we + # need to fallback to nil. + nil end def value(object) -- cgit v1.2.3 From 42d215a925a228778e43f7040f03ad8f3eb5341c Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Thu, 3 Jul 2008 12:48:00 -0500 Subject: Moved TemplateHandlers to Base --- actionpack/lib/action_view/base.rb | 1 + actionpack/lib/action_view/helpers/cache_helper.rb | 2 +- actionpack/lib/action_view/inline_template.rb | 2 +- actionpack/lib/action_view/template.rb | 7 +++++-- 4 files changed, 8 insertions(+), 4 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index e8e690abec..169bee1bfc 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -151,6 +151,7 @@ module ActionView #:nodoc: # # See the ActionView::Helpers::PrototypeHelper::GeneratorMethods documentation for more details. class Base + extend TemplateHandlers include ERB::Util attr_accessor :base_path, :assigns, :template_extension, :first_render diff --git a/actionpack/lib/action_view/helpers/cache_helper.rb b/actionpack/lib/action_view/helpers/cache_helper.rb index 930c397785..c2aab5aa72 100644 --- a/actionpack/lib/action_view/helpers/cache_helper.rb +++ b/actionpack/lib/action_view/helpers/cache_helper.rb @@ -32,7 +32,7 @@ module ActionView # Topics listed alphabetically # <% end %> def cache(name = {}, options = nil, &block) - handler = Template.handler_class_for_extension(current_render_extension.to_sym) + handler = Base.handler_class_for_extension(current_render_extension.to_sym) handler.new(@controller).cache_fragment(block, name, options) end end diff --git a/actionpack/lib/action_view/inline_template.rb b/actionpack/lib/action_view/inline_template.rb index fd0ad48302..3a97f47e32 100644 --- a/actionpack/lib/action_view/inline_template.rb +++ b/actionpack/lib/action_view/inline_template.rb @@ -7,7 +7,7 @@ module ActionView #:nodoc: @extension = type @locals = locals || {} - @handler = self.class.handler_class_for_extension(@extension).new(@view) + @handler = Base.handler_class_for_extension(@extension).new(@view) end def method_key diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 0cba1942f7..d4118f0f86 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -1,6 +1,9 @@ module ActionView #:nodoc: class Template #:nodoc: - extend TemplateHandlers + class << self + # TODO: Deprecate + delegate :register_template_handler, :to => 'ActionView::Base' + end attr_accessor :locals attr_reader :handler, :path, :extension, :filename, :method @@ -20,7 +23,7 @@ module ActionView #:nodoc: set_extension_and_file_name @locals = locals || {} - @handler = self.class.handler_class_for_extension(@extension).new(@view) + @handler = Base.handler_class_for_extension(@extension).new(@view) end def render_template -- cgit v1.2.3 From b6f89a8bf59a0e6227c054d0be49baedf7b9f530 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Thu, 3 Jul 2008 12:49:54 -0500 Subject: Don't rely on view instance logger --- actionpack/lib/action_view/template_handlers/compilable.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/template_handlers/compilable.rb b/actionpack/lib/action_view/template_handlers/compilable.rb index 783456ab53..f436ebbe45 100644 --- a/actionpack/lib/action_view/template_handlers/compilable.rb +++ b/actionpack/lib/action_view/template_handlers/compilable.rb @@ -41,10 +41,10 @@ module ActionView file_name = template.filename || 'compiled-template' ActionView::Base::CompiledTemplates.module_eval(render_source, file_name, -line_offset) rescue Exception => e # errors from template code - if @view.logger - @view.logger.debug "ERROR: compiling #{render_symbol} RAISED #{e}" - @view.logger.debug "Function body: #{render_source}" - @view.logger.debug "Backtrace: #{e.backtrace.join("\n")}" + if Base.logger + Base.logger.debug "ERROR: compiling #{render_symbol} RAISED #{e}" + Base.logger.debug "Function body: #{render_source}" + Base.logger.debug "Backtrace: #{e.backtrace.join("\n")}" end raise ActionView::TemplateError.new(template, @view.assigns, e) -- cgit v1.2.3 From 7d5c8505f528f195433693d5074a00f7635955b2 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Thu, 3 Jul 2008 12:50:43 -0500 Subject: Use render on InlineTemplate --- actionpack/lib/action_view/base.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 169bee1bfc..d4802d7965 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -305,7 +305,7 @@ module ActionView #:nodoc: end def render_inline(text, local_assigns = {}, type = nil) - InlineTemplate.new(self, text, local_assigns, type).render_template + InlineTemplate.new(self, text, local_assigns, type).render end def wrap_content_for_layout(content) -- cgit v1.2.3 From 8a442e0d57fabedcaf3ded836cfc12f7067ead68 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Thu, 3 Jul 2008 13:06:00 -0500 Subject: Extracted Template rendering logic into Renderer module --- actionpack/lib/action_view.rb | 2 ++ actionpack/lib/action_view/inline_template.rb | 9 ++++--- actionpack/lib/action_view/partial_template.rb | 2 +- actionpack/lib/action_view/renderer.rb | 29 ++++++++++++++++++++++ actionpack/lib/action_view/template.rb | 33 +++++--------------------- 5 files changed, 42 insertions(+), 33 deletions(-) create mode 100644 actionpack/lib/action_view/renderer.rb (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index 973020a768..49768fe264 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -24,6 +24,8 @@ require 'action_view/template_handlers' require 'action_view/template_file' require 'action_view/view_load_paths' + +require 'action_view/renderer' require 'action_view/template' require 'action_view/partial_template' require 'action_view/inline_template' diff --git a/actionpack/lib/action_view/inline_template.rb b/actionpack/lib/action_view/inline_template.rb index 3a97f47e32..19ab92ce1a 100644 --- a/actionpack/lib/action_view/inline_template.rb +++ b/actionpack/lib/action_view/inline_template.rb @@ -1,5 +1,7 @@ module ActionView #:nodoc: - class InlineTemplate < Template #:nodoc: + class InlineTemplate #:nodoc: + include Renderer + def initialize(view, source, locals = {}, type = nil) @view = view @@ -7,11 +9,8 @@ module ActionView #:nodoc: @extension = type @locals = locals || {} + @method_key = @source @handler = Base.handler_class_for_extension(@extension).new(@view) end - - def method_key - @source - end end end diff --git a/actionpack/lib/action_view/partial_template.rb b/actionpack/lib/action_view/partial_template.rb index 6ebe165a15..72f831e937 100644 --- a/actionpack/lib/action_view/partial_template.rb +++ b/actionpack/lib/action_view/partial_template.rb @@ -18,7 +18,7 @@ module ActionView #:nodoc: def render ActionController::Base.benchmark("Rendered #{@path.path_without_format_and_extension}", Logger::DEBUG, false) do - @handler.render(self) + super end end diff --git a/actionpack/lib/action_view/renderer.rb b/actionpack/lib/action_view/renderer.rb new file mode 100644 index 0000000000..e6c64d2749 --- /dev/null +++ b/actionpack/lib/action_view/renderer.rb @@ -0,0 +1,29 @@ +module ActionView + module Renderer + # TODO: Local assigns should not be tied to template instance + attr_accessor :locals + + # TODO: These readers should be private + attr_reader :filename, :source, :handler, :method_key, :method + + def render + prepare! + @handler.render(self) + end + + private + def prepare! + unless @prepared + @view.send(:evaluate_assigns) + @view.current_render_extension = @extension + + if @handler.compilable? + @handler.compile_template(self) # compile the given template, if necessary + @method = @view.method_names[method_key] # Set the method name for this template and run it + end + + @prepared = true + end + end + end +end diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index d4118f0f86..8142232c8f 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -1,12 +1,13 @@ module ActionView #:nodoc: class Template #:nodoc: + include Renderer + class << self # TODO: Deprecate delegate :register_template_handler, :to => 'ActionView::Base' end - attr_accessor :locals - attr_reader :handler, :path, :extension, :filename, :method + attr_reader :path, :extension def initialize(view, path, use_full_path = nil, locals = {}) unless use_full_path == nil @@ -19,9 +20,10 @@ module ActionView #:nodoc: @original_path = path @path = TemplateFile.from_path(path) @view.first_render ||= @path.to_s - @source = nil # Don't read the source until we know that it is required + set_extension_and_file_name + @method_key = @filename @locals = locals || {} @handler = Base.handler_class_for_extension(@extension).new(@view) end @@ -38,37 +40,14 @@ module ActionView #:nodoc: end end - def render - prepare! - @handler.render(self) - end - - def path_without_extension - @path.path_without_extension - end - def source @source ||= File.read(self.filename) end - def method_key - @filename - end - def base_path_for_exception (@paths.find_load_path_for_path(@path) || @paths.first).to_s end - def prepare! - @view.send :evaluate_assigns - @view.current_render_extension = @extension - - if @handler.compilable? - @handler.compile_template(self) # compile the given template, if necessary - @method = @view.method_names[method_key] # Set the method name for this template and run it - end - end - private def set_extension_and_file_name @extension = @path.extension @@ -94,7 +73,7 @@ module ActionView #:nodoc: full_template_path = @original_path.include?('.') ? @original_path : "#{@original_path}.#{@view.template_format}.erb" display_paths = @paths.join(':') template_type = (@original_path =~ /layouts/i) ? 'layout' : 'template' - raise(MissingTemplate, "Missing #{template_type} #{full_template_path} in view path #{display_paths}") + raise MissingTemplate, "Missing #{template_type} #{full_template_path} in view path #{display_paths}" end end end -- cgit v1.2.3 From 1a478923dc909bf7b6aea4f2ad49cbeee6dea259 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Thu, 3 Jul 2008 14:01:45 -0500 Subject: Reduce the number of callsites for new TemplateFiles --- actionpack/lib/action_controller/base.rb | 5 +++-- actionpack/lib/action_view/base.rb | 28 ++++++++++++++++----------- actionpack/lib/action_view/view_load_paths.rb | 22 ++++++++++++--------- 3 files changed, 33 insertions(+), 22 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 009c9eec99..a4bade1bd5 100755 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -1235,8 +1235,9 @@ module ActionController #:nodoc: end def template_exempt_from_layout?(template_name = default_template_name) - template_name = @template.send(:template_file_from_name, template_name) if @template - @@exempt_from_layout.any? { |ext| template_name.to_s =~ ext } + extension = @template && @template.pick_template_extension(template_name) + name_with_extension = !template_name.include?('.') && extension ? "#{template_name}.#{extension}" : template_name + @@exempt_from_layout.any? { |ext| name_with_extension =~ ext } end def default_template_name(action_name = self.action_name) diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index d4802d7965..5a3fc4182f 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -284,6 +284,21 @@ module ActionView #:nodoc: view_paths.template_exists?(template_file_from_name(template_path)) end + # Gets the extension for an existing template with the given template_path. + # Returns the format with the extension if that template exists. + # + # pick_template_extension('users/show') + # # => 'html.erb' + # + # pick_template_extension('users/legacy') + # # => "rhtml" + # + def pick_template_extension(template_path) + if template = template_file_from_name(template_path) + template.extension + end + end + private # Renders the template present at template_path. The hash in local_assigns # is made available as local variables. @@ -336,19 +351,10 @@ module ActionView #:nodoc: def template_file_from_name(template_name) template_name = TemplateFile.from_path(template_name) - pick_template_extension(template_name) unless template_name.extension + pick_template(template_name) unless template_name.extension end - # Gets the extension for an existing template with the given template_path. - # Returns the format with the extension if that template exists. - # - # pick_template_extension('users/show') - # # => 'html.erb' - # - # pick_template_extension('users/legacy') - # # => "rhtml" - # - def pick_template_extension(file) + def pick_template(file) if f = self.view_paths.find_template_file_for_path(file.dup_with_extension(template_format)) || file_from_first_render(file) f elsif template_format == :js && f = self.view_paths.find_template_file_for_path(file.dup_with_extension(:html)) diff --git a/actionpack/lib/action_view/view_load_paths.rb b/actionpack/lib/action_view/view_load_paths.rb index f23ac665f1..6e439a009c 100644 --- a/actionpack/lib/action_view/view_load_paths.rb +++ b/actionpack/lib/action_view/view_load_paths.rb @@ -29,12 +29,10 @@ module ActionView #:nodoc: @paths.freeze end - # Tries to find the extension for the template name. - # If it does not it exist, tries again without the format extension - # find_template_file_for_partial_path('users/show') => 'html.erb' - # find_template_file_for_partial_path('users/legacy') => 'rhtml' - def find_template_file_for_partial_path(file) - @paths[file.path] || @paths[file.path_without_extension] || @paths[file.path_without_format_and_extension] + def find_template_file_for_partial_path(template_path, template_format) + @paths["#{template_path}.#{template_format}"] || + @paths[template_path] || + @paths[template_path.gsub(/\..*$/, '')] end private @@ -81,10 +79,10 @@ module ActionView #:nodoc: find { |path| path.paths[file.to_s] } end - def find_template_file_for_path(file) - file = TemplateFile.from_path(file) + def find_template_file_for_path(template_path) + template_path_without_extension, template_extension = path_and_extension(template_path.to_s) each do |path| - if f = path.find_template_file_for_partial_path(file) + if f = path.find_template_file_for_partial_path(template_path_without_extension, template_extension) return f end end @@ -95,5 +93,11 @@ module ActionView #:nodoc: def delete_paths!(paths) paths.each { |p1| delete_if { |p2| p1.to_s == p2.to_s } } end + + # Splits the path and extension from the given template_path and returns as an array. + def path_and_extension(template_path) + template_path_without_extension = template_path.sub(/\.(\w+)$/, '') + [template_path_without_extension, $1] + end end end -- cgit v1.2.3 From 570f5aad663fa3113772cf56306862829babc739 Mon Sep 17 00:00:00 2001 From: miloops Date: Tue, 1 Jul 2008 11:08:25 -0300 Subject: Allow date helpers to ignore date hidden field tags. [#503 state:resolved] Signed-off-by: Pratik Naik --- actionpack/lib/action_view/helpers/date_helper.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb index 50ae27da61..d018034ebe 100755 --- a/actionpack/lib/action_view/helpers/date_helper.rb +++ b/actionpack/lib/action_view/helpers/date_helper.rb @@ -159,7 +159,10 @@ module ActionView # Returns a set of select tags (one for hour, minute and optionally second) pre-selected for accessing a specified # time-based attribute (identified by +method+) on an object assigned to the template (identified by +object+). # You can include the seconds with :include_seconds. - # + # + # This method will also generate 3 input hidden tags, for the actual year, month and day unless the option + # :ignore_date is set to +true+. + # # If anything is passed in the html_options hash it will be applied to every select tag in the set. # # ==== Examples @@ -655,7 +658,7 @@ module ActionView order.reverse.each do |param| # Send hidden fields for discarded elements once output has started # This ensures AR can reconstruct valid dates using ParseDate - next if discard[param] && date_or_time_select.empty? + next if discard[param] && (date_or_time_select.empty? || options[:ignore_date]) date_or_time_select.insert(0, self.send("select_#{param}", datetime, options_with_prefix(position[param], options.merge(:use_hidden => discard[param])), html_options)) date_or_time_select.insert(0, -- cgit v1.2.3 From bad1eac91d1549631dca8e93e7e846911649acf7 Mon Sep 17 00:00:00 2001 From: josevalim Date: Sat, 14 Jun 2008 10:45:32 +0200 Subject: Allow caches_action to accept cache store options. [#416 state:resolved] Signed-off-by: Pratik Naik --- actionpack/lib/action_controller/caching/actions.rb | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/caching/actions.rb b/actionpack/lib/action_controller/caching/actions.rb index 65a36f7f98..234ef8ae5b 100644 --- a/actionpack/lib/action_controller/caching/actions.rb +++ b/actionpack/lib/action_controller/caching/actions.rb @@ -27,13 +27,15 @@ module ActionController #:nodoc: # You can set modify the default action cache path by passing a :cache_path option. This will be passed directly to ActionCachePath.path_for. This is handy # for actions with multiple possible routes that should be cached differently. If a block is given, it is called with the current controller instance. # - # And you can also use :if to pass a Proc that specifies when the action should be cached. + # And you can also use :if (or :unless) to pass a Proc that specifies when the action should be cached. + # + # Finally, if you are using memcached, you can also pass :expires_in. # # class ListsController < ApplicationController # before_filter :authenticate, :except => :public # caches_page :public # caches_action :index, :if => Proc.new { |c| !c.request.format.json? } # cache if is not a JSON request - # caches_action :show, :cache_path => { :project => 1 } + # caches_action :show, :cache_path => { :project => 1 }, :expires_in => 1.hour # caches_action :feed, :cache_path => Proc.new { |controller| # controller.params[:user_id] ? # controller.send(:user_list_url, c.params[:user_id], c.params[:id]) : @@ -56,8 +58,10 @@ module ActionController #:nodoc: def caches_action(*actions) return unless cache_configured? options = actions.extract_options! - cache_filter = ActionCacheFilter.new(:layout => options.delete(:layout), :cache_path => options.delete(:cache_path)) - around_filter(cache_filter, {:only => actions}.merge(options)) + filter_options = { :only => actions, :if => options.delete(:if), :unless => options.delete(:unless) } + + cache_filter = ActionCacheFilter.new(:layout => options.delete(:layout), :cache_path => options.delete(:cache_path), :store_options => options) + around_filter(cache_filter, filter_options) end end @@ -80,8 +84,8 @@ module ActionController #:nodoc: end def before(controller) - cache_path = ActionCachePath.new(controller, path_options_for(controller, @options)) - if cache = controller.read_fragment(cache_path.path) + cache_path = ActionCachePath.new(controller, path_options_for(controller, @options.slice(:cache_path))) + if cache = controller.read_fragment(cache_path.path, @options[:store_options]) controller.rendered_action_cache = true set_content_type!(controller, cache_path.extension) options = { :text => cache } @@ -96,7 +100,7 @@ module ActionController #:nodoc: def after(controller) return if controller.rendered_action_cache || !caching_allowed(controller) action_content = cache_layout? ? content_for_layout(controller) : controller.response.body - controller.write_fragment(controller.action_cache_path.path, action_content) + controller.write_fragment(controller.action_cache_path.path, action_content, @options[:store_options]) end private -- cgit v1.2.3 From 01637796d712943ebf9e9a76aa5c708edfab4d02 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Thu, 3 Jul 2008 21:08:27 -0500 Subject: Revert "Moved TemplateHandlers to Base" This reverts commit 42d215a925a228778e43f7040f03ad8f3eb5341c. Conflicts: actionpack/lib/action_view/inline_template.rb actionpack/lib/action_view/template.rb --- actionpack/lib/action_view/base.rb | 1 - actionpack/lib/action_view/helpers/cache_helper.rb | 2 +- actionpack/lib/action_view/inline_template.rb | 2 +- actionpack/lib/action_view/template.rb | 8 ++------ 4 files changed, 4 insertions(+), 9 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 5a3fc4182f..d18c701619 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -151,7 +151,6 @@ module ActionView #:nodoc: # # See the ActionView::Helpers::PrototypeHelper::GeneratorMethods documentation for more details. class Base - extend TemplateHandlers include ERB::Util attr_accessor :base_path, :assigns, :template_extension, :first_render diff --git a/actionpack/lib/action_view/helpers/cache_helper.rb b/actionpack/lib/action_view/helpers/cache_helper.rb index c2aab5aa72..930c397785 100644 --- a/actionpack/lib/action_view/helpers/cache_helper.rb +++ b/actionpack/lib/action_view/helpers/cache_helper.rb @@ -32,7 +32,7 @@ module ActionView # Topics listed alphabetically # <% end %> def cache(name = {}, options = nil, &block) - handler = Base.handler_class_for_extension(current_render_extension.to_sym) + handler = Template.handler_class_for_extension(current_render_extension.to_sym) handler.new(@controller).cache_fragment(block, name, options) end end diff --git a/actionpack/lib/action_view/inline_template.rb b/actionpack/lib/action_view/inline_template.rb index 19ab92ce1a..1ccb23a3fc 100644 --- a/actionpack/lib/action_view/inline_template.rb +++ b/actionpack/lib/action_view/inline_template.rb @@ -10,7 +10,7 @@ module ActionView #:nodoc: @locals = locals || {} @method_key = @source - @handler = Base.handler_class_for_extension(@extension).new(@view) + @handler = Template.handler_class_for_extension(@extension).new(@view) end end end diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 8142232c8f..dbc8ccdee8 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -1,12 +1,8 @@ module ActionView #:nodoc: class Template #:nodoc: + extend TemplateHandlers include Renderer - class << self - # TODO: Deprecate - delegate :register_template_handler, :to => 'ActionView::Base' - end - attr_reader :path, :extension def initialize(view, path, use_full_path = nil, locals = {}) @@ -25,7 +21,7 @@ module ActionView #:nodoc: @method_key = @filename @locals = locals || {} - @handler = Base.handler_class_for_extension(@extension).new(@view) + @handler = self.class.handler_class_for_extension(@extension).new(@view) end def render_template -- cgit v1.2.3 From db5839107951b000633fa8405f78e5c315b6656a Mon Sep 17 00:00:00 2001 From: Michael Koziarski Date: Mon, 23 Jun 2008 20:32:26 +0300 Subject: Remove old broken follow_redirect from functional tests. Still works in integration tests. The follow_redirect in functional tests only worked if you used redirect_to :id=>foo, :action=>bar, rather than named routes. --- actionpack/lib/action_controller/test_process.rb | 9 --------- 1 file changed, 9 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/test_process.rb b/actionpack/lib/action_controller/test_process.rb index 0cf143210d..8ae73a66f4 100644 --- a/actionpack/lib/action_controller/test_process.rb +++ b/actionpack/lib/action_controller/test_process.rb @@ -404,15 +404,6 @@ module ActionController #:nodoc: end alias xhr :xml_http_request - def follow_redirect - redirected_controller = @response.redirected_to[:controller] - if redirected_controller && redirected_controller != @controller.controller_name - raise "Can't follow redirects outside of current controller (from #{@controller.controller_name} to #{redirected_controller})" - end - - get(@response.redirected_to.delete(:action), @response.redirected_to.stringify_keys) - end - def assigns(key = nil) if key.nil? @response.template.assigns -- cgit v1.2.3 From c3aaba0180f0710094d974b4ba4659bce81446df Mon Sep 17 00:00:00 2001 From: Michael Koziarski Date: Mon, 23 Jun 2008 19:46:15 +0300 Subject: Simplify the implementation of assert_redirected_to to normalise the urls before comparing. Also allows for a simpler implementation of redirect_to without most of the recursion. Also allows for assert_redirected_to @some_record --- .../assertions/response_assertions.rb | 96 +++++----------------- actionpack/lib/action_controller/base.rb | 32 ++++---- 2 files changed, 37 insertions(+), 91 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/assertions/response_assertions.rb b/actionpack/lib/action_controller/assertions/response_assertions.rb index 3deda0b45a..3ecaee641f 100644 --- a/actionpack/lib/action_controller/assertions/response_assertions.rb +++ b/actionpack/lib/action_controller/assertions/response_assertions.rb @@ -56,75 +56,18 @@ module ActionController # # assert that the redirection was to the named route login_url # assert_redirected_to login_url # + # # assert that the redirection was to the url for @customer + # assert_redirected_to @customer + # def assert_redirected_to(options = {}, message=nil) clean_backtrace do assert_response(:redirect, message) return true if options == @response.redirected_to - ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty? - - begin - url = {} - original = { :expected => options, :actual => @response.redirected_to.is_a?(Symbol) ? @response.redirected_to : @response.redirected_to.dup } - original.each do |key, value| - if value.is_a?(Symbol) - value = @controller.respond_to?(value, true) ? @controller.send(value) : @controller.send("hash_for_#{value}_url") - end - - unless value.is_a?(Hash) - request = case value - when NilClass then nil - when /^\w+:\/\// then recognized_request_for(%r{^(\w+://.*?(/|$|\?))(.*)$} =~ value ? $3 : nil) - else recognized_request_for(value) - end - value = request.path_parameters if request - end - - if value.is_a?(Hash) # stringify 2 levels of hash keys - if name = value.delete(:use_route) - route = ActionController::Routing::Routes.named_routes[name] - value.update(route.parameter_shell) - end - - value.stringify_keys! - value.values.select { |v| v.is_a?(Hash) }.collect { |v| v.stringify_keys! } - if key == :expected && value['controller'] == @controller.controller_name && original[:actual].is_a?(Hash) - original[:actual].stringify_keys! - value.delete('controller') if original[:actual]['controller'].nil? || original[:actual]['controller'] == value['controller'] - end - end - - if value.respond_to?(:[]) && value['controller'] - value['controller'] = value['controller'].to_s - if key == :actual && value['controller'].first != '/' && !value['controller'].include?('/') - new_controller_path = ActionController::Routing.controller_relative_to(value['controller'], @controller.class.controller_path) - value['controller'] = new_controller_path if value['controller'] != new_controller_path && ActionController::Routing.possible_controllers.include?(new_controller_path) && @response.redirected_to.is_a?(Hash) - end - value['controller'] = value['controller'][1..-1] if value['controller'].first == '/' # strip leading hash - end - url[key] = value - end - - @response_diff = url[:actual].diff(url[:expected]) if url[:actual] - msg = build_message(message, "expected a redirect to , found one to , a difference of ", url[:expected], url[:actual], @response_diff) - - assert_block(msg) do - url[:expected].keys.all? do |k| - if k == :controller then url[:expected][k] == ActionController::Routing.controller_relative_to(url[:actual][k], @controller.class.controller_path) - else parameterize(url[:expected][k]) == parameterize(url[:actual][k]) - end - end - end - rescue ActionController::RoutingError # routing failed us, so match the strings only. - msg = build_message(message, "expected a redirect to , found one to ", options, @response.redirect_url) - url_regexp = %r{^(\w+://.*?(/|$|\?))(.*)$} - eurl, epath, url, path = [options, @response.redirect_url].collect do |url| - u, p = (url_regexp =~ url) ? [$1, $3] : [nil, url] - [u, (p.first == '/') ? p : '/' + p] - end.flatten + redirected_to_after_normalisation = normalize_argument_to_redirection(@response.redirected_to) + options_after_normalisation = normalize_argument_to_redirection(options) - assert_equal(eurl, url, msg) if eurl && url - assert_equal(epath, path, msg) if epath && path - end + assert_equal redirected_to_after_normalisation, options_after_normalisation, + "Expected response to be a redirect to <#{options_after_normalisation}> but was a redirect to <#{redirected_to_after_normalisation}>" end end @@ -150,23 +93,24 @@ module ActionController end private - # Recognizes the route for a given path. - def recognized_request_for(path, request_method = nil) - path = "/#{path}" unless path.first == '/' - - # Assume given controller - request = ActionController::TestRequest.new({}, {}, nil) - request.env["REQUEST_METHOD"] = request_method.to_s.upcase if request_method - request.path = path - - ActionController::Routing::Routes.recognize(request) - request - end # Proxy to to_param if the object will respond to it. def parameterize(value) value.respond_to?(:to_param) ? value.to_param : value end + + def normalize_argument_to_redirection(fragment) + after_routing = @controller.url_for(fragment) + if after_routing =~ %r{^\w+://.*} + after_routing + else + # FIXME - this should probably get removed. + if after_routing.first != '/' + after_routing = '/' + after_routing + end + @request.protocol + @request.host_with_port + after_routing + end + end end end end diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index a4bade1bd5..58eb5cabcd 100755 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -1042,29 +1042,31 @@ module ActionController #:nodoc: status = 302 end + response.redirected_to= options + logger.info("Redirected to #{options}") if logger && logger.info? + case options when %r{^\w+://.*} - raise DoubleRenderError if performed? - logger.info("Redirected to #{options}") if logger && logger.info? - response.redirect(options, interpret_status(status)) - response.redirected_to = options - @performed_redirect = true - + redirect_to_full_url(options, status) when String - redirect_to(request.protocol + request.host_with_port + options, :status=>status) - + redirect_to_full_url(request.protocol + request.host_with_port + options, status) when :back - request.env["HTTP_REFERER"] ? redirect_to(request.env["HTTP_REFERER"], :status=>status) : raise(RedirectBackError) - - when Hash - redirect_to(url_for(options), :status=>status) - response.redirected_to = options - + if referer = request.headers["Referer"] + redirect_to(referer, :status=>status) + else + raise RedirectBackError + end else - redirect_to(url_for(options), :status=>status) + redirect_to_full_url(url_for(options), status) end end + def redirect_to_full_url(url, status) + raise DoubleRenderError if performed? + response.redirect(url, interpret_status(status)) + @performed_redirect = true + end + # Sets a HTTP 1.1 Cache-Control header. Defaults to issuing a "private" instruction, so that # intermediate caches shouldn't cache the response. # -- cgit v1.2.3 From 271f5b655fb58b08a89a144aa835f7b70617c399 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Fri, 4 Jul 2008 12:51:16 -0700 Subject: Fix rdoc for Filters::ClassMethods --- actionpack/lib/action_controller/filters.rb | 389 ++++++++++++++-------------- 1 file changed, 194 insertions(+), 195 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/filters.rb b/actionpack/lib/action_controller/filters.rb index 60d92d9b98..155d8b480a 100644 --- a/actionpack/lib/action_controller/filters.rb +++ b/actionpack/lib/action_controller/filters.rb @@ -7,6 +7,200 @@ module ActionController #:nodoc: end end + class FilterChain < ActiveSupport::Callbacks::CallbackChain #:nodoc: + def append_filter_to_chain(filters, filter_type, &block) + pos = find_filter_append_position(filters, filter_type) + update_filter_chain(filters, filter_type, pos, &block) + end + + def prepend_filter_to_chain(filters, filter_type, &block) + pos = find_filter_prepend_position(filters, filter_type) + update_filter_chain(filters, filter_type, pos, &block) + end + + def create_filters(filters, filter_type, &block) + filters, conditions = extract_options(filters, &block) + filters.map! { |filter| find_or_create_filter(filter, filter_type, conditions) } + filters + end + + def skip_filter_in_chain(*filters, &test) + filters, conditions = extract_options(filters) + filters.each do |filter| + if callback = find(filter) then delete(callback) end + end if conditions.empty? + update_filter_in_chain(filters, :skip => conditions, &test) + end + + private + def update_filter_chain(filters, filter_type, pos, &block) + new_filters = create_filters(filters, filter_type, &block) + insert(pos, new_filters).flatten! + end + + def find_filter_append_position(filters, filter_type) + # appending an after filter puts it at the end of the call chain + # before and around filters go before the first after filter in the chain + unless filter_type == :after + each_with_index do |f,i| + return i if f.after? + end + end + return -1 + end + + def find_filter_prepend_position(filters, filter_type) + # prepending a before or around filter puts it at the front of the call chain + # after filters go before the first after filter in the chain + if filter_type == :after + each_with_index do |f,i| + return i if f.after? + end + return -1 + end + return 0 + end + + def find_or_create_filter(filter, filter_type, options = {}) + update_filter_in_chain([filter], options) + + if found_filter = find(filter) { |f| f.type == filter_type } + found_filter + else + filter_kind = case + when filter.respond_to?(:before) && filter_type == :before + :before + when filter.respond_to?(:after) && filter_type == :after + :after + else + :filter + end + + case filter_type + when :before + BeforeFilter.new(filter_kind, filter, options) + when :after + AfterFilter.new(filter_kind, filter, options) + else + AroundFilter.new(filter_kind, filter, options) + end + end + end + + def update_filter_in_chain(filters, options, &test) + filters.map! { |f| block_given? ? find(f, &test) : find(f) } + filters.compact! + + map! do |filter| + if filters.include?(filter) + new_filter = filter.dup + new_filter.options.merge!(options) + new_filter + else + filter + end + end + end + end + + class Filter < ActiveSupport::Callbacks::Callback #:nodoc: + def before? + self.class == BeforeFilter + end + + def after? + self.class == AfterFilter + end + + def around? + self.class == AroundFilter + end + + private + def should_not_skip?(controller) + if options[:skip] + !included_in_action?(controller, options[:skip]) + else + true + end + end + + def included_in_action?(controller, options) + if options[:only] + Array(options[:only]).map(&:to_s).include?(controller.action_name) + elsif options[:except] + !Array(options[:except]).map(&:to_s).include?(controller.action_name) + else + true + end + end + + def should_run_callback?(controller) + should_not_skip?(controller) && included_in_action?(controller, options) && super + end + end + + class AroundFilter < Filter #:nodoc: + def type + :around + end + + def call(controller, &block) + if should_run_callback?(controller) + method = filter_responds_to_before_and_after? ? around_proc : self.method + + # For around_filter do |controller, action| + if method.is_a?(Proc) && method.arity == 2 + evaluate_method(method, controller, block) + else + evaluate_method(method, controller, &block) + end + else + block.call + end + end + + private + def filter_responds_to_before_and_after? + method.respond_to?(:before) && method.respond_to?(:after) + end + + def around_proc + Proc.new do |controller, action| + method.before(controller) + + if controller.send!(:performed?) + controller.send!(:halt_filter_chain, method, :rendered_or_redirected) + else + begin + action.call + ensure + method.after(controller) + end + end + end + end + end + + class BeforeFilter < Filter #:nodoc: + def type + :before + end + + def call(controller, &block) + super + if controller.send!(:performed?) + controller.send!(:halt_filter_chain, method, :rendered_or_redirected) + end + end + end + + class AfterFilter < Filter #:nodoc: + def type + :after + end + end + # Filters enable controllers to run shared pre- and post-processing code for its actions. These filters can be used to do # authentication, caching, or auditing before the intended action is performed. Or to do localization or output # compression after the action has been performed. Filters have access to the request, response, and all the instance @@ -245,201 +439,6 @@ module ActionController #:nodoc: # filter and controller action will not be run. If +before+ renders or redirects, # the second half of +around+ and will still run but +after+ and the # action will not. If +around+ fails to yield, +after+ will not be run. - - class FilterChain < ActiveSupport::Callbacks::CallbackChain #:nodoc: - def append_filter_to_chain(filters, filter_type, &block) - pos = find_filter_append_position(filters, filter_type) - update_filter_chain(filters, filter_type, pos, &block) - end - - def prepend_filter_to_chain(filters, filter_type, &block) - pos = find_filter_prepend_position(filters, filter_type) - update_filter_chain(filters, filter_type, pos, &block) - end - - def create_filters(filters, filter_type, &block) - filters, conditions = extract_options(filters, &block) - filters.map! { |filter| find_or_create_filter(filter, filter_type, conditions) } - filters - end - - def skip_filter_in_chain(*filters, &test) - filters, conditions = extract_options(filters) - filters.each do |filter| - if callback = find(filter) then delete(callback) end - end if conditions.empty? - update_filter_in_chain(filters, :skip => conditions, &test) - end - - private - def update_filter_chain(filters, filter_type, pos, &block) - new_filters = create_filters(filters, filter_type, &block) - insert(pos, new_filters).flatten! - end - - def find_filter_append_position(filters, filter_type) - # appending an after filter puts it at the end of the call chain - # before and around filters go before the first after filter in the chain - unless filter_type == :after - each_with_index do |f,i| - return i if f.after? - end - end - return -1 - end - - def find_filter_prepend_position(filters, filter_type) - # prepending a before or around filter puts it at the front of the call chain - # after filters go before the first after filter in the chain - if filter_type == :after - each_with_index do |f,i| - return i if f.after? - end - return -1 - end - return 0 - end - - def find_or_create_filter(filter, filter_type, options = {}) - update_filter_in_chain([filter], options) - - if found_filter = find(filter) { |f| f.type == filter_type } - found_filter - else - filter_kind = case - when filter.respond_to?(:before) && filter_type == :before - :before - when filter.respond_to?(:after) && filter_type == :after - :after - else - :filter - end - - case filter_type - when :before - BeforeFilter.new(filter_kind, filter, options) - when :after - AfterFilter.new(filter_kind, filter, options) - else - AroundFilter.new(filter_kind, filter, options) - end - end - end - - def update_filter_in_chain(filters, options, &test) - filters.map! { |f| block_given? ? find(f, &test) : find(f) } - filters.compact! - - map! do |filter| - if filters.include?(filter) - new_filter = filter.dup - new_filter.options.merge!(options) - new_filter - else - filter - end - end - end - end - - class Filter < ActiveSupport::Callbacks::Callback #:nodoc: - def before? - self.class == BeforeFilter - end - - def after? - self.class == AfterFilter - end - - def around? - self.class == AroundFilter - end - - private - def should_not_skip?(controller) - if options[:skip] - !included_in_action?(controller, options[:skip]) - else - true - end - end - - def included_in_action?(controller, options) - if options[:only] - Array(options[:only]).map(&:to_s).include?(controller.action_name) - elsif options[:except] - !Array(options[:except]).map(&:to_s).include?(controller.action_name) - else - true - end - end - - def should_run_callback?(controller) - should_not_skip?(controller) && included_in_action?(controller, options) && super - end - end - - class AroundFilter < Filter #:nodoc: - def type - :around - end - - def call(controller, &block) - if should_run_callback?(controller) - method = filter_responds_to_before_and_after? ? around_proc : self.method - - # For around_filter do |controller, action| - if method.is_a?(Proc) && method.arity == 2 - evaluate_method(method, controller, block) - else - evaluate_method(method, controller, &block) - end - else - block.call - end - end - - private - def filter_responds_to_before_and_after? - method.respond_to?(:before) && method.respond_to?(:after) - end - - def around_proc - Proc.new do |controller, action| - method.before(controller) - - if controller.send!(:performed?) - controller.send!(:halt_filter_chain, method, :rendered_or_redirected) - else - begin - action.call - ensure - method.after(controller) - end - end - end - end - end - - class BeforeFilter < Filter #:nodoc: - def type - :before - end - - def call(controller, &block) - super - if controller.send!(:performed?) - controller.send!(:halt_filter_chain, method, :rendered_or_redirected) - end - end - end - - class AfterFilter < Filter #:nodoc: - def type - :after - end - end - module ClassMethods # The passed filters will be appended to the filter_chain and # will execute before the action on this controller is performed. -- cgit v1.2.3 From 1dcc59121b9f0c332f6fe93f90fb028ff3448899 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sat, 5 Jul 2008 12:05:50 -0500 Subject: Renamed Renderer to Renderable --- actionpack/lib/action_view.rb | 2 +- actionpack/lib/action_view/inline_template.rb | 2 +- actionpack/lib/action_view/renderable.rb | 29 +++++++++++++++++++++++++++ actionpack/lib/action_view/renderer.rb | 29 --------------------------- actionpack/lib/action_view/template.rb | 2 +- 5 files changed, 32 insertions(+), 32 deletions(-) create mode 100644 actionpack/lib/action_view/renderable.rb delete mode 100644 actionpack/lib/action_view/renderer.rb (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index 49768fe264..8f928d6fdf 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -25,7 +25,7 @@ require 'action_view/template_handlers' require 'action_view/template_file' require 'action_view/view_load_paths' -require 'action_view/renderer' +require 'action_view/renderable' require 'action_view/template' require 'action_view/partial_template' require 'action_view/inline_template' diff --git a/actionpack/lib/action_view/inline_template.rb b/actionpack/lib/action_view/inline_template.rb index 1ccb23a3fc..49147901a1 100644 --- a/actionpack/lib/action_view/inline_template.rb +++ b/actionpack/lib/action_view/inline_template.rb @@ -1,6 +1,6 @@ module ActionView #:nodoc: class InlineTemplate #:nodoc: - include Renderer + include Renderable def initialize(view, source, locals = {}, type = nil) @view = view diff --git a/actionpack/lib/action_view/renderable.rb b/actionpack/lib/action_view/renderable.rb new file mode 100644 index 0000000000..61bd8140fb --- /dev/null +++ b/actionpack/lib/action_view/renderable.rb @@ -0,0 +1,29 @@ +module ActionView + module Renderable + # TODO: Local assigns should not be tied to template instance + attr_accessor :locals + + # TODO: These readers should be private + attr_reader :filename, :source, :handler, :method_key, :method + + def render + prepare! + @handler.render(self) + end + + private + def prepare! + unless @prepared + @view.send(:evaluate_assigns) + @view.current_render_extension = @extension + + if @handler.compilable? + @handler.compile_template(self) # compile the given template, if necessary + @method = @view.method_names[method_key] # Set the method name for this template and run it + end + + @prepared = true + end + end + end +end diff --git a/actionpack/lib/action_view/renderer.rb b/actionpack/lib/action_view/renderer.rb deleted file mode 100644 index e6c64d2749..0000000000 --- a/actionpack/lib/action_view/renderer.rb +++ /dev/null @@ -1,29 +0,0 @@ -module ActionView - module Renderer - # TODO: Local assigns should not be tied to template instance - attr_accessor :locals - - # TODO: These readers should be private - attr_reader :filename, :source, :handler, :method_key, :method - - def render - prepare! - @handler.render(self) - end - - private - def prepare! - unless @prepared - @view.send(:evaluate_assigns) - @view.current_render_extension = @extension - - if @handler.compilable? - @handler.compile_template(self) # compile the given template, if necessary - @method = @view.method_names[method_key] # Set the method name for this template and run it - end - - @prepared = true - end - end - end -end diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index dbc8ccdee8..f696ea366d 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -1,7 +1,7 @@ module ActionView #:nodoc: class Template #:nodoc: extend TemplateHandlers - include Renderer + include Renderable attr_reader :path, :extension -- cgit v1.2.3 From 39ba2da82bcc2f9fad494e6ac0a66a3387ab8ee2 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sat, 5 Jul 2008 16:27:43 -0500 Subject: Moved complied method name logic into Renderable --- actionpack/lib/action_view/inline_template.rb | 10 +++++++++ actionpack/lib/action_view/renderable.rb | 4 ++++ actionpack/lib/action_view/template.rb | 9 +++++++- .../action_view/template_handlers/compilable.rb | 24 ++-------------------- 4 files changed, 24 insertions(+), 23 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/inline_template.rb b/actionpack/lib/action_view/inline_template.rb index 49147901a1..fb5e4408db 100644 --- a/actionpack/lib/action_view/inline_template.rb +++ b/actionpack/lib/action_view/inline_template.rb @@ -2,6 +2,10 @@ module ActionView #:nodoc: class InlineTemplate #:nodoc: include Renderable + # Count the number of inline templates + cattr_accessor :inline_template_count + @@inline_template_count = 0 + def initialize(view, source, locals = {}, type = nil) @view = view @@ -12,5 +16,11 @@ module ActionView #:nodoc: @method_key = @source @handler = Template.handler_class_for_extension(@extension).new(@view) end + + private + # FIXME: Modifying this shared variable may not thread safe + def method_name_path_segment + "inline_#{@@inline_template_count += 1}" + end end end diff --git a/actionpack/lib/action_view/renderable.rb b/actionpack/lib/action_view/renderable.rb index 61bd8140fb..d73dc3e2dc 100644 --- a/actionpack/lib/action_view/renderable.rb +++ b/actionpack/lib/action_view/renderable.rb @@ -11,6 +11,10 @@ module ActionView @handler.render(self) end + def method_name + ['_run', @extension, method_name_path_segment].compact.join('_').to_sym + end + private def prepare! unless @prepared diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index f696ea366d..56d740f478 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -37,7 +37,7 @@ module ActionView #:nodoc: end def source - @source ||= File.read(self.filename) + @source ||= File.read(@filename) end def base_path_for_exception @@ -71,5 +71,12 @@ module ActionView #:nodoc: template_type = (@original_path =~ /layouts/i) ? 'layout' : 'template' raise MissingTemplate, "Missing #{template_type} #{full_template_path} in view path #{display_paths}" end + + def method_name_path_segment + s = File.expand_path(@filename) + s.sub!(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}/, '') if defined?(RAILS_ROOT) + s.gsub!(/([^a-zA-Z0-9_])/) { $1.ord } + s + end end end diff --git a/actionpack/lib/action_view/template_handlers/compilable.rb b/actionpack/lib/action_view/template_handlers/compilable.rb index f436ebbe45..d95a5c8419 100644 --- a/actionpack/lib/action_view/template_handlers/compilable.rb +++ b/actionpack/lib/action_view/template_handlers/compilable.rb @@ -1,7 +1,6 @@ module ActionView module TemplateHandlers module Compilable - def self.included(base) base.extend ClassMethod @@ -12,10 +11,6 @@ module ActionView # Map method names to the names passed in local assigns so far base.cattr_accessor :template_args base.template_args = {} - - # Count the number of inline templates - base.cattr_accessor :inline_template_count - base.inline_template_count = 0 end module ClassMethod @@ -24,7 +19,7 @@ module ActionView true end end - + def render(template) @view.send :execute, template end @@ -75,22 +70,7 @@ module ActionView end def assign_method_name(template) - @view.method_names[template.method_key] ||= compiled_method_name(template) - end - - def compiled_method_name(template) - ['_run', self.class.to_s.demodulize.underscore, compiled_method_name_file_path_segment(template.filename)].compact.join('_').to_sym - end - - def compiled_method_name_file_path_segment(file_name) - if file_name - s = File.expand_path(file_name) - s.sub!(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}/, '') if defined?(RAILS_ROOT) - s.gsub!(/([^a-zA-Z0-9_])/) { $1.ord } - s - else - (self.inline_template_count += 1).to_s - end + @view.method_names[template.method_key] ||= template.method_name end # Method to create the source code for a given template. -- cgit v1.2.3 From cd6fe831526d84ae40e425cadbf22f42a375de2a Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sat, 5 Jul 2008 16:34:51 -0500 Subject: Ensure all complied method names are cleaned up in the error backtrace --- actionpack/lib/action_view/template_error.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/template_error.rb b/actionpack/lib/action_view/template_error.rb index 65d80362b5..a1be1a8833 100644 --- a/actionpack/lib/action_view/template_error.rb +++ b/actionpack/lib/action_view/template_error.rb @@ -105,6 +105,6 @@ module ActionView end if defined?(Exception::TraceSubstitutions) - Exception::TraceSubstitutions << [/:in\s+`_run_(html|xml).*'\s*$/, ''] + Exception::TraceSubstitutions << [/:in\s+`_run_.*'\s*$/, ''] Exception::TraceSubstitutions << [%r{^\s*#{Regexp.escape RAILS_ROOT}/}, ''] if defined?(RAILS_ROOT) end -- cgit v1.2.3 From 27f382641c9ec945a1d657f5efba6a06296dca54 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sat, 5 Jul 2008 17:31:57 -0500 Subject: Deprecated TemplateHandler line offset --- actionpack/lib/action_view/template_handler.rb | 8 -- .../lib/action_view/template_handlers/builder.rb | 12 +-- .../action_view/template_handlers/compilable.rb | 101 ++++++++++----------- .../lib/action_view/template_handlers/rjs.rb | 8 +- 4 files changed, 55 insertions(+), 74 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/template_handler.rb b/actionpack/lib/action_view/template_handler.rb index 39e578e586..78586d6142 100644 --- a/actionpack/lib/action_view/template_handler.rb +++ b/actionpack/lib/action_view/template_handler.rb @@ -1,9 +1,5 @@ module ActionView class TemplateHandler - def self.line_offset - 0 - end - def self.compilable? false end @@ -22,10 +18,6 @@ module ActionView self.class.compilable? end - def line_offset - self.class.line_offset - end - # Called by CacheHelper#cache def cache_fragment(block, name = {}, options = nil) end diff --git a/actionpack/lib/action_view/template_handlers/builder.rb b/actionpack/lib/action_view/template_handlers/builder.rb index ee02ce1a6f..2d413490bd 100644 --- a/actionpack/lib/action_view/template_handlers/builder.rb +++ b/actionpack/lib/action_view/template_handlers/builder.rb @@ -5,17 +5,11 @@ module ActionView class Builder < TemplateHandler include Compilable - def self.line_offset - 2 - end - def compile(template) - content_type_handler = (@view.send!(:controller).respond_to?(:response) ? "controller.response" : "controller") - - "#{content_type_handler}.content_type ||= Mime::XML\n" + - "xml = ::Builder::XmlMarkup.new(:indent => 2)\n" + + "controller.response.content_type ||= Mime::XML;" + + "xml = ::Builder::XmlMarkup.new(:indent => 2);" + template.source + - "\nxml.target!\n" + ";xml.target!;" end def cache_fragment(block, name = {}, options = nil) diff --git a/actionpack/lib/action_view/template_handlers/compilable.rb b/actionpack/lib/action_view/template_handlers/compilable.rb index d95a5c8419..5278320d1d 100644 --- a/actionpack/lib/action_view/template_handlers/compilable.rb +++ b/actionpack/lib/action_view/template_handlers/compilable.rb @@ -30,11 +30,10 @@ module ActionView render_symbol = assign_method_name(template) render_source = create_template_source(template, render_symbol) - line_offset = self.template_args[render_symbol].size + self.line_offset begin file_name = template.filename || 'compiled-template' - ActionView::Base::CompiledTemplates.module_eval(render_source, file_name, -line_offset) + ActionView::Base::CompiledTemplates.module_eval(render_source, file_name, 0) rescue Exception => e # errors from template code if Base.logger Base.logger.debug "ERROR: compiling #{render_symbol} RAISED #{e}" @@ -50,65 +49,65 @@ module ActionView end private - - # Method to check whether template compilation is necessary. - # The template will be compiled if the inline template or file has not been compiled yet, - # if local_assigns has a new key, which isn't supported by the compiled code yet, - # or if the file has changed on disk and checking file mods hasn't been disabled. - def compile_template?(template) - method_key = template.method_key - render_symbol = @view.method_names[method_key] - - compile_time = self.compile_time[render_symbol] - if compile_time && supports_local_assigns?(render_symbol, template.locals) - if template.filename && !@view.cache_template_loading - template_changed_since?(template.filename, compile_time) + # Method to check whether template compilation is necessary. + # The template will be compiled if the inline template or file has not been compiled yet, + # if local_assigns has a new key, which isn't supported by the compiled code yet, + # or if the file has changed on disk and checking file mods hasn't been disabled. + def compile_template?(template) + method_key = template.method_key + render_symbol = @view.method_names[method_key] + + compile_time = self.compile_time[render_symbol] + if compile_time && supports_local_assigns?(render_symbol, template.locals) + if template.filename && !@view.cache_template_loading + template_changed_since?(template.filename, compile_time) + end + else + true end - else - true end - end - def assign_method_name(template) - @view.method_names[template.method_key] ||= template.method_name - end - - # Method to create the source code for a given template. - def create_template_source(template, render_symbol) - body = compile(template) + def assign_method_name(template) + @view.method_names[template.method_key] ||= template.method_name + end - self.template_args[render_symbol] ||= {} - locals_keys = self.template_args[render_symbol].keys | template.locals.keys - self.template_args[render_symbol] = locals_keys.inject({}) { |h, k| h[k] = true; h } + # Method to create the source code for a given template. + def create_template_source(template, render_symbol) + body = compile(template) - locals_code = "" - locals_keys.each do |key| - locals_code << "#{key} = local_assigns[:#{key}]\n" - end + self.template_args[render_symbol] ||= {} + locals_keys = self.template_args[render_symbol].keys | template.locals.keys + self.template_args[render_symbol] = locals_keys.inject({}) { |h, k| h[k] = true; h } - <<-end_src - def #{render_symbol}(local_assigns) - old_output_buffer = output_buffer;#{locals_code}#{body} - ensure - self.output_buffer = old_output_buffer + locals_code = "" + locals_keys.each do |key| + locals_code << "#{key} = local_assigns[:#{key}];" end - end_src - end - # Return true if the given template was compiled for a superset of the keys in local_assigns - def supports_local_assigns?(render_symbol, local_assigns) - local_assigns.empty? || - ((args = self.template_args[render_symbol]) && local_assigns.all? { |k,_| args.has_key?(k) }) - end + source = <<-end_src + def #{render_symbol}(local_assigns) + old_output_buffer = output_buffer;#{locals_code};#{body} + ensure + self.output_buffer = old_output_buffer + end + end_src - # Method to handle checking a whether a template has changed since last compile; isolated so that templates - # not stored on the file system can hook and extend appropriately. - def template_changed_since?(file_name, compile_time) - lstat = File.lstat(file_name) - compile_time < lstat.mtime || - (lstat.symlink? && compile_time < File.stat(file_name).mtime) - end + return source + end + # Return true if the given template was compiled for a superset of the keys in local_assigns + def supports_local_assigns?(render_symbol, local_assigns) + local_assigns.empty? || + ((args = self.template_args[render_symbol]) && local_assigns.all? { |k,_| args.has_key?(k) }) + end + + # Method to handle checking a whether a template has changed since last compile; isolated so that templates + # not stored on the file system can hook and extend appropriately. + def template_changed_since?(file_name, compile_time) + lstat = File.lstat(file_name) + compile_time < lstat.mtime || + (lstat.symlink? && compile_time < File.stat(file_name).mtime) + end end end end diff --git a/actionpack/lib/action_view/template_handlers/rjs.rb b/actionpack/lib/action_view/template_handlers/rjs.rb index 5854e33fed..31ce598c46 100644 --- a/actionpack/lib/action_view/template_handlers/rjs.rb +++ b/actionpack/lib/action_view/template_handlers/rjs.rb @@ -3,13 +3,9 @@ module ActionView class RJS < TemplateHandler include Compilable - def self.line_offset - 2 - end - def compile(template) - "controller.response.content_type ||= Mime::JS\n" + - "update_page do |page|\n#{template.source}\nend" + "controller.response.content_type ||= Mime::JS;" + + "update_page do |page|;#{template.source};end" end def cache_fragment(block, name = {}, options = nil) #:nodoc: -- cgit v1.2.3 From 5a3bc6f12f7ca78d7ce569f6541d691e42fac6f8 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sat, 5 Jul 2008 17:40:39 -0500 Subject: Removed unused template_args variable --- actionpack/lib/action_view/base.rb | 2 -- 1 file changed, 2 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index d18c701619..4fbe6ac674 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -192,8 +192,6 @@ module ActionView #:nodoc: # Maps inline templates to their method names cattr_accessor :method_names @@method_names = {} - # Map method names to the names passed in local assigns so far - @@template_args = {} # Cache public asset paths cattr_reader :computed_public_paths -- cgit v1.2.3 From f22ae15a8e30f7ad475acdbcfcd1120e498cfede Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sat, 5 Jul 2008 17:49:49 -0500 Subject: Use the inline template's hash as a method key instead of relying on a counter --- actionpack/lib/action_view/inline_template.rb | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/inline_template.rb b/actionpack/lib/action_view/inline_template.rb index fb5e4408db..965df96e3b 100644 --- a/actionpack/lib/action_view/inline_template.rb +++ b/actionpack/lib/action_view/inline_template.rb @@ -2,10 +2,6 @@ module ActionView #:nodoc: class InlineTemplate #:nodoc: include Renderable - # Count the number of inline templates - cattr_accessor :inline_template_count - @@inline_template_count = 0 - def initialize(view, source, locals = {}, type = nil) @view = view @@ -13,14 +9,13 @@ module ActionView #:nodoc: @extension = type @locals = locals || {} - @method_key = @source + @method_key = "inline_#{@source.hash.abs}" @handler = Template.handler_class_for_extension(@extension).new(@view) end private - # FIXME: Modifying this shared variable may not thread safe def method_name_path_segment - "inline_#{@@inline_template_count += 1}" + @method_key end end end -- cgit v1.2.3 From ce5d958f8fe878465c0d2142991a2945ca8d3cd1 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sat, 5 Jul 2008 18:35:52 -0500 Subject: Do not stat template files in production mode before rendering. You will no longer be able to modify templates in production mode without restarting the server --- actionpack/lib/action_view/base.rb | 2 +- .../action_view/template_handlers/compilable.rb | 43 ++++++++-------------- 2 files changed, 16 insertions(+), 29 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 4fbe6ac674..649bd4dd5b 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -165,7 +165,7 @@ module ActionView #:nodoc: delegate :erb_trim_mode=, :to => 'ActionView::TemplateHandlers::ERB' end - # Specify whether file modification times should be checked to see if a template needs recompilation + # Specify whether templates should be cached. Otherwise the file we be read everytime it is accessed. @@cache_template_loading = false cattr_accessor :cache_template_loading diff --git a/actionpack/lib/action_view/template_handlers/compilable.rb b/actionpack/lib/action_view/template_handlers/compilable.rb index 5278320d1d..887c783537 100644 --- a/actionpack/lib/action_view/template_handlers/compilable.rb +++ b/actionpack/lib/action_view/template_handlers/compilable.rb @@ -4,10 +4,6 @@ module ActionView def self.included(base) base.extend ClassMethod - # Map method names to their compile time - base.cattr_accessor :compile_time - base.compile_time = {} - # Map method names to the names passed in local assigns so far base.cattr_accessor :template_args base.template_args = {} @@ -26,7 +22,7 @@ module ActionView # Compile and evaluate the template's code def compile_template(template) - return unless compile_template?(template) + return false unless compile_template?(template) render_symbol = assign_method_name(template) render_source = create_template_source(template, render_symbol) @@ -43,28 +39,27 @@ module ActionView raise ActionView::TemplateError.new(template, @view.assigns, e) end - - self.compile_time[render_symbol] = Time.now - # logger.debug "Compiled template #{file_name || template}\n ==> #{render_symbol}" if logger end private # Method to check whether template compilation is necessary. # The template will be compiled if the inline template or file has not been compiled yet, - # if local_assigns has a new key, which isn't supported by the compiled code yet, - # or if the file has changed on disk and checking file mods hasn't been disabled. + # if local_assigns has a new key, which isn't supported by the compiled code yet. def compile_template?(template) - method_key = template.method_key - render_symbol = @view.method_names[method_key] + # Unless the template has been complied yet, compile + return true unless render_symbol = @view.method_names[template.method_key] - compile_time = self.compile_time[render_symbol] - if compile_time && supports_local_assigns?(render_symbol, template.locals) - if template.filename && !@view.cache_template_loading - template_changed_since?(template.filename, compile_time) - end - else - true - end + # If template caching is disabled, compile + return true unless Base.cache_template_loading + + # Always recompile inline templates + return true if template.is_a?(InlineTemplate) + + # Unless local assigns support, recompile + return true unless supports_local_assigns?(render_symbol, template.locals) + + # Otherwise, use compiled method + return false end def assign_method_name(template) @@ -100,14 +95,6 @@ module ActionView local_assigns.empty? || ((args = self.template_args[render_symbol]) && local_assigns.all? { |k,_| args.has_key?(k) }) end - - # Method to handle checking a whether a template has changed since last compile; isolated so that templates - # not stored on the file system can hook and extend appropriately. - def template_changed_since?(file_name, compile_time) - lstat = File.lstat(file_name) - compile_time < lstat.mtime || - (lstat.symlink? && compile_time < File.stat(file_name).mtime) - end end end end -- cgit v1.2.3 From 9828aecd2aa98910f17e4b0f52519f4727d198d8 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sat, 5 Jul 2008 23:54:11 -0500 Subject: Lookup compiled methods in CompiledTemplates instance methods set instead of using a "methods_names" hash --- actionpack/lib/action_view/base.rb | 4 -- actionpack/lib/action_view/inline_template.rb | 7 +-- actionpack/lib/action_view/renderable.rb | 7 ++- actionpack/lib/action_view/template.rb | 4 +- .../action_view/template_handlers/compilable.rb | 58 +++++++++------------- 5 files changed, 30 insertions(+), 50 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 649bd4dd5b..92501133a6 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -189,10 +189,6 @@ module ActionView #:nodoc: end include CompiledTemplates - # Maps inline templates to their method names - cattr_accessor :method_names - @@method_names = {} - # Cache public asset paths cattr_reader :computed_public_paths @@computed_public_paths = {} diff --git a/actionpack/lib/action_view/inline_template.rb b/actionpack/lib/action_view/inline_template.rb index 965df96e3b..3e25f6902d 100644 --- a/actionpack/lib/action_view/inline_template.rb +++ b/actionpack/lib/action_view/inline_template.rb @@ -9,13 +9,8 @@ module ActionView #:nodoc: @extension = type @locals = locals || {} - @method_key = "inline_#{@source.hash.abs}" + @method_segment = "inline_#{@source.hash.abs}" @handler = Template.handler_class_for_extension(@extension).new(@view) end - - private - def method_name_path_segment - @method_key - end end end diff --git a/actionpack/lib/action_view/renderable.rb b/actionpack/lib/action_view/renderable.rb index d73dc3e2dc..2e2fff44c6 100644 --- a/actionpack/lib/action_view/renderable.rb +++ b/actionpack/lib/action_view/renderable.rb @@ -4,15 +4,15 @@ module ActionView attr_accessor :locals # TODO: These readers should be private - attr_reader :filename, :source, :handler, :method_key, :method + attr_reader :filename, :source, :handler def render prepare! @handler.render(self) end - def method_name - ['_run', @extension, method_name_path_segment].compact.join('_').to_sym + def method + ['_run', @extension, @method_segment].compact.join('_').to_sym end private @@ -23,7 +23,6 @@ module ActionView if @handler.compilable? @handler.compile_template(self) # compile the given template, if necessary - @method = @view.method_names[method_key] # Set the method name for this template and run it end @prepared = true diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 56d740f478..069d7d57af 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -19,7 +19,7 @@ module ActionView #:nodoc: set_extension_and_file_name - @method_key = @filename + @method_segment = compiled_method_name_file_path_segment @locals = locals || {} @handler = self.class.handler_class_for_extension(@extension).new(@view) end @@ -72,7 +72,7 @@ module ActionView #:nodoc: raise MissingTemplate, "Missing #{template_type} #{full_template_path} in view path #{display_paths}" end - def method_name_path_segment + def compiled_method_name_file_path_segment s = File.expand_path(@filename) s.sub!(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}/, '') if defined?(RAILS_ROOT) s.gsub!(/([^a-zA-Z0-9_])/) { $1.ord } diff --git a/actionpack/lib/action_view/template_handlers/compilable.rb b/actionpack/lib/action_view/template_handlers/compilable.rb index 887c783537..ed7b0e71ea 100644 --- a/actionpack/lib/action_view/template_handlers/compilable.rb +++ b/actionpack/lib/action_view/template_handlers/compilable.rb @@ -4,7 +4,7 @@ module ActionView def self.included(base) base.extend ClassMethod - # Map method names to the names passed in local assigns so far + # Map method names to the compiled local assigns base.cattr_accessor :template_args base.template_args = {} end @@ -17,23 +17,34 @@ module ActionView end def render(template) - @view.send :execute, template + @view.send(:execute, template) end # Compile and evaluate the template's code def compile_template(template) return false unless compile_template?(template) - render_symbol = assign_method_name(template) - render_source = create_template_source(template, render_symbol) + locals_code = "" + locals_keys = cache_template_args(template.method, template.locals) + locals_keys.each do |key| + locals_code << "#{key} = local_assigns[:#{key}];" + end + + source = <<-end_src + def #{template.method}(local_assigns) + old_output_buffer = output_buffer;#{locals_code};#{compile(template)} + ensure + self.output_buffer = old_output_buffer + end + end_src begin file_name = template.filename || 'compiled-template' - ActionView::Base::CompiledTemplates.module_eval(render_source, file_name, 0) - rescue Exception => e # errors from template code + ActionView::Base::CompiledTemplates.module_eval(source, file_name, 0) + rescue Exception => e # errors from template code if Base.logger - Base.logger.debug "ERROR: compiling #{render_symbol} RAISED #{e}" - Base.logger.debug "Function body: #{render_source}" + Base.logger.debug "ERROR: compiling #{template.method} RAISED #{e}" + Base.logger.debug "Function body: #{source}" Base.logger.debug "Backtrace: #{e.backtrace.join("\n")}" end @@ -47,7 +58,7 @@ module ActionView # if local_assigns has a new key, which isn't supported by the compiled code yet. def compile_template?(template) # Unless the template has been complied yet, compile - return true unless render_symbol = @view.method_names[template.method_key] + return true unless Base::CompiledTemplates.instance_methods.include?(template.method.to_s) # If template caching is disabled, compile return true unless Base.cache_template_loading @@ -56,38 +67,17 @@ module ActionView return true if template.is_a?(InlineTemplate) # Unless local assigns support, recompile - return true unless supports_local_assigns?(render_symbol, template.locals) + return true unless supports_local_assigns?(template.method, template.locals) # Otherwise, use compiled method return false end - def assign_method_name(template) - @view.method_names[template.method_key] ||= template.method_name - end - - # Method to create the source code for a given template. - def create_template_source(template, render_symbol) - body = compile(template) - + def cache_template_args(render_symbol, local_assigns) self.template_args[render_symbol] ||= {} - locals_keys = self.template_args[render_symbol].keys | template.locals.keys + locals_keys = self.template_args[render_symbol].keys | local_assigns.keys self.template_args[render_symbol] = locals_keys.inject({}) { |h, k| h[k] = true; h } - - locals_code = "" - locals_keys.each do |key| - locals_code << "#{key} = local_assigns[:#{key}];" - end - - source = <<-end_src - def #{render_symbol}(local_assigns) - old_output_buffer = output_buffer;#{locals_code};#{body} - ensure - self.output_buffer = old_output_buffer - end - end_src - - return source + locals_keys end # Return true if the given template was compiled for a superset of the keys in local_assigns -- cgit v1.2.3 From 7b9e8ae2734089555e5bfdb9e9c80d92f43551a2 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 6 Jul 2008 00:00:45 -0500 Subject: Synchronize template compiling --- .../action_view/template_handlers/compilable.rb | 65 +++++++++++----------- 1 file changed, 34 insertions(+), 31 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/template_handlers/compilable.rb b/actionpack/lib/action_view/template_handlers/compilable.rb index ed7b0e71ea..d079ef3d15 100644 --- a/actionpack/lib/action_view/template_handlers/compilable.rb +++ b/actionpack/lib/action_view/template_handlers/compilable.rb @@ -4,9 +4,10 @@ module ActionView def self.included(base) base.extend ClassMethod + @@mutex = Mutex.new + # Map method names to the compiled local assigns - base.cattr_accessor :template_args - base.template_args = {} + @@template_args = {} end module ClassMethod @@ -22,33 +23,35 @@ module ActionView # Compile and evaluate the template's code def compile_template(template) - return false unless compile_template?(template) - - locals_code = "" - locals_keys = cache_template_args(template.method, template.locals) - locals_keys.each do |key| - locals_code << "#{key} = local_assigns[:#{key}];" - end + return false unless recompile_template?(template) - source = <<-end_src - def #{template.method}(local_assigns) - old_output_buffer = output_buffer;#{locals_code};#{compile(template)} - ensure - self.output_buffer = old_output_buffer - end - end_src - - begin - file_name = template.filename || 'compiled-template' - ActionView::Base::CompiledTemplates.module_eval(source, file_name, 0) - rescue Exception => e # errors from template code - if Base.logger - Base.logger.debug "ERROR: compiling #{template.method} RAISED #{e}" - Base.logger.debug "Function body: #{source}" - Base.logger.debug "Backtrace: #{e.backtrace.join("\n")}" + @@mutex.synchronize do + locals_code = "" + locals_keys = cache_template_args(template.method, template.locals) + locals_keys.each do |key| + locals_code << "#{key} = local_assigns[:#{key}];" end - raise ActionView::TemplateError.new(template, @view.assigns, e) + source = <<-end_src + def #{template.method}(local_assigns) + old_output_buffer = output_buffer;#{locals_code};#{compile(template)} + ensure + self.output_buffer = old_output_buffer + end + end_src + + begin + file_name = template.filename || 'compiled-template' + ActionView::Base::CompiledTemplates.module_eval(source, file_name, 0) + rescue Exception => e # errors from template code + if Base.logger + Base.logger.debug "ERROR: compiling #{template.method} RAISED #{e}" + Base.logger.debug "Function body: #{source}" + Base.logger.debug "Backtrace: #{e.backtrace.join("\n")}" + end + + raise ActionView::TemplateError.new(template, @view.assigns, e) + end end end @@ -56,7 +59,7 @@ module ActionView # Method to check whether template compilation is necessary. # The template will be compiled if the inline template or file has not been compiled yet, # if local_assigns has a new key, which isn't supported by the compiled code yet. - def compile_template?(template) + def recompile_template?(template) # Unless the template has been complied yet, compile return true unless Base::CompiledTemplates.instance_methods.include?(template.method.to_s) @@ -74,16 +77,16 @@ module ActionView end def cache_template_args(render_symbol, local_assigns) - self.template_args[render_symbol] ||= {} - locals_keys = self.template_args[render_symbol].keys | local_assigns.keys - self.template_args[render_symbol] = locals_keys.inject({}) { |h, k| h[k] = true; h } + @@template_args[render_symbol] ||= {} + locals_keys = @@template_args[render_symbol].keys | local_assigns.keys + @@template_args[render_symbol] = locals_keys.inject({}) { |h, k| h[k] = true; h } locals_keys end # Return true if the given template was compiled for a superset of the keys in local_assigns def supports_local_assigns?(render_symbol, local_assigns) local_assigns.empty? || - ((args = self.template_args[render_symbol]) && local_assigns.all? { |k,_| args.has_key?(k) }) + ((args = @@template_args[render_symbol]) && local_assigns.all? { |k,_| args.has_key?(k) }) end end end -- cgit v1.2.3 From 1d8623b42f6249613d39e834a8742b3b143f2aff Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 6 Jul 2008 01:13:15 -0500 Subject: Added local assign keys to compiled method name so two threads evaluating the same template with different locals don't step on top of each other --- actionpack/lib/action_view/renderable.rb | 8 ++++++- actionpack/lib/action_view/template.rb | 2 +- .../action_view/template_handlers/compilable.rb | 25 +--------------------- 3 files changed, 9 insertions(+), 26 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/renderable.rb b/actionpack/lib/action_view/renderable.rb index 2e2fff44c6..3a30e603fe 100644 --- a/actionpack/lib/action_view/renderable.rb +++ b/actionpack/lib/action_view/renderable.rb @@ -12,7 +12,7 @@ module ActionView end def method - ['_run', @extension, @method_segment].compact.join('_').to_sym + ['_run', @extension, @method_segment, local_assigns_keys].compact.join('_').to_sym end private @@ -28,5 +28,11 @@ module ActionView @prepared = true end end + + def local_assigns_keys + if @locals && @locals.any? + "locals_#{@locals.keys.map { |k| k.to_s }.sort.join('_')}" + end + end end end diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 069d7d57af..5e5ea9b9b9 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -20,7 +20,7 @@ module ActionView #:nodoc: set_extension_and_file_name @method_segment = compiled_method_name_file_path_segment - @locals = locals || {} + @locals = (locals && locals.dup) || {} @handler = self.class.handler_class_for_extension(@extension).new(@view) end diff --git a/actionpack/lib/action_view/template_handlers/compilable.rb b/actionpack/lib/action_view/template_handlers/compilable.rb index d079ef3d15..256d8da031 100644 --- a/actionpack/lib/action_view/template_handlers/compilable.rb +++ b/actionpack/lib/action_view/template_handlers/compilable.rb @@ -5,9 +5,6 @@ module ActionView base.extend ClassMethod @@mutex = Mutex.new - - # Map method names to the compiled local assigns - @@template_args = {} end module ClassMethod @@ -26,11 +23,7 @@ module ActionView return false unless recompile_template?(template) @@mutex.synchronize do - locals_code = "" - locals_keys = cache_template_args(template.method, template.locals) - locals_keys.each do |key| - locals_code << "#{key} = local_assigns[:#{key}];" - end + locals_code = template.locals.keys.map { |key| "#{key} = local_assigns[:#{key}];" }.join source = <<-end_src def #{template.method}(local_assigns) @@ -69,25 +62,9 @@ module ActionView # Always recompile inline templates return true if template.is_a?(InlineTemplate) - # Unless local assigns support, recompile - return true unless supports_local_assigns?(template.method, template.locals) - # Otherwise, use compiled method return false end - - def cache_template_args(render_symbol, local_assigns) - @@template_args[render_symbol] ||= {} - locals_keys = @@template_args[render_symbol].keys | local_assigns.keys - @@template_args[render_symbol] = locals_keys.inject({}) { |h, k| h[k] = true; h } - locals_keys - end - - # Return true if the given template was compiled for a superset of the keys in local_assigns - def supports_local_assigns?(render_symbol, local_assigns) - local_assigns.empty? || - ((args = @@template_args[render_symbol]) && local_assigns.all? { |k,_| args.has_key?(k) }) - end end end end -- cgit v1.2.3 From 2f4aaed7b3feb3be787a316fab3144c06bb21a27 Mon Sep 17 00:00:00 2001 From: Michael Koziarski Date: Fri, 27 Jun 2008 11:29:04 +0300 Subject: Disable the Accept header by default The accept header is poorly implemented by browsers and causes strange errors when used on public sites where crawlers make requests too. You should use formatted urls (e.g. /people/1.xml) to support API clients. Alternatively to re-enable it you need to set: config.action_controller.use_accept_header = true A special case remains for ajax requests which will have a javascript format for the base resource (/people/1) if the X-Requested-With header is present. This lets ajax pages still use format.js despite there being no params[:format] --- actionpack/lib/action_controller/base.rb | 10 +++++++ .../lib/action_controller/caching/actions.rb | 5 +--- actionpack/lib/action_controller/mime_responds.rb | 6 +++- actionpack/lib/action_controller/request.rb | 34 ++++++++++++++++------ actionpack/lib/action_view/base.rb | 10 ++----- 5 files changed, 44 insertions(+), 21 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 58eb5cabcd..c28e9005cf 100755 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -340,6 +340,16 @@ module ActionController #:nodoc: cattr_accessor :optimise_named_routes self.optimise_named_routes = true + # Indicates whether the response format should be determined by examining the Accept HTTP header, + # or by using the simpler params + ajax rules. + # + # If this is set to +true+ then +respond_to+ and +Request#format+ will take the Accept header into + # account. If it is set to false (the default) then the request format will be determined solely + # by examining params[:format]. If params format is missing, the format will be either HTML or + # Javascript depending on whether the request is an AJAX request. + cattr_accessor :use_accept_header + self.use_accept_header = false + # Controls whether request forgergy protection is turned on or not. Turned off by default only in test mode. class_inheritable_accessor :allow_forgery_protection self.allow_forgery_protection = true diff --git a/actionpack/lib/action_controller/caching/actions.rb b/actionpack/lib/action_controller/caching/actions.rb index 234ef8ae5b..f3535f8330 100644 --- a/actionpack/lib/action_controller/caching/actions.rb +++ b/actionpack/lib/action_controller/caching/actions.rb @@ -166,10 +166,7 @@ module ActionController #:nodoc: # If there's no extension in the path, check request.format if extension.nil? - extension = request.format.to_sym.to_s - if extension=='all' - extension = nil - end + extension = request.cache_format end extension end diff --git a/actionpack/lib/action_controller/mime_responds.rb b/actionpack/lib/action_controller/mime_responds.rb index 1dbd8b9e6f..29294476f7 100644 --- a/actionpack/lib/action_controller/mime_responds.rb +++ b/actionpack/lib/action_controller/mime_responds.rb @@ -114,7 +114,11 @@ module ActionController #:nodoc: @request = controller.request @response = controller.response - @mime_type_priority = Array(Mime::Type.lookup_by_extension(@request.parameters[:format]) || @request.accepts) + if ActionController::Base.use_accept_header + @mime_type_priority = Array(Mime::Type.lookup_by_extension(@request.parameters[:format]) || @request.accepts) + else + @mime_type_priority = [@request.format] + end @order = [] @responses = {} diff --git a/actionpack/lib/action_controller/request.rb b/actionpack/lib/action_controller/request.rb index c91a3387a0..c76a93f7a1 100755 --- a/actionpack/lib/action_controller/request.rb +++ b/actionpack/lib/action_controller/request.rb @@ -89,14 +89,23 @@ module ActionController end end - # Returns the Mime type for the format used in the request. If there is no format available, the first of the - # accept types will be used. Examples: + # Returns the Mime type for the format used in the request. # # GET /posts/5.xml | request.format => Mime::XML # GET /posts/5.xhtml | request.format => Mime::HTML - # GET /posts/5 | request.format => request.accepts.first (usually Mime::HTML for browsers) + # GET /posts/5 | request.format => Mime::HTML or MIME::JS, or request.accepts.first depending on the value of ActionController::Base.use_accept_header def format - @format ||= parameters[:format] ? Mime::Type.lookup_by_extension(parameters[:format]) : accepts.first + @format ||= begin + if parameters[:format] + Mime::Type.lookup_by_extension(parameters[:format]) + elsif ActionController::Base.use_accept_header + accepts.first + elsif xhr? + Mime::Type.lookup_by_extension("js") + else + Mime::Type.lookup_by_extension("html") + end + end end @@ -116,19 +125,26 @@ module ActionController @format = Mime::Type.lookup_by_extension(parameters[:format]) end + # Returns a symbolized version of the :format parameter of the request. + # If no format is given it returns :jsfor AJAX requests and :html + # otherwise. def template_format parameter_format = parameters[:format] - case - when parameter_format.blank? && !xhr? - :html - when parameter_format.blank? && xhr? + if parameter_format + parameter_format.to_sym + elsif xhr? :js else - parameter_format.to_sym + :html end end + def cache_format + parameter_format = parameters[:format] + parameter_format && parameter_format.to_sym + end + # Returns true if the request's "X-Requested-With" header contains # "XMLHttpRequest". (The Prototype Javascript library sends this header with # every Ajax request.) diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 92501133a6..66892fdabf 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -256,13 +256,9 @@ module ActionView #:nodoc: template_path.split('/').last[0,1] != '_' end - # Returns a symbolized version of the :format parameter of the request, - # or :html by default. - # - # EXCEPTION: If the :format parameter is not set, the Accept header will be examined for - # whether it contains the JavaScript mime type as its first priority. If that's the case, - # it will be used. This ensures that Ajax applications can use the same URL to support both - # JavaScript and non-JavaScript users. + # The format to be used when choosing between multiple templates with + # the same name but differing formats. See +Request#template_format+ + # for more details. def template_format return @template_format if @template_format -- cgit v1.2.3 From 91320f2a809d3a59efabd9f839fe9b879f4a9b29 Mon Sep 17 00:00:00 2001 From: Damian Janowski Date: Fri, 4 Jul 2008 17:12:30 -0300 Subject: Add :recursive option to javascript_include_tag and stylesheet_link_tag to be used along with :all. [#480 state:resolved] Signed-off-by: Pratik Naik --- .../lib/action_view/helpers/asset_tag_helper.rb | 56 ++++++++++++++++------ 1 file changed, 42 insertions(+), 14 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb index 0122de47af..bf13945844 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb @@ -209,6 +209,10 @@ module ActionView # Note that the default javascript files will be included first. So Prototype and Scriptaculous are available to # all subsequently included files. # + # If you want Rails to search in all the subdirectories under javascripts, you should explicitly set :recursive: + # + # javascript_include_tag :all, :recursive => true + # # == Caching multiple javascripts into one # # You can also cache multiple javascripts into one file, which requires less HTTP connections to download and can better be @@ -235,18 +239,23 @@ module ActionView # # javascript_include_tag "prototype", "cart", "checkout", :cache => "shop" # when ActionController::Base.perform_caching is true => # + # + # The :recursive option is also available for caching: + # + # javascript_include_tag :all, :cache => true, :recursive => true def javascript_include_tag(*sources) options = sources.extract_options!.stringify_keys cache = options.delete("cache") + recursive = options.delete("recursive") if ActionController::Base.perform_caching && cache joined_javascript_name = (cache == true ? "all" : cache) + ".js" joined_javascript_path = File.join(JAVASCRIPTS_DIR, joined_javascript_name) - write_asset_file_contents(joined_javascript_path, compute_javascript_paths(sources)) unless File.exists?(joined_javascript_path) + write_asset_file_contents(joined_javascript_path, compute_javascript_paths(sources, recursive)) unless File.exists?(joined_javascript_path) javascript_src_tag(joined_javascript_name, options) else - expand_javascript_sources(sources).collect { |source| javascript_src_tag(source, options) }.join("\n") + expand_javascript_sources(sources, recursive).collect { |source| javascript_src_tag(source, options) }.join("\n") end end @@ -332,13 +341,17 @@ module ActionView # # # - # You can also include all styles in the stylesheet directory using :all as the source: + # You can also include all styles in the stylesheets directory using :all as the source: # # stylesheet_link_tag :all # => # # # # + # If you want Rails to search in all the subdirectories under stylesheets, you should explicitly set :recursive: + # + # stylesheet_link_tag :all, :recursive => true + # # == Caching multiple stylesheets into one # # You can also cache multiple stylesheets into one file, which requires less HTTP connections and can better be @@ -362,18 +375,23 @@ module ActionView # # stylesheet_link_tag "shop", "cart", "checkout", :cache => "payment" # when ActionController::Base.perform_caching is true => # + # + # The :recursive option is also available for caching: + # + # stylesheet_link_tag :all, :cache => true, :recursive => true def stylesheet_link_tag(*sources) options = sources.extract_options!.stringify_keys cache = options.delete("cache") + recursive = options.delete("recursive") if ActionController::Base.perform_caching && cache joined_stylesheet_name = (cache == true ? "all" : cache) + ".css" joined_stylesheet_path = File.join(STYLESHEETS_DIR, joined_stylesheet_name) - write_asset_file_contents(joined_stylesheet_path, compute_stylesheet_paths(sources)) unless File.exists?(joined_stylesheet_path) + write_asset_file_contents(joined_stylesheet_path, compute_stylesheet_paths(sources, recursive)) unless File.exists?(joined_stylesheet_path) stylesheet_tag(joined_stylesheet_name, options) else - expand_stylesheet_sources(sources).collect { |source| stylesheet_tag(source, options) }.join("\n") + expand_stylesheet_sources(sources, recursive).collect { |source| stylesheet_tag(source, options) }.join("\n") end end @@ -556,18 +574,19 @@ module ActionView tag("link", { "rel" => "stylesheet", "type" => Mime::CSS, "media" => "screen", "href" => html_escape(path_to_stylesheet(source)) }.merge(options), false, false) end - def compute_javascript_paths(sources) - expand_javascript_sources(sources).collect { |source| compute_public_path(source, 'javascripts', 'js', false) } + def compute_javascript_paths(*args) + expand_javascript_sources(*args).collect { |source| compute_public_path(source, 'javascripts', 'js', false) } end - def compute_stylesheet_paths(sources) - expand_stylesheet_sources(sources).collect { |source| compute_public_path(source, 'stylesheets', 'css', false) } + def compute_stylesheet_paths(*args) + expand_stylesheet_sources(*args).collect { |source| compute_public_path(source, 'stylesheets', 'css', false) } end - def expand_javascript_sources(sources) + def expand_javascript_sources(sources, recursive = false) if sources.include?(:all) - all_javascript_files = Dir[File.join(JAVASCRIPTS_DIR, '*.js')].collect { |file| File.basename(file).gsub(/\.\w+$/, '') }.sort - @@all_javascript_sources ||= ((determine_source(:defaults, @@javascript_expansions).dup & all_javascript_files) + all_javascript_files).uniq + all_javascript_files = collect_asset_files(JAVASCRIPTS_DIR, ('**' if recursive), '*.js') + @@all_javascript_sources ||= {} + @@all_javascript_sources[recursive] ||= ((determine_source(:defaults, @@javascript_expansions).dup & all_javascript_files) + all_javascript_files).uniq else expanded_sources = sources.collect do |source| determine_source(source, @@javascript_expansions) @@ -577,9 +596,10 @@ module ActionView end end - def expand_stylesheet_sources(sources) + def expand_stylesheet_sources(sources, recursive) if sources.first == :all - @@all_stylesheet_sources ||= Dir[File.join(STYLESHEETS_DIR, '*.css')].collect { |file| File.basename(file).gsub(/\.\w+$/, '') }.sort + @@all_stylesheet_sources ||= {} + @@all_stylesheet_sources[recursive] ||= collect_asset_files(STYLESHEETS_DIR, ('**' if recursive), '*.css') else sources.collect do |source| determine_source(source, @@stylesheet_expansions) @@ -604,6 +624,14 @@ module ActionView FileUtils.mkdir_p(File.dirname(joined_asset_path)) File.open(joined_asset_path, "w+") { |cache| cache.write(join_asset_file_contents(asset_paths)) } end + + def collect_asset_files(*path) + dir = path.first + + Dir[File.join(*path.compact)].collect do |file| + file[-(file.size - dir.size - 1)..-1].sub(/\.\w+$/, '') + end.sort + end end end end -- cgit v1.2.3 From 96708af6a58a48c2324a3bf8d34232bc29b398c9 Mon Sep 17 00:00:00 2001 From: Cheah Chu Yeow Date: Mon, 23 Jun 2008 20:51:38 +0800 Subject: Ensure url_for(nil) falls back to url_for({}). [#472 state:resolved] Signed-off-by: Pratik Naik --- actionpack/lib/action_controller/base.rb | 3 ++- actionpack/lib/action_view/helpers/url_helper.rb | 6 ++---- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index c28e9005cf..f6d5491100 100755 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -613,7 +613,8 @@ module ActionController #:nodoc: # # This takes the current URL as is and only exchanges the action. In contrast, url_for :action => 'print' # would have slashed-off the path components after the changed action. - def url_for(options = {}) #:doc: + def url_for(options = {}) + options ||= {} case options when String options diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb index d5b7255642..f6a1f271f0 100644 --- a/actionpack/lib/action_view/helpers/url_helper.rb +++ b/actionpack/lib/action_view/helpers/url_helper.rb @@ -63,17 +63,15 @@ module ActionView # # calls @workshop.to_s # # => /workshops/5 def url_for(options = {}) + options ||= {} case options when Hash - show_path = options[:host].nil? ? true : false - options = { :only_path => show_path }.update(options.symbolize_keys) + options = { :only_path => options[:host].nil? }.update(options.symbolize_keys) escape = options.key?(:escape) ? options.delete(:escape) : true url = @controller.send(:url_for, options) when String escape = true url = options - when NilClass - url = @controller.send(:url_for, nil) else escape = false url = polymorphic_path(options) -- cgit v1.2.3 From 6b61e95dc8d717b4500ab623816863c0bb707e2b Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Wed, 9 Jul 2008 09:13:24 -0500 Subject: Changed PrototypeHelper#submit_to_remote to PrototypeHelper#button_to_remote to stay consistent with link_to_remote (submit_to_remote still works as an alias) (clemens) [#8994 status:closed] --- actionpack/lib/action_view/helpers/prototype_helper.rb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb index a7c3b9ddc3..d0c281c803 100644 --- a/actionpack/lib/action_view/helpers/prototype_helper.rb +++ b/actionpack/lib/action_view/helpers/prototype_helper.rb @@ -397,7 +397,7 @@ module ActionView # # Generates: - # <%= submit_to_remote 'create_btn', 'Create', :url => { :action => 'create' } %> + # <%= button_to_remote 'create_btn', 'Create', :url => { :action => 'create' } %> # # # Submit to the remote action update and update the DIV succeed or fail based # # on the success or failure of the request @@ -405,11 +405,13 @@ module ActionView # # Generates: - # <%= submit_to_remote 'update_btn', 'Update', :url => { :action => 'update' }, + # <%= button_to_remote 'update_btn', 'Update', :url => { :action => 'update' }, # :update => { :success => "succeed", :failure => "fail" } # # options argument is the same as in form_remote_tag. - def submit_to_remote(name, value, options = {}) + # + # Note: This method used to be called submit_to_remote, but that's now just an alias for button_to_remote + def button_to_remote(name, value, options = {}) options[:with] ||= 'Form.serialize(this.form)' options[:html] ||= {} @@ -420,6 +422,7 @@ module ActionView tag("input", options[:html], false) end + alias_method :submit_to_remote, :button_to_remote # Returns 'eval(request.responseText)' which is the JavaScript function # that +form_remote_tag+ can call in :complete to evaluate a multiple -- cgit v1.2.3 From 4ce9931f4f30045b2975328e7d42a02188e35079 Mon Sep 17 00:00:00 2001 From: Michael Koziarski Date: Wed, 9 Jul 2008 18:35:35 +0200 Subject: Reenable the use of the Accept header to give people a chance to update their applications and provide feedback. --- actionpack/lib/action_controller/base.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index f6d5491100..dd50f17c1c 100755 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -343,12 +343,12 @@ module ActionController #:nodoc: # Indicates whether the response format should be determined by examining the Accept HTTP header, # or by using the simpler params + ajax rules. # - # If this is set to +true+ then +respond_to+ and +Request#format+ will take the Accept header into - # account. If it is set to false (the default) then the request format will be determined solely + # If this is set to +true+ (the default) then +respond_to+ and +Request#format+ will take the Accept + # header into account. If it is set to false then the request format will be determined solely # by examining params[:format]. If params format is missing, the format will be either HTML or # Javascript depending on whether the request is an AJAX request. cattr_accessor :use_accept_header - self.use_accept_header = false + self.use_accept_header = true # Controls whether request forgergy protection is turned on or not. Turned off by default only in test mode. class_inheritable_accessor :allow_forgery_protection -- cgit v1.2.3 From 350faf14e80740a440ab16c7130c5262d603d283 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Mon, 7 Jul 2008 11:02:15 -0700 Subject: Pass caller to concat deprecation warning --- actionpack/lib/action_view/helpers/text_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index a6c48737e9..3e3452b615 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -27,7 +27,7 @@ module ActionView # %> def concat(string, unused_binding = nil) if unused_binding - ActiveSupport::Deprecation.warn("The binding argument of #concat is no longer needed. Please remove it from your views and helpers.") + ActiveSupport::Deprecation.warn("The binding argument of #concat is no longer needed. Please remove it from your views and helpers.", caller) end output_buffer << string -- cgit v1.2.3 From 4354aa36fb0b94f3750256441054d42db9900bf5 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Mon, 7 Jul 2008 11:57:53 -0700 Subject: Rendering default template for missing actions works with non-word characters in action name --- actionpack/lib/action_view/template_file.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/template_file.rb b/actionpack/lib/action_view/template_file.rb index c38e8ed122..0aa16b5e70 100644 --- a/actionpack/lib/action_view/template_file.rb +++ b/actionpack/lib/action_view/template_file.rb @@ -74,7 +74,7 @@ module ActionView #:nodoc: # Returns file split into an array # [base_path, name, format, extension] def split(file) - if m = file.match(/^(.*\/)?(\w+)\.?(\w+)?\.?(\w+)?\.?(\w+)?$/) + if m = file.match(/^(.*\/)?([^\.]+)\.?(\w+)?\.?(\w+)?\.?(\w+)?$/) if m[5] # Mulipart formats [m[1], m[2], "#{m[3]}.#{m[4]}", m[5]] elsif m[4] # Single format -- cgit v1.2.3 From 7dc10478e53ca4f36951c85aab4885e5de6e11cb Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Mon, 7 Jul 2008 12:42:51 -0700 Subject: Use ActionController::Base.logger to report template compilation errors since there is no AV::Base.logger --- actionpack/lib/action_view/template_handlers/compilable.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/template_handlers/compilable.rb b/actionpack/lib/action_view/template_handlers/compilable.rb index 256d8da031..9b9255579c 100644 --- a/actionpack/lib/action_view/template_handlers/compilable.rb +++ b/actionpack/lib/action_view/template_handlers/compilable.rb @@ -37,10 +37,10 @@ module ActionView file_name = template.filename || 'compiled-template' ActionView::Base::CompiledTemplates.module_eval(source, file_name, 0) rescue Exception => e # errors from template code - if Base.logger - Base.logger.debug "ERROR: compiling #{template.method} RAISED #{e}" - Base.logger.debug "Function body: #{source}" - Base.logger.debug "Backtrace: #{e.backtrace.join("\n")}" + if logger = ActionController::Base.logger + logger.debug "ERROR: compiling #{template.method} RAISED #{e}" + logger.debug "Function body: #{source}" + logger.debug "Backtrace: #{e.backtrace.join("\n")}" end raise ActionView::TemplateError.new(template, @view.assigns, e) -- cgit v1.2.3 From ee6bbcb6ae4488a6ab556236dfa1cf7358378dcd Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Mon, 7 Jul 2008 12:43:43 -0700 Subject: Put a newline rather than a semicolon at the end of RJS source to avoid parse errors with embedded heredocs --- actionpack/lib/action_view/template_handlers/rjs.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/template_handlers/rjs.rb b/actionpack/lib/action_view/template_handlers/rjs.rb index 31ce598c46..3892bf1d6e 100644 --- a/actionpack/lib/action_view/template_handlers/rjs.rb +++ b/actionpack/lib/action_view/template_handlers/rjs.rb @@ -5,7 +5,7 @@ module ActionView def compile(template) "controller.response.content_type ||= Mime::JS;" + - "update_page do |page|;#{template.source};end" + "update_page do |page|;#{template.source}\nend" end def cache_fragment(block, name = {}, options = nil) #:nodoc: -- cgit v1.2.3 From f82bd31cb013cfba5bf3f5cad7356070fcefcc22 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Tue, 8 Jul 2008 12:35:03 -0700 Subject: Request#accepts special-cases a single mime type --- actionpack/lib/action_controller/request.rb | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/request.rb b/actionpack/lib/action_controller/request.rb index c76a93f7a1..7791e0696e 100755 --- a/actionpack/lib/action_controller/request.rb +++ b/actionpack/lib/action_controller/request.rb @@ -82,10 +82,16 @@ module ActionController # Returns the accepted MIME type for the request def accepts @accepts ||= - if @env['HTTP_ACCEPT'].to_s.strip.empty? - [ content_type, Mime::ALL ].compact # make sure content_type being nil is not included - else - Mime::Type.parse(@env['HTTP_ACCEPT']) + begin + header = @env['HTTP_ACCEPT'].to_s.strip + + if header.empty? + [content_type, Mime::ALL].compact + elsif header !~ /,/ + [Mime::Type.lookup(header)].compact + else + Mime::Type.parse(header) + end end end -- cgit v1.2.3 From ce4a1bb8538bd7cc5ee3cbf1156dc587482a7839 Mon Sep 17 00:00:00 2001 From: Cheah Chu Yeow Date: Thu, 26 Jun 2008 10:21:53 +0800 Subject: Remove some Symbol#to_proc usage in runtime code. [#484 state:resolved] --- actionpack/lib/action_controller/base.rb | 12 ++++++------ actionpack/lib/action_controller/filters.rb | 16 ++++++++++++---- 2 files changed, 18 insertions(+), 10 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index dd50f17c1c..9d9ff527c2 100755 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -412,7 +412,7 @@ module ActionController #:nodoc: # More methods can be hidden using hide_actions. def hidden_actions unless read_inheritable_attribute(:hidden_actions) - write_inheritable_attribute(:hidden_actions, ActionController::Base.public_instance_methods.map(&:to_s)) + write_inheritable_attribute(:hidden_actions, ActionController::Base.public_instance_methods.map { |m| m.to_s }) end read_inheritable_attribute(:hidden_actions) @@ -420,12 +420,12 @@ module ActionController #:nodoc: # Hide each of the given methods from being callable as actions. def hide_action(*names) - write_inheritable_attribute(:hidden_actions, hidden_actions | names.map(&:to_s)) + write_inheritable_attribute(:hidden_actions, hidden_actions | names.map { |name| name.to_s }) end - ## View load paths determine the bases from which template references can be made. So a call to - ## render("test/template") will be looked up in the view load paths array and the closest match will be - ## returned. + # View load paths determine the bases from which template references can be made. So a call to + # render("test/template") will be looked up in the view load paths array and the closest match will be + # returned. def view_paths @view_paths || superclass.view_paths end @@ -1201,7 +1201,7 @@ module ActionController #:nodoc: end def self.action_methods - @action_methods ||= Set.new(public_instance_methods.map(&:to_s)) - hidden_actions + @action_methods ||= Set.new(public_instance_methods.map { |m| m.to_s }) - hidden_actions end def add_variables_to_assigns diff --git a/actionpack/lib/action_controller/filters.rb b/actionpack/lib/action_controller/filters.rb index 155d8b480a..c3f1de971e 100644 --- a/actionpack/lib/action_controller/filters.rb +++ b/actionpack/lib/action_controller/filters.rb @@ -127,9 +127,9 @@ module ActionController #:nodoc: def included_in_action?(controller, options) if options[:only] - Array(options[:only]).map(&:to_s).include?(controller.action_name) + Array(options[:only]).map { |o| o.to_s }.include?(controller.action_name) elsif options[:except] - !Array(options[:except]).map(&:to_s).include?(controller.action_name) + !Array(options[:except]).map { |o| o.to_s }.include?(controller.action_name) else true end @@ -544,13 +544,21 @@ module ActionController #:nodoc: # Returns all the before filters for this class and all its ancestors. # This method returns the actual filter that was assigned in the controller to maintain existing functionality. def before_filters #:nodoc: - filter_chain.select(&:before?).map(&:method) + filters = [] + filter_chain.each do |filter| + filters << filter.method if filter.before? + end + filters end # Returns all the after filters for this class and all its ancestors. # This method returns the actual filter that was assigned in the controller to maintain existing functionality. def after_filters #:nodoc: - filter_chain.select(&:after?).map(&:method) + filters = [] + filter_chain.each do |filter| + filters << filter.method if filter.after? + end + filters end end -- cgit v1.2.3 From 0ce7fe5308337ae0b0394ae4c18b59cf64e33b38 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Tue, 8 Jul 2008 23:38:18 -0700 Subject: Don't repeatedly convert only/except options --- actionpack/lib/action_controller/filters.rb | 31 ++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/filters.rb b/actionpack/lib/action_controller/filters.rb index c3f1de971e..fc63890d13 100644 --- a/actionpack/lib/action_controller/filters.rb +++ b/actionpack/lib/action_controller/filters.rb @@ -94,7 +94,7 @@ module ActionController #:nodoc: map! do |filter| if filters.include?(filter) new_filter = filter.dup - new_filter.options.merge!(options) + new_filter.update_options!(options) new_filter else filter @@ -104,6 +104,11 @@ module ActionController #:nodoc: end class Filter < ActiveSupport::Callbacks::Callback #:nodoc: + def initialize(kind, method, options = {}) + super + update_options! options + end + def before? self.class == BeforeFilter end @@ -116,6 +121,18 @@ module ActionController #:nodoc: self.class == AroundFilter end + # Make sets of strings from :only/:except options + def update_options!(other) + if other + convert_only_and_except_options_to_sets_of_strings(other) + if other[:skip] + convert_only_and_except_options_to_sets_of_strings(other[:skip]) + end + end + + options.update(other) + end + private def should_not_skip?(controller) if options[:skip] @@ -127,9 +144,9 @@ module ActionController #:nodoc: def included_in_action?(controller, options) if options[:only] - Array(options[:only]).map { |o| o.to_s }.include?(controller.action_name) + options[:only].include?(controller.action_name) elsif options[:except] - !Array(options[:except]).map { |o| o.to_s }.include?(controller.action_name) + !options[:except].include?(controller.action_name) else true end @@ -138,6 +155,14 @@ module ActionController #:nodoc: def should_run_callback?(controller) should_not_skip?(controller) && included_in_action?(controller, options) && super end + + def convert_only_and_except_options_to_sets_of_strings(opts) + [:only, :except].each do |key| + if values = opts[key] + opts[key] = Array(values).map(&:to_s).to_set + end + end + end end class AroundFilter < Filter #:nodoc: -- cgit v1.2.3 From d37e6413366c9a3fafa02c4298a2946dc8327a42 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Wed, 9 Jul 2008 11:30:18 -0700 Subject: Move accept header parsing shortcut to Mime::Type.parse --- actionpack/lib/action_controller/mime_type.rb | 82 ++++++++++++++------------- actionpack/lib/action_controller/request.rb | 2 - 2 files changed, 43 insertions(+), 41 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/mime_type.rb b/actionpack/lib/action_controller/mime_type.rb index fa123f7808..a7215e6ea3 100644 --- a/actionpack/lib/action_controller/mime_type.rb +++ b/actionpack/lib/action_controller/mime_type.rb @@ -72,57 +72,61 @@ module Mime end def parse(accept_header) - # keep track of creation order to keep the subsequent sort stable - list = [] - accept_header.split(/,/).each_with_index do |header, index| - params, q = header.split(/;\s*q=/) - if params - params.strip! - list << AcceptItem.new(index, params, q) unless params.empty? + if accept_header !~ /,/ + [Mime::Type.lookup(accept_header)] + else + # keep track of creation order to keep the subsequent sort stable + list = [] + accept_header.split(/,/).each_with_index do |header, index| + params, q = header.split(/;\s*q=/) + if params + params.strip! + list << AcceptItem.new(index, params, q) unless params.empty? + end end - end - list.sort! + list.sort! - # Take care of the broken text/xml entry by renaming or deleting it - text_xml = list.index("text/xml") - app_xml = list.index(Mime::XML.to_s) + # Take care of the broken text/xml entry by renaming or deleting it + text_xml = list.index("text/xml") + app_xml = list.index(Mime::XML.to_s) - if text_xml && app_xml - # set the q value to the max of the two - list[app_xml].q = [list[text_xml].q, list[app_xml].q].max + if text_xml && app_xml + # set the q value to the max of the two + list[app_xml].q = [list[text_xml].q, list[app_xml].q].max - # make sure app_xml is ahead of text_xml in the list - if app_xml > text_xml - list[app_xml], list[text_xml] = list[text_xml], list[app_xml] - app_xml, text_xml = text_xml, app_xml - end + # make sure app_xml is ahead of text_xml in the list + if app_xml > text_xml + list[app_xml], list[text_xml] = list[text_xml], list[app_xml] + app_xml, text_xml = text_xml, app_xml + end - # delete text_xml from the list - list.delete_at(text_xml) + # delete text_xml from the list + list.delete_at(text_xml) - elsif text_xml - list[text_xml].name = Mime::XML.to_s - end + elsif text_xml + list[text_xml].name = Mime::XML.to_s + end - # Look for more specific XML-based types and sort them ahead of app/xml + # Look for more specific XML-based types and sort them ahead of app/xml - if app_xml - idx = app_xml - app_xml_type = list[app_xml] + if app_xml + idx = app_xml + app_xml_type = list[app_xml] - while(idx < list.length) - type = list[idx] - break if type.q < app_xml_type.q - if type.name =~ /\+xml$/ - list[app_xml], list[idx] = list[idx], list[app_xml] - app_xml = idx + while(idx < list.length) + type = list[idx] + break if type.q < app_xml_type.q + if type.name =~ /\+xml$/ + list[app_xml], list[idx] = list[idx], list[app_xml] + app_xml = idx + end + idx += 1 end - idx += 1 end - end - list.map! { |i| Mime::Type.lookup(i.name) }.uniq! - list + list.map! { |i| Mime::Type.lookup(i.name) }.uniq! + list + end end end diff --git a/actionpack/lib/action_controller/request.rb b/actionpack/lib/action_controller/request.rb index 7791e0696e..2d9f6c3e6f 100755 --- a/actionpack/lib/action_controller/request.rb +++ b/actionpack/lib/action_controller/request.rb @@ -87,8 +87,6 @@ module ActionController if header.empty? [content_type, Mime::ALL].compact - elsif header !~ /,/ - [Mime::Type.lookup(header)].compact else Mime::Type.parse(header) end -- cgit v1.2.3 From feb08984ea5517db5780a88584929feac1cafb59 Mon Sep 17 00:00:00 2001 From: Clemens Kofler Date: Wed, 9 Jul 2008 21:41:03 +0200 Subject: Added notes to Routing documentation and routes.rb regarding defaults routes opening the whole application for GET requests Signed-off-by: Michael Koziarski --- actionpack/lib/action_controller/routing.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/routing.rb b/actionpack/lib/action_controller/routing.rb index 8846dcc504..dfbaa53b7c 100644 --- a/actionpack/lib/action_controller/routing.rb +++ b/actionpack/lib/action_controller/routing.rb @@ -88,6 +88,10 @@ module ActionController # # map.connect ':controller/:action/:id', :action => 'show', :defaults => { :page => 'Dashboard' } # + # Note: The default routes, as provided by the Rails generator, make all actions in every + # controller accessible via GET requests. You should consider removing them or commenting + # them out if you're using named routes and resources. + # # == Named routes # # Routes can be named with the syntax map.name_of_route options, -- cgit v1.2.3 From 68289693f723f7a11ab13014a784d0a95abfd6ed Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Fri, 11 Jul 2008 11:14:59 -0500 Subject: Check for response in builder template since ActionMailer does not have one --- actionpack/lib/action_view/template_handlers/builder.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/template_handlers/builder.rb b/actionpack/lib/action_view/template_handlers/builder.rb index 2d413490bd..cbe53e11d8 100644 --- a/actionpack/lib/action_view/template_handlers/builder.rb +++ b/actionpack/lib/action_view/template_handlers/builder.rb @@ -6,7 +6,8 @@ module ActionView include Compilable def compile(template) - "controller.response.content_type ||= Mime::XML;" + + # ActionMailer does not have a response + "controller.respond_to?(:response) && controller.response.content_type ||= Mime::XML;" + "xml = ::Builder::XmlMarkup.new(:indent => 2);" + template.source + ";xml.target!;" -- cgit v1.2.3 From 6b9f8adb3eff3be81653bd565be4ff9c63cd775d Mon Sep 17 00:00:00 2001 From: Michael Koziarski Date: Fri, 11 Jul 2008 19:22:43 +0200 Subject: Whitespace --- actionpack/lib/action_view/helpers/capture_helper.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/capture_helper.rb b/actionpack/lib/action_view/helpers/capture_helper.rb index 990c30b90d..720e2da8cc 100644 --- a/actionpack/lib/action_view/helpers/capture_helper.rb +++ b/actionpack/lib/action_view/helpers/capture_helper.rb @@ -34,9 +34,8 @@ module ActionView # Return captured buffer in erb. if block_called_from_erb?(block) with_output_buffer { block.call(*args) } - - # Return block result otherwise, but protect buffer also. else + # Return block result otherwise, but protect buffer also. with_output_buffer { return block.call(*args) } end end -- cgit v1.2.3 From 6ebdd0e32b846e99a9885b06fbca2bed58149c7e Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Fri, 11 Jul 2008 15:39:22 -0500 Subject: Changed ActionView::TemplateHandler#render API method signature to render(template, local_assigns = {}) --- actionpack/lib/action_view/base.rb | 4 ++-- actionpack/lib/action_view/renderable.rb | 2 +- actionpack/lib/action_view/template_handler.rb | 2 +- actionpack/lib/action_view/template_handlers/compilable.rb | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 66892fdabf..7ef90ddf5e 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -332,8 +332,8 @@ module ActionView #:nodoc: @assigns.each { |key, value| instance_variable_set("@#{key}", value) } end - def execute(template) - send(template.method, template.locals) do |*names| + def execute(template, local_assigns = {}) + send(template.method, local_assigns) do |*names| instance_variable_get "@content_for_#{names.first || 'layout'}" end end diff --git a/actionpack/lib/action_view/renderable.rb b/actionpack/lib/action_view/renderable.rb index 3a30e603fe..6a8a0e44fc 100644 --- a/actionpack/lib/action_view/renderable.rb +++ b/actionpack/lib/action_view/renderable.rb @@ -8,7 +8,7 @@ module ActionView def render prepare! - @handler.render(self) + @handler.render(self, @locals) end def method diff --git a/actionpack/lib/action_view/template_handler.rb b/actionpack/lib/action_view/template_handler.rb index 78586d6142..1afea21f67 100644 --- a/actionpack/lib/action_view/template_handler.rb +++ b/actionpack/lib/action_view/template_handler.rb @@ -8,7 +8,7 @@ module ActionView @view = view end - def render(template) + def render(template, local_assigns = {}) end def compile(template) diff --git a/actionpack/lib/action_view/template_handlers/compilable.rb b/actionpack/lib/action_view/template_handlers/compilable.rb index 9b9255579c..95ae75ca68 100644 --- a/actionpack/lib/action_view/template_handlers/compilable.rb +++ b/actionpack/lib/action_view/template_handlers/compilable.rb @@ -14,8 +14,8 @@ module ActionView end end - def render(template) - @view.send(:execute, template) + def render(template, local_assigns = {}) + @view.send(:execute, template, local_assigns) end # Compile and evaluate the template's code -- cgit v1.2.3 From 50b5c6845ed1645cf25613024ef04187385f8dcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20S=C3=B8rensen?= Date: Sat, 12 Jul 2008 00:57:38 +0100 Subject: Ensure mail_to label is obfuscated for javascript encoding. [#294 state:resolved] Signed-off-by: Pratik Naik --- actionpack/lib/action_view/helpers/url_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb index f6a1f271f0..e5178938fd 100644 --- a/actionpack/lib/action_view/helpers/url_helper.rb +++ b/actionpack/lib/action_view/helpers/url_helper.rb @@ -466,7 +466,7 @@ module ActionView email_address_obfuscated.gsub!(/\./, html_options.delete("replace_dot")) if html_options.has_key?("replace_dot") if encode == "javascript" - "document.write('#{content_tag("a", name || email_address, html_options.merge({ "href" => "mailto:"+email_address+extras }))}');".each_byte do |c| + "document.write('#{content_tag("a", name || email_address_obfuscated, html_options.merge({ "href" => "mailto:"+email_address+extras }))}');".each_byte do |c| string << sprintf("%%%x", c) end "" -- cgit v1.2.3 From e53f5fe696d692f1985981c34bb311e898fe3c72 Mon Sep 17 00:00:00 2001 From: Michael Koziarski Date: Sat, 12 Jul 2008 11:42:41 +0200 Subject: Restore support for partial matches in assert_redirected_to If both the actual redirection and the asserted redirection are hashes, succeed if the asserted redirection is a strict subset of the actual redirection. --- .../lib/action_controller/assertions/response_assertions.rb | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/assertions/response_assertions.rb b/actionpack/lib/action_controller/assertions/response_assertions.rb index 3ecaee641f..64aaf6211f 100644 --- a/actionpack/lib/action_controller/assertions/response_assertions.rb +++ b/actionpack/lib/action_controller/assertions/response_assertions.rb @@ -63,11 +63,18 @@ module ActionController clean_backtrace do assert_response(:redirect, message) return true if options == @response.redirected_to + + # Support partial arguments for hash redirections + if options.is_a?(Hash) && @response.redirected_to.is_a?(Hash) + return true if options.all? {|(key, value)| @response.redirected_to[key] == value} + end + redirected_to_after_normalisation = normalize_argument_to_redirection(@response.redirected_to) options_after_normalisation = normalize_argument_to_redirection(options) - assert_equal redirected_to_after_normalisation, options_after_normalisation, - "Expected response to be a redirect to <#{options_after_normalisation}> but was a redirect to <#{redirected_to_after_normalisation}>" + if redirected_to_after_normalisation != options_after_normalisation + flunk "Expected response to be a redirect to <#{options_after_normalisation}> but was a redirect to <#{redirected_to_after_normalisation}>" + end end end -- cgit v1.2.3 From 73b34e9f75d33dc0709d4ad36c912bdbb8977994 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sat, 12 Jul 2008 14:33:46 -0500 Subject: Refactor template preloading. New abstractions include Renderable mixins and a refactored Template class. --- .../assertions/response_assertions.rb | 2 +- actionpack/lib/action_controller/base.rb | 9 +- actionpack/lib/action_controller/layout.rb | 2 +- actionpack/lib/action_controller/test_process.rb | 10 +- actionpack/lib/action_view.rb | 8 +- actionpack/lib/action_view/base.rb | 79 ++++++------ actionpack/lib/action_view/inline_template.rb | 13 +- actionpack/lib/action_view/partial_template.rb | 69 ----------- actionpack/lib/action_view/partials.rb | 58 +++++---- actionpack/lib/action_view/paths.rb | 85 +++++++++++++ actionpack/lib/action_view/renderable.rb | 81 +++++++++--- actionpack/lib/action_view/renderable_partial.rb | 19 +++ actionpack/lib/action_view/template.rb | 138 +++++++++++++-------- actionpack/lib/action_view/template_error.rb | 2 +- actionpack/lib/action_view/template_file.rb | 88 ------------- .../action_view/template_handlers/compilable.rb | 50 -------- actionpack/lib/action_view/view_load_paths.rb | 103 --------------- 17 files changed, 351 insertions(+), 465 deletions(-) delete mode 100644 actionpack/lib/action_view/partial_template.rb create mode 100644 actionpack/lib/action_view/paths.rb create mode 100644 actionpack/lib/action_view/renderable_partial.rb delete mode 100644 actionpack/lib/action_view/template_file.rb delete mode 100644 actionpack/lib/action_view/view_load_paths.rb (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/assertions/response_assertions.rb b/actionpack/lib/action_controller/assertions/response_assertions.rb index 64aaf6211f..cb36405700 100644 --- a/actionpack/lib/action_controller/assertions/response_assertions.rb +++ b/actionpack/lib/action_controller/assertions/response_assertions.rb @@ -93,7 +93,7 @@ module ActionController if expected.nil? !@response.rendered_with_file? else - expected == rendered + rendered.match(expected) end end end diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 9d9ff527c2..6926941396 100755 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -431,7 +431,7 @@ module ActionController #:nodoc: end def view_paths=(value) - @view_paths = ActionView::ViewLoadPaths.new(Array(value)) if value + @view_paths = ActionView::PathSet.new(Array(value)) if value end # Adds a view_path to the front of the view_paths array. @@ -652,7 +652,7 @@ module ActionController #:nodoc: end def view_paths=(value) - @template.view_paths = ViewLoadPaths.new(value) + @template.view_paths = PathSet.new(value) end # Adds a view_path to the front of the view_paths array. @@ -1248,9 +1248,8 @@ module ActionController #:nodoc: end def template_exempt_from_layout?(template_name = default_template_name) - extension = @template && @template.pick_template_extension(template_name) - name_with_extension = !template_name.include?('.') && extension ? "#{template_name}.#{extension}" : template_name - @@exempt_from_layout.any? { |ext| name_with_extension =~ ext } + template_name = @template.pick_template(template_name).to_s if @template + @@exempt_from_layout.any? { |ext| template_name =~ ext } end def default_template_name(action_name = self.action_name) diff --git a/actionpack/lib/action_controller/layout.rb b/actionpack/lib/action_controller/layout.rb index d0c717ff67..8b6febe254 100644 --- a/actionpack/lib/action_controller/layout.rb +++ b/actionpack/lib/action_controller/layout.rb @@ -304,7 +304,7 @@ module ActionController #:nodoc: end def layout_directory?(layout_name) - @template.view_paths.find_template_file_for_path("#{File.join('layouts', layout_name)}.#{@template.template_format}.erb") ? true : false + @template.file_exists?("#{File.join('layouts', layout_name)}.#{@template.template_format}") end end end diff --git a/actionpack/lib/action_controller/test_process.rb b/actionpack/lib/action_controller/test_process.rb index 8ae73a66f4..52884a93f4 100644 --- a/actionpack/lib/action_controller/test_process.rb +++ b/actionpack/lib/action_controller/test_process.rb @@ -207,13 +207,9 @@ module ActionController #:nodoc: # Returns the template path of the file which was used to # render this response (or nil) - def rendered_file(with_controller=false) - unless template.first_render.nil? - unless with_controller - template.first_render - else - template.first_render.split('/').last || template.first_render - end + def rendered_file(with_controller = false) + if template.first_render + template.first_render.to_s end end diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index 8f928d6fdf..9ab615c7a5 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -21,14 +21,14 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #++ -require 'action_view/template_handlers' -require 'action_view/template_file' -require 'action_view/view_load_paths' +require 'action_view/template_handlers' require 'action_view/renderable' +require 'action_view/renderable_partial' + require 'action_view/template' -require 'action_view/partial_template' require 'action_view/inline_template' +require 'action_view/paths' require 'action_view/base' require 'action_view/partials' diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 7ef90ddf5e..9d4d897dbc 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -3,6 +3,12 @@ module ActionView #:nodoc: end class MissingTemplate < ActionViewError #:nodoc: + def initialize(paths, path, template_format = nil) + full_template_path = path.include?('.') ? path : "#{path}.erb" + display_paths = paths.join(':') + template_type = (path =~ /layouts/i) ? 'layout' : 'template' + super("Missing #{template_type} #{full_template_path} in view path #{display_paths}") + end end # Action View templates can be written in three ways. If the template file has a .erb (or .rhtml) extension then it uses a mixture of ERb @@ -216,12 +222,14 @@ module ActionView #:nodoc: attr_reader :view_paths def view_paths=(paths) - @view_paths = ViewLoadPaths.new(Array(paths)) + @view_paths = PathSet.new(Array(paths)) end # Renders the template present at template_path (relative to the view_paths array). # The hash in local_assigns is made available as local variables. def render(options = {}, local_assigns = {}, &block) #:nodoc: + local_assigns ||= {} + if options.is_a?(String) render_file(options, nil, local_assigns) elsif options == :update @@ -270,21 +278,40 @@ module ActionView #:nodoc: end def file_exists?(template_path) - view_paths.template_exists?(template_file_from_name(template_path)) + pick_template(template_path) ? true : false + rescue MissingTemplate + false end # Gets the extension for an existing template with the given template_path. # Returns the format with the extension if that template exists. # - # pick_template_extension('users/show') - # # => 'html.erb' + # pick_template('users/show') + # # => 'users/show.html.erb' # - # pick_template_extension('users/legacy') - # # => "rhtml" + # pick_template('users/legacy') + # # => 'users/legacy.rhtml' # - def pick_template_extension(template_path) - if template = template_file_from_name(template_path) - template.extension + def pick_template(template_path) + path = template_path.sub(/^\//, '') + if m = path.match(/(.*)\.(\w+)$/) + template_file_name, template_file_extension = m[1], m[2] + else + template_file_name = path + end + + # OPTIMIZE: Checks to lookup template in view path + if template = self.view_paths["#{template_file_name}.#{template_format}"] + template + elsif template = self.view_paths[template_file_name] + template + elsif first_render && template = self.view_paths["#{template_file_name}.#{first_render.extension}"] + template + elsif template_format == :js && template = self.view_paths["#{template_file_name}.html"] + @template_format = :html + template + else + Template.new(template_path, view_paths) end end @@ -292,6 +319,10 @@ module ActionView #:nodoc: # Renders the template present at template_path. The hash in local_assigns # is made available as local variables. def render_file(template_path, use_full_path = nil, local_assigns = {}) #:nodoc: + unless use_full_path == nil + ActiveSupport::Deprecation.warn("use_full_path option has been deprecated and has no affect.", caller) + end + if defined?(ActionMailer) && defined?(ActionMailer::Base) && controller.is_a?(ActionMailer::Base) && !template_path.include?("/") raise ActionViewError, <<-END_ERROR Due to changes in ActionMailer, you need to provide the mailer_name along with the template name. @@ -305,11 +336,12 @@ module ActionView #:nodoc: END_ERROR end - Template.new(self, template_path, use_full_path, local_assigns).render_template + template = pick_template(template_path) + template.render_template(self, local_assigns) end def render_inline(text, local_assigns = {}, type = nil) - InlineTemplate.new(self, text, local_assigns, type).render + InlineTemplate.new(text, type).render(self, local_assigns) end def wrap_content_for_layout(content) @@ -333,32 +365,9 @@ module ActionView #:nodoc: end def execute(template, local_assigns = {}) - send(template.method, local_assigns) do |*names| + send(template.method(local_assigns), local_assigns) do |*names| instance_variable_get "@content_for_#{names.first || 'layout'}" end end - - def template_file_from_name(template_name) - template_name = TemplateFile.from_path(template_name) - pick_template(template_name) unless template_name.extension - end - - def pick_template(file) - if f = self.view_paths.find_template_file_for_path(file.dup_with_extension(template_format)) || file_from_first_render(file) - f - elsif template_format == :js && f = self.view_paths.find_template_file_for_path(file.dup_with_extension(:html)) - @template_format = :html - f - else - nil - end - end - - # Determine the template extension from the @first_render filename - def file_from_first_render(file) - if extension = File.basename(@first_render.to_s)[/^[^.]+\.(.+)$/, 1] - file.dup_with_extension(extension) - end - end end end diff --git a/actionpack/lib/action_view/inline_template.rb b/actionpack/lib/action_view/inline_template.rb index 3e25f6902d..5e00cef13f 100644 --- a/actionpack/lib/action_view/inline_template.rb +++ b/actionpack/lib/action_view/inline_template.rb @@ -2,15 +2,18 @@ module ActionView #:nodoc: class InlineTemplate #:nodoc: include Renderable - def initialize(view, source, locals = {}, type = nil) - @view = view + attr_reader :source, :extension, :method_segment + def initialize(source, type = nil) @source = source @extension = type - @locals = locals || {} - @method_segment = "inline_#{@source.hash.abs}" - @handler = Template.handler_class_for_extension(@extension).new(@view) end + + private + # Always recompile inline templates + def recompile?(local_assigns) + true + end end end diff --git a/actionpack/lib/action_view/partial_template.rb b/actionpack/lib/action_view/partial_template.rb deleted file mode 100644 index 72f831e937..0000000000 --- a/actionpack/lib/action_view/partial_template.rb +++ /dev/null @@ -1,69 +0,0 @@ -module ActionView #:nodoc: - class PartialTemplate < Template #:nodoc: - attr_reader :variable_name, :object, :as - - def initialize(view, partial_path, object = nil, locals = {}, as = nil) - @view_controller = view.controller if view.respond_to?(:controller) - @as = as - set_path_and_variable_name!(partial_path) - super(view, @path, nil, locals) - add_object_to_local_assigns!(object) - - # This is needed here in order to compile template with knowledge of 'counter' - initialize_counter! - - # Prepare early. This is a performance optimization for partial collections - prepare! - end - - def render - ActionController::Base.benchmark("Rendered #{@path.path_without_format_and_extension}", Logger::DEBUG, false) do - super - end - end - - def render_member(object) - @locals[:object] = @locals[@variable_name] = object - @locals[as] = object if as - - template = render_template - @locals[@counter_name] += 1 - @locals.delete(as) - @locals.delete(@variable_name) - @locals.delete(:object) - - template - end - - def counter=(num) - @locals[@counter_name] = num - end - - private - def add_object_to_local_assigns!(object) - @locals[:object] ||= - @locals[@variable_name] ||= object || @view_controller.instance_variable_get("@#{variable_name}") - @locals[as] ||= @locals[:object] if as - end - - def set_path_and_variable_name!(partial_path) - if partial_path.include?('/') - @variable_name = File.basename(partial_path) - @path = "#{File.dirname(partial_path)}/_#{@variable_name}" - elsif @view_controller - @variable_name = partial_path - @path = "#{@view_controller.class.controller_path}/_#{@variable_name}" - else - @variable_name = partial_path - @path = "_#{@variable_name}" - end - - @variable_name = @variable_name.sub(/\..*$/, '').to_sym - end - - def initialize_counter! - @counter_name ||= "#{@variable_name}_counter".to_sym - @locals[@counter_name] = 0 - end - end -end diff --git a/actionpack/lib/action_view/partials.rb b/actionpack/lib/action_view/partials.rb index 7c6c98d611..116d61e13b 100644 --- a/actionpack/lib/action_view/partials.rb +++ b/actionpack/lib/action_view/partials.rb @@ -104,10 +104,12 @@ module ActionView module Partials private def render_partial(partial_path, object_assigns = nil, local_assigns = {}) #:nodoc: + local_assigns ||= {} + case partial_path when String, Symbol, NilClass - # Render the template - ActionView::PartialTemplate.new(self, partial_path, object_assigns, local_assigns).render_template + variable_name, path = partial_pieces(partial_path) + pick_template(path).render_partial(self, variable_name, object_assigns, local_assigns) when ActionView::Helpers::FormBuilder builder_partial_path = partial_path.class.to_s.demodulize.underscore.sub(/_builder$/, '') render_partial(builder_partial_path, object_assigns, (local_assigns || {}).merge(builder_partial_path.to_sym => partial_path)) @@ -128,31 +130,43 @@ module ActionView local_assigns = local_assigns ? local_assigns.clone : {} spacer = partial_spacer_template ? render(:partial => partial_spacer_template) : '' + _partial_pieces = {} + _templates = {} - if partial_path.nil? - render_partial_collection_with_unknown_partial_path(collection, local_assigns, as) - else - render_partial_collection_with_known_partial_path(collection, partial_path, local_assigns, as) - end.join(spacer) - end + index = 0 + collection.map do |object| + _partial_path ||= partial_path || ActionController::RecordIdentifier.partial_path(object, controller.class.controller_path) + variable_name, path = _partial_pieces[_partial_path] ||= partial_pieces(_partial_path) + template = _templates[path] ||= pick_template(path) - def render_partial_collection_with_known_partial_path(collection, partial_path, local_assigns, as) - template = ActionView::PartialTemplate.new(self, partial_path, nil, local_assigns, as) - collection.map do |element| - template.render_member(element) - end + local_assigns["#{variable_name}_counter".to_sym] = index + local_assigns[:object] = local_assigns[variable_name] = object + local_assigns[as] = object if as + + result = template.render_partial(self, variable_name, object, local_assigns) + + local_assigns.delete(as) + local_assigns.delete(variable_name) + local_assigns.delete(:object) + index += 1 + + result + end.join(spacer) end - def render_partial_collection_with_unknown_partial_path(collection, local_assigns, as) - templates = Hash.new - i = 0 - collection.map do |element| - partial_path = ActionController::RecordIdentifier.partial_path(element, controller.class.controller_path) - template = templates[partial_path] ||= ActionView::PartialTemplate.new(self, partial_path, nil, local_assigns, as) - template.counter = i - i += 1 - template.render_member(element) + def partial_pieces(partial_path) + if partial_path.include?('/') + variable_name = File.basename(partial_path) + path = "#{File.dirname(partial_path)}/_#{variable_name}" + elsif respond_to?(:controller) + variable_name = partial_path + path = "#{controller.class.controller_path}/_#{variable_name}" + else + variable_name = partial_path + path = "_#{variable_name}" end + variable_name = variable_name.sub(/\..*$/, '').to_sym + return variable_name, path end end end diff --git a/actionpack/lib/action_view/paths.rb b/actionpack/lib/action_view/paths.rb new file mode 100644 index 0000000000..0fa7d3dad3 --- /dev/null +++ b/actionpack/lib/action_view/paths.rb @@ -0,0 +1,85 @@ +module ActionView #:nodoc: + class PathSet < Array #:nodoc: + def self.type_cast(obj) + obj.is_a?(String) ? Path.new(obj) : obj + end + + class Path #:nodoc: + attr_reader :path, :paths + delegate :to_s, :to_str, :inspect, :to => :path + + def initialize(path) + @path = path.freeze + reload! + end + + def ==(path) + to_str == path.to_str + end + + def [](path) + @paths[path] + end + + # Rebuild load path directory cache + def reload! + @paths = {} + + templates_in_path do |template| + @paths[template.path] = template + @paths[template.path_without_extension] ||= template + end + + @paths.freeze + end + + private + def templates_in_path + (Dir.glob("#{@path}/**/*/**") | Dir.glob("#{@path}/**")).each do |file| + unless File.directory?(file) + template = Template.new(file.split("#{self}/").last, self) + # Eager load memoized methods and freeze cached template + template.freeze if Base.cache_template_loading + yield template + end + end + end + end + + def initialize(*args) + super(*args).map! { |obj| self.class.type_cast(obj) } + end + + def reload! + each { |path| path.reload! } + end + + def <<(obj) + super(self.class.type_cast(obj)) + end + + def push(*objs) + delete_paths!(objs) + super(*objs.map { |obj| self.class.type_cast(obj) }) + end + + def unshift(*objs) + delete_paths!(objs) + super(*objs.map { |obj| self.class.type_cast(obj) }) + end + + def [](template_path) + each do |path| + if template = path[template_path] + return template + end + end + nil + end + + private + def delete_paths!(paths) + paths.each { |p1| delete_if { |p2| p1.to_s == p2.to_s } } + end + end +end diff --git a/actionpack/lib/action_view/renderable.rb b/actionpack/lib/action_view/renderable.rb index 6a8a0e44fc..2c4302146f 100644 --- a/actionpack/lib/action_view/renderable.rb +++ b/actionpack/lib/action_view/renderable.rb @@ -1,37 +1,78 @@ module ActionView module Renderable - # TODO: Local assigns should not be tied to template instance - attr_accessor :locals + # NOTE: The template that this mixin is beening include into is frozen + # So you can not set or modify any instance variables - # TODO: These readers should be private - attr_reader :filename, :source, :handler + def self.included(base) + @@mutex = Mutex.new + end + + # NOTE: Exception to earlier notice. Ensure this is called before freeze + def handler + @handler ||= Template.handler_class_for_extension(extension) + end - def render - prepare! - @handler.render(self, @locals) + # NOTE: Exception to earlier notice. Ensure this is called before freeze + def compiled_source + @compiled_source ||= handler.new(nil).compile(self) if handler.compilable? end - def method - ['_run', @extension, @method_segment, local_assigns_keys].compact.join('_').to_sym + def render(view, local_assigns = {}) + view.first_render ||= self + view.send(:evaluate_assigns) + view.current_render_extension = extension + compile(local_assigns) if handler.compilable? + handler.new(view).render(self, local_assigns) + end + + def method(local_assigns) + if local_assigns && local_assigns.any? + local_assigns_keys = "locals_#{local_assigns.keys.map { |k| k.to_s }.sort.join('_')}" + end + ['_run', extension, method_segment, local_assigns_keys].compact.join('_').to_sym end private - def prepare! - unless @prepared - @view.send(:evaluate_assigns) - @view.current_render_extension = @extension + # Compile and evaluate the template's code + def compile(local_assigns) + render_symbol = method(local_assigns) - if @handler.compilable? - @handler.compile_template(self) # compile the given template, if necessary - end + @@mutex.synchronize do + return false unless recompile?(render_symbol) + + locals_code = local_assigns.keys.map { |key| "#{key} = local_assigns[:#{key}];" }.join + + source = <<-end_src + def #{render_symbol}(local_assigns) + old_output_buffer = output_buffer;#{locals_code};#{compiled_source} + ensure + self.output_buffer = old_output_buffer + end + end_src - @prepared = true + begin + file_name = respond_to?(:filename) ? filename : 'compiled-template' + ActionView::Base::CompiledTemplates.module_eval(source, file_name, 0) + rescue Exception => e # errors from template code + if logger = ActionController::Base.logger + logger.debug "ERROR: compiling #{render_symbol} RAISED #{e}" + logger.debug "Function body: #{source}" + logger.debug "Backtrace: #{e.backtrace.join("\n")}" + end + + raise ActionView::TemplateError.new(self, {}, e) + end end end - def local_assigns_keys - if @locals && @locals.any? - "locals_#{@locals.keys.map { |k| k.to_s }.sort.join('_')}" + # Method to check whether template compilation is necessary. + # The template will be compiled if the file has not been compiled yet, or + # if local_assigns has a new key, which isn't supported by the compiled code yet. + def recompile?(symbol) + unless Base::CompiledTemplates.instance_methods.include?(symbol) && Base.cache_template_loading + true + else + false end end end diff --git a/actionpack/lib/action_view/renderable_partial.rb b/actionpack/lib/action_view/renderable_partial.rb new file mode 100644 index 0000000000..6a17b50a14 --- /dev/null +++ b/actionpack/lib/action_view/renderable_partial.rb @@ -0,0 +1,19 @@ +module ActionView + module RenderablePartial + # NOTE: The template that this mixin is beening include into is frozen + # So you can not set or modify any instance variables + + def render(view, local_assigns = {}) + ActionController::Base.benchmark("Rendered #{path_without_format_and_extension}", Logger::DEBUG, false) do + super + end + end + + def render_partial(view, variable_name, object = nil, local_assigns = {}, as = nil) + object ||= view.controller.instance_variable_get("@#{variable_name}") if view.respond_to?(:controller) + local_assigns[:object] ||= local_assigns[variable_name] ||= object + local_assigns[as] ||= local_assigns[:object] if as + render_template(view, local_assigns) + end + end +end diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 5e5ea9b9b9..03f9234289 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -1,82 +1,112 @@ module ActionView #:nodoc: - class Template #:nodoc: + class Template extend TemplateHandlers include Renderable - attr_reader :path, :extension + attr_accessor :filename, :load_path, :base_path, :name, :format, :extension + delegate :to_s, :to => :path - def initialize(view, path, use_full_path = nil, locals = {}) - unless use_full_path == nil - ActiveSupport::Deprecation.warn("use_full_path option has been deprecated and has no affect.", caller) - end + def initialize(template_path, load_paths = []) + template_path = template_path.dup + @base_path, @name, @format, @extension = split(template_path) + @base_path.to_s.gsub!(/\/$/, '') # Push to split method + @load_path, @filename = find_full_path(template_path, load_paths) + + # Extend with partial super powers + extend RenderablePartial if @name =~ /^_/ + end + + def freeze + # Eager load memoized methods + format_and_extension + path + path_without_extension + path_without_format_and_extension + source + method_segment + + # Eager load memoized methods from Renderable + handler + compiled_source + + instance_variables.each { |ivar| ivar.freeze } + + super + end - @view = view - @paths = view.view_paths + def format_and_extension + @format_and_extension ||= (extensions = [format, extension].compact.join(".")).blank? ? nil : extensions + end + + def path + @path ||= [base_path, [name, format, extension].compact.join('.')].compact.join('/') + end - @original_path = path - @path = TemplateFile.from_path(path) - @view.first_render ||= @path.to_s + def path_without_extension + @path_without_extension ||= [base_path, [name, format].compact.join('.')].compact.join('/') + end - set_extension_and_file_name + def path_without_format_and_extension + @path_without_format_and_extension ||= [base_path, name].compact.join('/') + end - @method_segment = compiled_method_name_file_path_segment - @locals = (locals && locals.dup) || {} - @handler = self.class.handler_class_for_extension(@extension).new(@view) + def source + @source ||= File.read(@filename) end - def render_template - render + def method_segment + unless @method_segment + segment = File.expand_path(@filename) + segment.sub!(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}/, '') if defined?(RAILS_ROOT) + segment.gsub!(/([^a-zA-Z0-9_])/) { $1.ord } + @method_segment = segment + end + + @method_segment + end + + def render_template(view, local_assigns = {}) + render(view, local_assigns) rescue Exception => e raise e unless filename if TemplateError === e e.sub_template_of(filename) raise e else - raise TemplateError.new(self, @view.assigns, e) + raise TemplateError.new(self, view.assigns, e) end end - def source - @source ||= File.read(@filename) - end - - def base_path_for_exception - (@paths.find_load_path_for_path(@path) || @paths.first).to_s - end - private - def set_extension_and_file_name - @extension = @path.extension - - unless @extension - @path = @view.send(:template_file_from_name, @path) - raise_missing_template_exception unless @path - @extension = @path.extension - end - - if p = @paths.find_template_file_for_path(path) - @path = p - @filename = @path.full_path - @extension = @path.extension - raise_missing_template_exception if @filename.blank? - else - @filename = @original_path - raise_missing_template_exception unless File.exist?(@filename) - end + def valid_extension?(extension) + Template.template_handler_extensions.include?(extension) end - def raise_missing_template_exception - full_template_path = @original_path.include?('.') ? @original_path : "#{@original_path}.#{@view.template_format}.erb" - display_paths = @paths.join(':') - template_type = (@original_path =~ /layouts/i) ? 'layout' : 'template' - raise MissingTemplate, "Missing #{template_type} #{full_template_path} in view path #{display_paths}" + def find_full_path(path, load_paths) + load_paths = Array(load_paths) + [nil] + load_paths.each do |load_path| + file = [load_path, path].compact.join('/') + return load_path, file if File.exist?(file) + end + raise MissingTemplate.new(load_paths, path) end - def compiled_method_name_file_path_segment - s = File.expand_path(@filename) - s.sub!(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}/, '') if defined?(RAILS_ROOT) - s.gsub!(/([^a-zA-Z0-9_])/) { $1.ord } - s + # Returns file split into an array + # [base_path, name, format, extension] + def split(file) + if m = file.match(/^(.*\/)?([^\.]+)\.?(\w+)?\.?(\w+)?\.?(\w+)?$/) + if m[5] # Mulipart formats + [m[1], m[2], "#{m[3]}.#{m[4]}", m[5]] + elsif m[4] # Single format + [m[1], m[2], m[3], m[4]] + else + if valid_extension?(m[3]) # No format + [m[1], m[2], nil, m[3]] + else # No extension + [m[1], m[2], m[3], nil] + end + end + end end end end diff --git a/actionpack/lib/action_view/template_error.rb b/actionpack/lib/action_view/template_error.rb index a1be1a8833..35fc07bdb2 100644 --- a/actionpack/lib/action_view/template_error.rb +++ b/actionpack/lib/action_view/template_error.rb @@ -7,7 +7,7 @@ module ActionView attr_reader :original_exception def initialize(template, assigns, original_exception) - @base_path = template.base_path_for_exception + @base_path = template.base_path @assigns, @source, @original_exception = assigns.dup, template.source, original_exception @file_path = template.filename @backtrace = compute_backtrace diff --git a/actionpack/lib/action_view/template_file.rb b/actionpack/lib/action_view/template_file.rb deleted file mode 100644 index 0aa16b5e70..0000000000 --- a/actionpack/lib/action_view/template_file.rb +++ /dev/null @@ -1,88 +0,0 @@ -module ActionView #:nodoc: - # TemplateFile abstracts the pattern of querying a file path for its - # path with or without its extension. The path is only the partial path - # from the load path root e.g. "hello/index.html.erb" not - # "app/views/hello/index.html.erb" - class TemplateFile - def self.from_path(path) - path.is_a?(self) ? path : new(path) - end - - def self.from_full_path(load_path, full_path) - file = new(full_path.split(load_path).last) - file.load_path = load_path - file.freeze - end - - attr_accessor :load_path, :base_path, :name, :format, :extension - delegate :to_s, :inspect, :to => :path - - def initialize(path) - path = path.dup - - # Clear the forward slash in the beginning - trim_forward_slash!(path) - - @base_path, @name, @format, @extension = split(path) - end - - def freeze - @load_path.freeze - @base_path.freeze - @name.freeze - @format.freeze - @extension.freeze - super - end - - def format_and_extension - extensions = [format, extension].compact.join(".") - extensions.blank? ? nil : extensions - end - - def full_path - if load_path - "#{load_path}/#{path}" - else - path - end - end - - def path - base_path.to_s + [name, format, extension].compact.join(".") - end - - def path_without_extension - base_path.to_s + [name, format].compact.join(".") - end - - def path_without_format_and_extension - "#{base_path}#{name}" - end - - def dup_with_extension(extension) - file = dup - file.extension = extension ? extension.to_s : nil - file - end - - private - def trim_forward_slash!(path) - path.sub!(/^\//, '') - end - - # Returns file split into an array - # [base_path, name, format, extension] - def split(file) - if m = file.match(/^(.*\/)?([^\.]+)\.?(\w+)?\.?(\w+)?\.?(\w+)?$/) - if m[5] # Mulipart formats - [m[1], m[2], "#{m[3]}.#{m[4]}", m[5]] - elsif m[4] # Single format - [m[1], m[2], m[3], m[4]] - else # No format - [m[1], m[2], nil, m[3]] - end - end - end - end -end diff --git a/actionpack/lib/action_view/template_handlers/compilable.rb b/actionpack/lib/action_view/template_handlers/compilable.rb index 95ae75ca68..a0ebaefeef 100644 --- a/actionpack/lib/action_view/template_handlers/compilable.rb +++ b/actionpack/lib/action_view/template_handlers/compilable.rb @@ -3,8 +3,6 @@ module ActionView module Compilable def self.included(base) base.extend ClassMethod - - @@mutex = Mutex.new end module ClassMethod @@ -17,54 +15,6 @@ module ActionView def render(template, local_assigns = {}) @view.send(:execute, template, local_assigns) end - - # Compile and evaluate the template's code - def compile_template(template) - return false unless recompile_template?(template) - - @@mutex.synchronize do - locals_code = template.locals.keys.map { |key| "#{key} = local_assigns[:#{key}];" }.join - - source = <<-end_src - def #{template.method}(local_assigns) - old_output_buffer = output_buffer;#{locals_code};#{compile(template)} - ensure - self.output_buffer = old_output_buffer - end - end_src - - begin - file_name = template.filename || 'compiled-template' - ActionView::Base::CompiledTemplates.module_eval(source, file_name, 0) - rescue Exception => e # errors from template code - if logger = ActionController::Base.logger - logger.debug "ERROR: compiling #{template.method} RAISED #{e}" - logger.debug "Function body: #{source}" - logger.debug "Backtrace: #{e.backtrace.join("\n")}" - end - - raise ActionView::TemplateError.new(template, @view.assigns, e) - end - end - end - - private - # Method to check whether template compilation is necessary. - # The template will be compiled if the inline template or file has not been compiled yet, - # if local_assigns has a new key, which isn't supported by the compiled code yet. - def recompile_template?(template) - # Unless the template has been complied yet, compile - return true unless Base::CompiledTemplates.instance_methods.include?(template.method.to_s) - - # If template caching is disabled, compile - return true unless Base.cache_template_loading - - # Always recompile inline templates - return true if template.is_a?(InlineTemplate) - - # Otherwise, use compiled method - return false - end end end end diff --git a/actionpack/lib/action_view/view_load_paths.rb b/actionpack/lib/action_view/view_load_paths.rb deleted file mode 100644 index 6e439a009c..0000000000 --- a/actionpack/lib/action_view/view_load_paths.rb +++ /dev/null @@ -1,103 +0,0 @@ -module ActionView #:nodoc: - class ViewLoadPaths < Array #:nodoc: - def self.type_cast(obj) - obj.is_a?(String) ? LoadPath.new(obj) : obj - end - - class LoadPath #:nodoc: - attr_reader :path, :paths - delegate :to_s, :to_str, :inspect, :to => :path - - def initialize(path) - @path = path.freeze - reload! - end - - def ==(path) - to_str == path.to_str - end - - # Rebuild load path directory cache - def reload! - @paths = {} - - files.each do |file| - @paths[file.path] = file - @paths[file.path_without_extension] ||= file - end - - @paths.freeze - end - - def find_template_file_for_partial_path(template_path, template_format) - @paths["#{template_path}.#{template_format}"] || - @paths[template_path] || - @paths[template_path.gsub(/\..*$/, '')] - end - - private - # Get all the files and directories in the path - def files_in_path - Dir.glob("#{@path}/**/*/**") | Dir.glob("#{@path}/**") - end - - # Create an array of all the files within the path - def files - files_in_path.map do |file| - TemplateFile.from_full_path(@path, file) unless File.directory?(file) - end.compact - end - end - - def initialize(*args) - super(*args).map! { |obj| self.class.type_cast(obj) } - end - - def reload! - each { |path| path.reload! } - end - - def <<(obj) - super(self.class.type_cast(obj)) - end - - def push(*objs) - delete_paths!(objs) - super(*objs.map { |obj| self.class.type_cast(obj) }) - end - - def unshift(*objs) - delete_paths!(objs) - super(*objs.map { |obj| self.class.type_cast(obj) }) - end - - def template_exists?(file) - find_load_path_for_path(file) ? true : false - end - - def find_load_path_for_path(file) - find { |path| path.paths[file.to_s] } - end - - def find_template_file_for_path(template_path) - template_path_without_extension, template_extension = path_and_extension(template_path.to_s) - each do |path| - if f = path.find_template_file_for_partial_path(template_path_without_extension, template_extension) - return f - end - end - nil - end - - private - def delete_paths!(paths) - paths.each { |p1| delete_if { |p2| p1.to_s == p2.to_s } } - end - - # Splits the path and extension from the given template_path and returns as an array. - def path_and_extension(template_path) - template_path_without_extension = template_path.sub(/\.(\w+)$/, '') - [template_path_without_extension, $1] - end - end -end -- cgit v1.2.3 From 99cc85bc099a757cdd44e4f5f1be4972ab124e0d Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sat, 12 Jul 2008 15:31:50 -0500 Subject: Set config.action_view.warn_cache_misses = true to receive a warning if you perform an action that results in an expensive disk operation that could be cached --- actionpack/lib/action_controller/base.rb | 4 ++-- actionpack/lib/action_view/base.rb | 22 ++++++++++++++++++++-- actionpack/lib/action_view/paths.rb | 13 ++++++++++++- 3 files changed, 34 insertions(+), 5 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 6926941396..df94f78f18 100755 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -431,7 +431,7 @@ module ActionController #:nodoc: end def view_paths=(value) - @view_paths = ActionView::PathSet.new(Array(value)) if value + @view_paths = ActionView::Base.process_view_paths(value) if value end # Adds a view_path to the front of the view_paths array. @@ -652,7 +652,7 @@ module ActionController #:nodoc: end def view_paths=(value) - @template.view_paths = PathSet.new(value) + @template.view_paths = ActionView::Base.process_view_paths(value) end # Adds a view_path to the front of the view_paths array. diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 9d4d897dbc..989e92a890 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -185,6 +185,10 @@ module ActionView #:nodoc: @@debug_rjs = false cattr_accessor :debug_rjs + # A warning will be displayed whenever an action results in a cache miss on your view paths. + @@warn_cache_misses = false + cattr_accessor :warn_cache_misses + attr_internal :request delegate :request_forgery_protection_token, :template, :params, :session, :cookies, :response, :headers, @@ -212,6 +216,10 @@ module ActionView #:nodoc: return helpers end + def self.process_view_paths(value) + ActionView::PathSet.new(Array(value)) + end + def initialize(view_paths = [], assigns_for_first_render = {}, controller = nil)#:nodoc: @assigns = assigns_for_first_render @assigns_added = nil @@ -222,7 +230,7 @@ module ActionView #:nodoc: attr_reader :view_paths def view_paths=(paths) - @view_paths = PathSet.new(Array(paths)) + @view_paths = self.class.process_view_paths(paths) end # Renders the template present at template_path (relative to the view_paths array). @@ -311,7 +319,17 @@ module ActionView #:nodoc: @template_format = :html template else - Template.new(template_path, view_paths) + template = Template.new(template_path, view_paths) + + if self.class.warn_cache_misses && logger = ActionController::Base.logger + logger.debug "[PERFORMANCE] Rendering a template that was " + + "not found in view path. Templates outside the view path are " + + "not cached and result in expensive disk operations. Move this " + + "file into #{view_paths.join(':')} or add the folder to your " + + "view path list" + end + + template end end diff --git a/actionpack/lib/action_view/paths.rb b/actionpack/lib/action_view/paths.rb index 0fa7d3dad3..b0ab7d0c67 100644 --- a/actionpack/lib/action_view/paths.rb +++ b/actionpack/lib/action_view/paths.rb @@ -1,7 +1,18 @@ module ActionView #:nodoc: class PathSet < Array #:nodoc: def self.type_cast(obj) - obj.is_a?(String) ? Path.new(obj) : obj + if obj.is_a?(String) + if Base.warn_cache_misses && defined?(Rails) && Rails.initialized? + Rails.logger.debug "[PERFORMANCE] Processing view path during a " + + "request. This an expense disk operation that should be done at " + + "boot. You can manually process this view path with " + + "ActionView::Base.process_view_paths(#{obj.inspect}) and set it " + + "as your view path" + end + Path.new(obj) + else + obj + end end class Path #:nodoc: -- cgit v1.2.3 From e0fef66149092dd3d2988fff64f0ce8765735687 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 13 Jul 2008 13:26:48 -0500 Subject: Made ActionView::Base#first_render a little more private. And added _last_render to track the most recent render. Will fix #609 as a side effect. [#609 state:resolved] --- .../action_controller/assertions/response_assertions.rb | 4 ++-- actionpack/lib/action_controller/test_process.rb | 15 ++++----------- actionpack/lib/action_view/base.rb | 6 +++--- actionpack/lib/action_view/helpers/cache_helper.rb | 3 +-- actionpack/lib/action_view/renderable.rb | 4 ++-- 5 files changed, 12 insertions(+), 20 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/assertions/response_assertions.rb b/actionpack/lib/action_controller/assertions/response_assertions.rb index cb36405700..a98c70d66f 100644 --- a/actionpack/lib/action_controller/assertions/response_assertions.rb +++ b/actionpack/lib/action_controller/assertions/response_assertions.rb @@ -87,11 +87,11 @@ module ActionController # def assert_template(expected = nil, message=nil) clean_backtrace do - rendered = expected ? @response.rendered_file(!expected.include?('/')) : @response.rendered_file + rendered = @response.rendered_template.to_s msg = build_message(message, "expecting but rendering with ", expected, rendered) assert_block(msg) do if expected.nil? - !@response.rendered_with_file? + @response.rendered_template ? true : false else rendered.match(expected) end diff --git a/actionpack/lib/action_controller/test_process.rb b/actionpack/lib/action_controller/test_process.rb index 52884a93f4..a6e0c98936 100644 --- a/actionpack/lib/action_controller/test_process.rb +++ b/actionpack/lib/action_controller/test_process.rb @@ -205,17 +205,10 @@ module ActionController #:nodoc: p.match(redirect_url) != nil end - # Returns the template path of the file which was used to - # render this response (or nil) - def rendered_file(with_controller = false) - if template.first_render - template.first_render.to_s - end - end - - # Was this template rendered by a file? - def rendered_with_file? - !rendered_file.nil? + # Returns the template of the file which was used to + # render this response (or nil) + def rendered_template + template._first_render end # A shortcut to the flash. Returns an empyt hash if no session flash exists. diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 989e92a890..9f244d7250 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -159,11 +159,11 @@ module ActionView #:nodoc: class Base include ERB::Util - attr_accessor :base_path, :assigns, :template_extension, :first_render + attr_accessor :base_path, :assigns, :template_extension attr_accessor :controller + attr_accessor :_first_render, :_last_render attr_writer :template_format - attr_accessor :current_render_extension attr_accessor :output_buffer @@ -313,7 +313,7 @@ module ActionView #:nodoc: template elsif template = self.view_paths[template_file_name] template - elsif first_render && template = self.view_paths["#{template_file_name}.#{first_render.extension}"] + elsif _first_render && template = self.view_paths["#{template_file_name}.#{_first_render.extension}"] template elsif template_format == :js && template = self.view_paths["#{template_file_name}.html"] @template_format = :html diff --git a/actionpack/lib/action_view/helpers/cache_helper.rb b/actionpack/lib/action_view/helpers/cache_helper.rb index 930c397785..2cdbae6e40 100644 --- a/actionpack/lib/action_view/helpers/cache_helper.rb +++ b/actionpack/lib/action_view/helpers/cache_helper.rb @@ -32,8 +32,7 @@ module ActionView # Topics listed alphabetically # <% end %> def cache(name = {}, options = nil, &block) - handler = Template.handler_class_for_extension(current_render_extension.to_sym) - handler.new(@controller).cache_fragment(block, name, options) + _last_render.handler.new(@controller).cache_fragment(block, name, options) end end end diff --git a/actionpack/lib/action_view/renderable.rb b/actionpack/lib/action_view/renderable.rb index 2c4302146f..ebb0f1b674 100644 --- a/actionpack/lib/action_view/renderable.rb +++ b/actionpack/lib/action_view/renderable.rb @@ -18,9 +18,9 @@ module ActionView end def render(view, local_assigns = {}) - view.first_render ||= self + view._first_render ||= self + view._last_render = self view.send(:evaluate_assigns) - view.current_render_extension = extension compile(local_assigns) if handler.compilable? handler.new(view).render(self, local_assigns) end -- cgit v1.2.3 From 26bc867151a8f302b4c6122e6375c3ea2088a037 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 13 Jul 2008 14:00:40 -0500 Subject: Small tweak to e0fef66 --- actionpack/lib/action_controller/assertions/response_assertions.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/assertions/response_assertions.rb b/actionpack/lib/action_controller/assertions/response_assertions.rb index a98c70d66f..765225ae24 100644 --- a/actionpack/lib/action_controller/assertions/response_assertions.rb +++ b/actionpack/lib/action_controller/assertions/response_assertions.rb @@ -87,13 +87,13 @@ module ActionController # def assert_template(expected = nil, message=nil) clean_backtrace do - rendered = @response.rendered_template.to_s + rendered = @response.rendered_template msg = build_message(message, "expecting but rendering with ", expected, rendered) assert_block(msg) do if expected.nil? - @response.rendered_template ? true : false + @response.rendered_template.nil? else - rendered.match(expected) + rendered.to_s.match(expected) end end end -- cgit v1.2.3 From 68fe898189a27e4e3c4c2fe005c99975d40e1dd7 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 13 Jul 2008 14:05:21 -0500 Subject: Check first render format and extension. Fixes failing ActionMailer test. --- actionpack/lib/action_view/base.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 9f244d7250..04e8d3a358 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -313,7 +313,7 @@ module ActionView #:nodoc: template elsif template = self.view_paths[template_file_name] template - elsif _first_render && template = self.view_paths["#{template_file_name}.#{_first_render.extension}"] + elsif _first_render && template = self.view_paths["#{template_file_name}.#{_first_render.format_and_extension}"] template elsif template_format == :js && template = self.view_paths["#{template_file_name}.html"] @template_format = :html -- cgit v1.2.3 From 95812d5eafc3b63ce5eeb0748a5d0132f5108b64 Mon Sep 17 00:00:00 2001 From: rsl Date: Mon, 14 Jul 2008 00:55:57 +0100 Subject: Ensure :index works with fields_for select methods. [#518 state:resolved] Signed-off-by: Pratik Naik --- actionpack/lib/action_view/helpers/form_options_helper.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb index ab9e174621..87d49397c6 100644 --- a/actionpack/lib/action_view/helpers/form_options_helper.rb +++ b/actionpack/lib/action_view/helpers/form_options_helper.rb @@ -445,19 +445,19 @@ module ActionView class FormBuilder def select(method, choices, options = {}, html_options = {}) - @template.select(@object_name, method, choices, options.merge(:object => @object), html_options) + @template.select(@object_name, method, choices, objectify_options(options), @default_options.merge(html_options)) end def collection_select(method, collection, value_method, text_method, options = {}, html_options = {}) - @template.collection_select(@object_name, method, collection, value_method, text_method, options.merge(:object => @object), html_options) + @template.collection_select(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_options.merge(html_options)) end def country_select(method, priority_countries = nil, options = {}, html_options = {}) - @template.country_select(@object_name, method, priority_countries, options.merge(:object => @object), html_options) + @template.country_select(@object_name, method, priority_countries, objectify_options(options), @default_options.merge(html_options)) end def time_zone_select(method, priority_zones = nil, options = {}, html_options = {}) - @template.time_zone_select(@object_name, method, priority_zones, options.merge(:object => @object), html_options) + @template.time_zone_select(@object_name, method, priority_zones, objectify_options(options), @default_options.merge(html_options)) end end end -- cgit v1.2.3 From 2167f95d857224b88901c5fb4cda63c2e0756676 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Wed, 9 Jul 2008 12:38:59 -0700 Subject: Restore the more readable before_ and after_filters methods since they aren't called frequently --- actionpack/lib/action_controller/filters.rb | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/filters.rb b/actionpack/lib/action_controller/filters.rb index fc63890d13..10dc0cc45b 100644 --- a/actionpack/lib/action_controller/filters.rb +++ b/actionpack/lib/action_controller/filters.rb @@ -569,21 +569,13 @@ module ActionController #:nodoc: # Returns all the before filters for this class and all its ancestors. # This method returns the actual filter that was assigned in the controller to maintain existing functionality. def before_filters #:nodoc: - filters = [] - filter_chain.each do |filter| - filters << filter.method if filter.before? - end - filters + filter_chain.select(&:before?).map(&:method) end # Returns all the after filters for this class and all its ancestors. # This method returns the actual filter that was assigned in the controller to maintain existing functionality. def after_filters #:nodoc: - filters = [] - filter_chain.each do |filter| - filters << filter.method if filter.after? - end - filters + filter_chain.select(&:after?).map(&:method) end end -- cgit v1.2.3 From 425de8db6adf13f21242bdd9adcb931bb836ad8b Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Wed, 9 Jul 2008 13:30:53 -0700 Subject: Use instance_method(...) to check whether the method exists --- .../action_view/template_handlers/compilable.rb | 46 +++++++++++++++++++++- 1 file changed, 44 insertions(+), 2 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/template_handlers/compilable.rb b/actionpack/lib/action_view/template_handlers/compilable.rb index a0ebaefeef..2a19fc7628 100644 --- a/actionpack/lib/action_view/template_handlers/compilable.rb +++ b/actionpack/lib/action_view/template_handlers/compilable.rb @@ -12,9 +12,51 @@ module ActionView end end - def render(template, local_assigns = {}) - @view.send(:execute, template, local_assigns) + def render(template) + @view.send(:execute, template) end + + # Compile and evaluate the template's code + def compile_template(template) + return false unless recompile_template?(template) + + @@mutex.synchronize do + locals_code = template.locals.keys.map { |key| "#{key} = local_assigns[:#{key}];" }.join + + source = <<-end_src + def #{template.method}(local_assigns) + old_output_buffer = output_buffer;#{locals_code};#{compile(template)} + ensure + self.output_buffer = old_output_buffer + end + end_src + + begin + file_name = template.filename || 'compiled-template' + ActionView::Base::CompiledTemplates.module_eval(source, file_name, 0) + rescue Exception => e # errors from template code + if logger = ActionController::Base.logger + logger.debug "ERROR: compiling #{template.method} RAISED #{e}" + logger.debug "Function body: #{source}" + logger.debug "Backtrace: #{e.backtrace.join("\n")}" + end + + raise ActionView::TemplateError.new(template, @view.assigns, e) + end + end + end + + private + # Method to check whether template compilation is necessary. + # The template will be compiled if the inline template or file has not been compiled yet, + # if local_assigns has a new key, which isn't supported by the compiled code yet. + def recompile_template?(template) + # Unless the template has been compiled yet, compile + # If template caching is disabled, compile + # Always recompile inline templates + meth = Base::CompiledTemplates.instance_method(template.method) rescue nil + !meth || !Base.cache_template_loading || template.is_a?(InlineTemplate) + end end end end -- cgit v1.2.3 From 4e323f6ef09fed146a9302d7b7e3f09934de6e37 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Mon, 14 Jul 2008 11:50:07 -0700 Subject: Fix bad merge --- actionpack/lib/action_view/template_handlers/compilable.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/template_handlers/compilable.rb b/actionpack/lib/action_view/template_handlers/compilable.rb index 2a19fc7628..2b96e7f133 100644 --- a/actionpack/lib/action_view/template_handlers/compilable.rb +++ b/actionpack/lib/action_view/template_handlers/compilable.rb @@ -12,8 +12,8 @@ module ActionView end end - def render(template) - @view.send(:execute, template) + def render(template, local_assigns = {}) + @view.send(:execute, template, local_assigns) end # Compile and evaluate the template's code -- cgit v1.2.3 From 3fbefecc9cdc0d1a903d6ab76170223166cc69ab Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Mon, 14 Jul 2008 13:47:51 -0700 Subject: Remove dead code from merge --- .../action_view/template_handlers/compilable.rb | 30 ---------------------- 1 file changed, 30 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/template_handlers/compilable.rb b/actionpack/lib/action_view/template_handlers/compilable.rb index 2b96e7f133..7e45761481 100644 --- a/actionpack/lib/action_view/template_handlers/compilable.rb +++ b/actionpack/lib/action_view/template_handlers/compilable.rb @@ -16,36 +16,6 @@ module ActionView @view.send(:execute, template, local_assigns) end - # Compile and evaluate the template's code - def compile_template(template) - return false unless recompile_template?(template) - - @@mutex.synchronize do - locals_code = template.locals.keys.map { |key| "#{key} = local_assigns[:#{key}];" }.join - - source = <<-end_src - def #{template.method}(local_assigns) - old_output_buffer = output_buffer;#{locals_code};#{compile(template)} - ensure - self.output_buffer = old_output_buffer - end - end_src - - begin - file_name = template.filename || 'compiled-template' - ActionView::Base::CompiledTemplates.module_eval(source, file_name, 0) - rescue Exception => e # errors from template code - if logger = ActionController::Base.logger - logger.debug "ERROR: compiling #{template.method} RAISED #{e}" - logger.debug "Function body: #{source}" - logger.debug "Backtrace: #{e.backtrace.join("\n")}" - end - - raise ActionView::TemplateError.new(template, @view.assigns, e) - end - end - end - private # Method to check whether template compilation is necessary. # The template will be compiled if the inline template or file has not been compiled yet, -- cgit v1.2.3 From 2d6562d51b96af518c1eb2947d6d34d5dd5bad12 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Mon, 14 Jul 2008 13:51:59 -0700 Subject: Move dead recompile_template? also --- actionpack/lib/action_view/renderable.rb | 7 ++----- actionpack/lib/action_view/template_handlers/compilable.rb | 12 ------------ 2 files changed, 2 insertions(+), 17 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/renderable.rb b/actionpack/lib/action_view/renderable.rb index ebb0f1b674..ffcffd1667 100644 --- a/actionpack/lib/action_view/renderable.rb +++ b/actionpack/lib/action_view/renderable.rb @@ -69,11 +69,8 @@ module ActionView # The template will be compiled if the file has not been compiled yet, or # if local_assigns has a new key, which isn't supported by the compiled code yet. def recompile?(symbol) - unless Base::CompiledTemplates.instance_methods.include?(symbol) && Base.cache_template_loading - true - else - false - end + meth = Base::CompiledTemplates.instance_method(template.method) rescue nil + !(meth && Base.cache_template_loading) end end end diff --git a/actionpack/lib/action_view/template_handlers/compilable.rb b/actionpack/lib/action_view/template_handlers/compilable.rb index 7e45761481..a0ebaefeef 100644 --- a/actionpack/lib/action_view/template_handlers/compilable.rb +++ b/actionpack/lib/action_view/template_handlers/compilable.rb @@ -15,18 +15,6 @@ module ActionView def render(template, local_assigns = {}) @view.send(:execute, template, local_assigns) end - - private - # Method to check whether template compilation is necessary. - # The template will be compiled if the inline template or file has not been compiled yet, - # if local_assigns has a new key, which isn't supported by the compiled code yet. - def recompile_template?(template) - # Unless the template has been compiled yet, compile - # If template caching is disabled, compile - # Always recompile inline templates - meth = Base::CompiledTemplates.instance_method(template.method) rescue nil - !meth || !Base.cache_template_loading || template.is_a?(InlineTemplate) - end end end end -- cgit v1.2.3 From 9dc258d6147c8dab772d1f041098a38389cd3e73 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 14 Jul 2008 17:40:03 -0500 Subject: Eager load Partial variable_name and counter_name. Tidy up render_partial_collection. --- actionpack/lib/action_view/partials.rb | 33 +++++++----------------- actionpack/lib/action_view/renderable.rb | 9 +++++-- actionpack/lib/action_view/renderable_partial.rb | 28 +++++++++++++++++--- actionpack/lib/action_view/template.rb | 24 +++++++---------- 4 files changed, 49 insertions(+), 45 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/partials.rb b/actionpack/lib/action_view/partials.rb index 116d61e13b..5aa4c83009 100644 --- a/actionpack/lib/action_view/partials.rb +++ b/actionpack/lib/action_view/partials.rb @@ -108,8 +108,7 @@ module ActionView case partial_path when String, Symbol, NilClass - variable_name, path = partial_pieces(partial_path) - pick_template(path).render_partial(self, variable_name, object_assigns, local_assigns) + pick_template(find_partial_path(partial_path)).render_partial(self, object_assigns, local_assigns) when ActionView::Helpers::FormBuilder builder_partial_path = partial_path.class.to_s.demodulize.underscore.sub(/_builder$/, '') render_partial(builder_partial_path, object_assigns, (local_assigns || {}).merge(builder_partial_path.to_sym => partial_path)) @@ -130,43 +129,29 @@ module ActionView local_assigns = local_assigns ? local_assigns.clone : {} spacer = partial_spacer_template ? render(:partial => partial_spacer_template) : '' - _partial_pieces = {} + _paths = {} _templates = {} index = 0 collection.map do |object| _partial_path ||= partial_path || ActionController::RecordIdentifier.partial_path(object, controller.class.controller_path) - variable_name, path = _partial_pieces[_partial_path] ||= partial_pieces(_partial_path) + path = _paths[_partial_path] ||= find_partial_path(_partial_path) template = _templates[path] ||= pick_template(path) - - local_assigns["#{variable_name}_counter".to_sym] = index - local_assigns[:object] = local_assigns[variable_name] = object - local_assigns[as] = object if as - - result = template.render_partial(self, variable_name, object, local_assigns) - - local_assigns.delete(as) - local_assigns.delete(variable_name) - local_assigns.delete(:object) + local_assigns[template.counter_name] = index + result = template.render_partial(self, object, local_assigns, as) index += 1 - result end.join(spacer) end - def partial_pieces(partial_path) + def find_partial_path(partial_path) if partial_path.include?('/') - variable_name = File.basename(partial_path) - path = "#{File.dirname(partial_path)}/_#{variable_name}" + "#{File.dirname(partial_path)}/_#{File.basename(partial_path)}" elsif respond_to?(:controller) - variable_name = partial_path - path = "#{controller.class.controller_path}/_#{variable_name}" + "#{controller.class.controller_path}/_#{partial_path}" else - variable_name = partial_path - path = "_#{variable_name}" + "_#{partial_path}" end - variable_name = variable_name.sub(/\..*$/, '').to_sym - return variable_name, path end end end diff --git a/actionpack/lib/action_view/renderable.rb b/actionpack/lib/action_view/renderable.rb index ffcffd1667..4fda408367 100644 --- a/actionpack/lib/action_view/renderable.rb +++ b/actionpack/lib/action_view/renderable.rb @@ -7,16 +7,21 @@ module ActionView @@mutex = Mutex.new end - # NOTE: Exception to earlier notice. Ensure this is called before freeze def handler @handler ||= Template.handler_class_for_extension(extension) end - # NOTE: Exception to earlier notice. Ensure this is called before freeze def compiled_source @compiled_source ||= handler.new(nil).compile(self) if handler.compilable? end + def freeze + # Eager load and freeze memoized methods + handler.freeze + compiled_source.freeze + super + end + def render(view, local_assigns = {}) view._first_render ||= self view._last_render = self diff --git a/actionpack/lib/action_view/renderable_partial.rb b/actionpack/lib/action_view/renderable_partial.rb index 6a17b50a14..250b4e1624 100644 --- a/actionpack/lib/action_view/renderable_partial.rb +++ b/actionpack/lib/action_view/renderable_partial.rb @@ -3,16 +3,36 @@ module ActionView # NOTE: The template that this mixin is beening include into is frozen # So you can not set or modify any instance variables + def variable_name + @variable_name ||= name.gsub(/^_/, '').to_sym + end + + def counter_name + @counter_name ||= "#{variable_name}_counter".to_sym + end + + def freeze + # Eager load and freeze memoized methods + variable_name.freeze + counter_name.freeze + super + end + def render(view, local_assigns = {}) ActionController::Base.benchmark("Rendered #{path_without_format_and_extension}", Logger::DEBUG, false) do super end end - def render_partial(view, variable_name, object = nil, local_assigns = {}, as = nil) - object ||= view.controller.instance_variable_get("@#{variable_name}") if view.respond_to?(:controller) - local_assigns[:object] ||= local_assigns[variable_name] ||= object - local_assigns[as] ||= local_assigns[:object] if as + def render_partial(view, object = nil, local_assigns = {}, as = nil) + object ||= local_assigns[:object] || + local_assigns[variable_name] || + view.controller.instance_variable_get("@#{variable_name}") if view.respond_to?(:controller) + + # Ensure correct object is reassigned to other accessors + local_assigns[:object] = local_assigns[variable_name] = object + local_assigns[as] = object if as + render_template(view, local_assigns) end end diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 03f9234289..42659efbd4 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -17,19 +17,13 @@ module ActionView #:nodoc: end def freeze - # Eager load memoized methods - format_and_extension - path - path_without_extension - path_without_format_and_extension - source - method_segment - - # Eager load memoized methods from Renderable - handler - compiled_source - - instance_variables.each { |ivar| ivar.freeze } + # Eager load and freeze memoized methods + format_and_extension.freeze + path.freeze + path_without_extension.freeze + path_without_format_and_extension.freeze + source.freeze + method_segment.freeze super end @@ -51,12 +45,12 @@ module ActionView #:nodoc: end def source - @source ||= File.read(@filename) + @source ||= File.read(filename) end def method_segment unless @method_segment - segment = File.expand_path(@filename) + segment = File.expand_path(filename) segment.sub!(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}/, '') if defined?(RAILS_ROOT) segment.gsub!(/([^a-zA-Z0-9_])/) { $1.ord } @method_segment = segment -- cgit v1.2.3 From d27dd860c7f4f9b9e5aebe7d0c6e9b6108d8717c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tarmo=20T=C3=A4nav?= Date: Mon, 14 Jul 2008 18:02:59 -0500 Subject: Use sub instead of gsub Signed-off-by: Joshua Peek --- actionpack/lib/action_view/renderable_partial.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/renderable_partial.rb b/actionpack/lib/action_view/renderable_partial.rb index 250b4e1624..7b51eccc27 100644 --- a/actionpack/lib/action_view/renderable_partial.rb +++ b/actionpack/lib/action_view/renderable_partial.rb @@ -4,7 +4,7 @@ module ActionView # So you can not set or modify any instance variables def variable_name - @variable_name ||= name.gsub(/^_/, '').to_sym + @variable_name ||= name.sub(/\A_/, '').to_sym end def counter_name -- cgit v1.2.3 From dd41f66af577947ad420fbd2a44184344ad5c983 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 14 Jul 2008 19:51:43 -0500 Subject: Include Memoizable in ActionView::Template --- actionpack/lib/action_view/renderable.rb | 15 ++++----- actionpack/lib/action_view/renderable_partial.rb | 15 ++++----- actionpack/lib/action_view/template.rb | 40 +++++++++--------------- 3 files changed, 27 insertions(+), 43 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/renderable.rb b/actionpack/lib/action_view/renderable.rb index 4fda408367..9185045adf 100644 --- a/actionpack/lib/action_view/renderable.rb +++ b/actionpack/lib/action_view/renderable.rb @@ -7,20 +7,17 @@ module ActionView @@mutex = Mutex.new end + include ActiveSupport::Memoizable + def handler - @handler ||= Template.handler_class_for_extension(extension) + Template.handler_class_for_extension(extension) end + memorize :handler def compiled_source - @compiled_source ||= handler.new(nil).compile(self) if handler.compilable? - end - - def freeze - # Eager load and freeze memoized methods - handler.freeze - compiled_source.freeze - super + handler.new(nil).compile(self) if handler.compilable? end + memorize :compiled_source def render(view, local_assigns = {}) view._first_render ||= self diff --git a/actionpack/lib/action_view/renderable_partial.rb b/actionpack/lib/action_view/renderable_partial.rb index 7b51eccc27..d2fe635b9c 100644 --- a/actionpack/lib/action_view/renderable_partial.rb +++ b/actionpack/lib/action_view/renderable_partial.rb @@ -3,20 +3,17 @@ module ActionView # NOTE: The template that this mixin is beening include into is frozen # So you can not set or modify any instance variables + include ActiveSupport::Memoizable + def variable_name - @variable_name ||= name.sub(/\A_/, '').to_sym + name.sub(/\A_/, '').to_sym end + memorize :variable_name def counter_name - @counter_name ||= "#{variable_name}_counter".to_sym - end - - def freeze - # Eager load and freeze memoized methods - variable_name.freeze - counter_name.freeze - super + "#{variable_name}_counter".to_sym end + memorize :counter_name def render(view, local_assigns = {}) ActionController::Base.benchmark("Rendered #{path_without_format_and_extension}", Logger::DEBUG, false) do diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 42659efbd4..b39ba0c48b 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -1,6 +1,7 @@ module ActionView #:nodoc: class Template extend TemplateHandlers + include ActiveSupport::Memoizable include Renderable attr_accessor :filename, :load_path, :base_path, :name, :format, :extension @@ -16,48 +17,37 @@ module ActionView #:nodoc: extend RenderablePartial if @name =~ /^_/ end - def freeze - # Eager load and freeze memoized methods - format_and_extension.freeze - path.freeze - path_without_extension.freeze - path_without_format_and_extension.freeze - source.freeze - method_segment.freeze - - super - end - def format_and_extension - @format_and_extension ||= (extensions = [format, extension].compact.join(".")).blank? ? nil : extensions + (extensions = [format, extension].compact.join(".")).blank? ? nil : extensions end + memorize :format_and_extension def path - @path ||= [base_path, [name, format, extension].compact.join('.')].compact.join('/') + [base_path, [name, format, extension].compact.join('.')].compact.join('/') end + memorize :path def path_without_extension - @path_without_extension ||= [base_path, [name, format].compact.join('.')].compact.join('/') + [base_path, [name, format].compact.join('.')].compact.join('/') end + memorize :path_without_extension def path_without_format_and_extension - @path_without_format_and_extension ||= [base_path, name].compact.join('/') + [base_path, name].compact.join('/') end + memorize :path_without_format_and_extension def source - @source ||= File.read(filename) + File.read(filename) end + memorize :source def method_segment - unless @method_segment - segment = File.expand_path(filename) - segment.sub!(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}/, '') if defined?(RAILS_ROOT) - segment.gsub!(/([^a-zA-Z0-9_])/) { $1.ord } - @method_segment = segment - end - - @method_segment + segment = File.expand_path(filename) + segment.sub!(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}/, '') if defined?(RAILS_ROOT) + segment.gsub!(/([^a-zA-Z0-9_])/) { $1.ord } end + memorize :method_segment def render_template(view, local_assigns = {}) render(view, local_assigns) -- cgit v1.2.3 From 001c8beb4d0999a858a8b52ad511ee1251cc3517 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 14 Jul 2008 20:02:59 -0500 Subject: memorize typo --- actionpack/lib/action_view/renderable.rb | 4 ++-- actionpack/lib/action_view/renderable_partial.rb | 4 ++-- actionpack/lib/action_view/template.rb | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/renderable.rb b/actionpack/lib/action_view/renderable.rb index 9185045adf..f66356c939 100644 --- a/actionpack/lib/action_view/renderable.rb +++ b/actionpack/lib/action_view/renderable.rb @@ -12,12 +12,12 @@ module ActionView def handler Template.handler_class_for_extension(extension) end - memorize :handler + memoize :handler def compiled_source handler.new(nil).compile(self) if handler.compilable? end - memorize :compiled_source + memoize :compiled_source def render(view, local_assigns = {}) view._first_render ||= self diff --git a/actionpack/lib/action_view/renderable_partial.rb b/actionpack/lib/action_view/renderable_partial.rb index d2fe635b9c..fdb1a5e6a7 100644 --- a/actionpack/lib/action_view/renderable_partial.rb +++ b/actionpack/lib/action_view/renderable_partial.rb @@ -8,12 +8,12 @@ module ActionView def variable_name name.sub(/\A_/, '').to_sym end - memorize :variable_name + memoize :variable_name def counter_name "#{variable_name}_counter".to_sym end - memorize :counter_name + memoize :counter_name def render(view, local_assigns = {}) ActionController::Base.benchmark("Rendered #{path_without_format_and_extension}", Logger::DEBUG, false) do diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index b39ba0c48b..304aec3a4c 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -20,34 +20,34 @@ module ActionView #:nodoc: def format_and_extension (extensions = [format, extension].compact.join(".")).blank? ? nil : extensions end - memorize :format_and_extension + memoize :format_and_extension def path [base_path, [name, format, extension].compact.join('.')].compact.join('/') end - memorize :path + memoize :path def path_without_extension [base_path, [name, format].compact.join('.')].compact.join('/') end - memorize :path_without_extension + memoize :path_without_extension def path_without_format_and_extension [base_path, name].compact.join('/') end - memorize :path_without_format_and_extension + memoize :path_without_format_and_extension def source File.read(filename) end - memorize :source + memoize :source def method_segment segment = File.expand_path(filename) segment.sub!(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}/, '') if defined?(RAILS_ROOT) segment.gsub!(/([^a-zA-Z0-9_])/) { $1.ord } end - memorize :method_segment + memoize :method_segment def render_template(view, local_assigns = {}) render(view, local_assigns) -- cgit v1.2.3 From bb33432b0f5bf644713e696e4dafc7e7d3cc5808 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=BE=E7=94=B0=20=E6=98=8E?= Date: Tue, 15 Jul 2008 21:30:20 +0900 Subject: Ruby 1.9 compat: call Proc#binding explicitly. [#623 state:resolved] --- actionpack/lib/action_view/helpers/tag_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/tag_helper.rb b/actionpack/lib/action_view/helpers/tag_helper.rb index aeafd3906d..e9b6dd6e43 100644 --- a/actionpack/lib/action_view/helpers/tag_helper.rb +++ b/actionpack/lib/action_view/helpers/tag_helper.rb @@ -115,7 +115,7 @@ module ActionView # can't take an <% end %> later on, so we have to use <% ... %> # and implicitly concat. def block_called_from_erb?(block) - block && eval(BLOCK_CALLED_FROM_ERB, block) + block && eval(BLOCK_CALLED_FROM_ERB, block.binding) end def content_tag_string(name, content, options, escape = true) -- cgit v1.2.3 From 3c282f3a0a7c1d5ab91241674251794ead5fa41d Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Tue, 15 Jul 2008 10:42:50 -0700 Subject: Ruby 1.9 compat: only eval with block.binding in 1.9, uses more memory than eval with block --- actionpack/lib/action_view/helpers/tag_helper.rb | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/helpers/tag_helper.rb b/actionpack/lib/action_view/helpers/tag_helper.rb index e9b6dd6e43..5a296da247 100644 --- a/actionpack/lib/action_view/helpers/tag_helper.rb +++ b/actionpack/lib/action_view/helpers/tag_helper.rb @@ -110,12 +110,18 @@ module ActionView private BLOCK_CALLED_FROM_ERB = 'defined? __in_erb_template' - # Check whether we're called from an erb template. - # We'd return a string in any other case, but erb <%= ... %> - # can't take an <% end %> later on, so we have to use <% ... %> - # and implicitly concat. - def block_called_from_erb?(block) - block && eval(BLOCK_CALLED_FROM_ERB, block.binding) + if RUBY_VERSION < '1.9.0' + # Check whether we're called from an erb template. + # We'd return a string in any other case, but erb <%= ... %> + # can't take an <% end %> later on, so we have to use <% ... %> + # and implicitly concat. + def block_called_from_erb?(block) + block && eval(BLOCK_CALLED_FROM_ERB, block) + end + else + def block_called_from_erb?(block) + block && eval(BLOCK_CALLED_FROM_ERB, block.binding) + end end def content_tag_string(name, content, options, escape = true) -- cgit v1.2.3 From aca246ab25497bb6787d2e18680e9f73ad13d223 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 15 Jul 2008 14:41:38 -0500 Subject: Get buffer for fragment cache from template's @output_buffer --- .../lib/action_controller/caching/fragments.rb | 4 +- actionpack/lib/action_view/helpers/cache_helper.rb | 2 +- .../lib/action_view/helpers/prototype_helper.rb | 375 +++++++++++---------- actionpack/lib/action_view/template_handler.rb | 4 - .../lib/action_view/template_handlers/builder.rb | 7 +- .../lib/action_view/template_handlers/erb.rb | 6 - .../lib/action_view/template_handlers/rjs.rb | 11 - 7 files changed, 191 insertions(+), 218 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_controller/caching/fragments.rb b/actionpack/lib/action_controller/caching/fragments.rb index 57b31ec9d1..b1f25fdf5c 100644 --- a/actionpack/lib/action_controller/caching/fragments.rb +++ b/actionpack/lib/action_controller/caching/fragments.rb @@ -60,10 +60,8 @@ module ActionController #:nodoc: ActiveSupport::Cache.expand_cache_key(key.is_a?(Hash) ? url_for(key).split("://").last : key, :views) end - def fragment_for(block, name = {}, options = nil) #:nodoc: + def fragment_for(buffer, name = {}, options = nil, &block) #:nodoc: if perform_caching - buffer = yield - if cache = read_fragment(name, options) buffer.concat(cache) else diff --git a/actionpack/lib/action_view/helpers/cache_helper.rb b/actionpack/lib/action_view/helpers/cache_helper.rb index 2cdbae6e40..64d1ad2715 100644 --- a/actionpack/lib/action_view/helpers/cache_helper.rb +++ b/actionpack/lib/action_view/helpers/cache_helper.rb @@ -32,7 +32,7 @@ module ActionView # Topics listed alphabetically # <% end %> def cache(name = {}, options = nil, &block) - _last_render.handler.new(@controller).cache_fragment(block, name, options) + @controller.fragment_for(output_buffer, name, options, &block) end end end diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb index d0c281c803..edb43844a4 100644 --- a/actionpack/lib/action_view/helpers/prototype_helper.rb +++ b/actionpack/lib/action_view/helpers/prototype_helper.rb @@ -3,25 +3,25 @@ require 'set' module ActionView module Helpers # Prototype[http://www.prototypejs.org/] is a JavaScript library that provides - # DOM[http://en.wikipedia.org/wiki/Document_Object_Model] manipulation, + # DOM[http://en.wikipedia.org/wiki/Document_Object_Model] manipulation, # Ajax[http://www.adaptivepath.com/publications/essays/archives/000385.php] - # functionality, and more traditional object-oriented facilities for JavaScript. + # functionality, and more traditional object-oriented facilities for JavaScript. # This module provides a set of helpers to make it more convenient to call - # functions from Prototype using Rails, including functionality to call remote - # Rails methods (that is, making a background request to a Rails action) using Ajax. - # This means that you can call actions in your controllers without - # reloading the page, but still update certain parts of it using + # functions from Prototype using Rails, including functionality to call remote + # Rails methods (that is, making a background request to a Rails action) using Ajax. + # This means that you can call actions in your controllers without + # reloading the page, but still update certain parts of it using # injections into the DOM. A common use case is having a form that adds # a new element to a list without reloading the page or updating a shopping # cart total when a new item is added. # # == Usage - # To be able to use these helpers, you must first include the Prototype - # JavaScript framework in your pages. + # To be able to use these helpers, you must first include the Prototype + # JavaScript framework in your pages. # # javascript_include_tag 'prototype' # - # (See the documentation for + # (See the documentation for # ActionView::Helpers::JavaScriptHelper for more information on including # this and other JavaScript files in your Rails templates.) # @@ -29,7 +29,7 @@ module ActionView # # link_to_remote "Add to cart", # :url => { :action => "add", :id => product.id }, - # :update => { :success => "cart", :failure => "error" } + # :update => { :success => "cart", :failure => "error" } # # ...through a form... # @@ -50,8 +50,8 @@ module ActionView # :update => :hits, # :with => 'query' # %> - # - # As you can see, there are numerous ways to use Prototype's Ajax functions (and actually more than + # + # As you can see, there are numerous ways to use Prototype's Ajax functions (and actually more than # are listed here); check out the documentation for each method to find out more about its usage and options. # # === Common Options @@ -63,7 +63,7 @@ module ActionView # When building your action handlers (that is, the Rails actions that receive your background requests), it's # important to remember a few things. First, whatever your action would normall return to the browser, it will # return to the Ajax call. As such, you typically don't want to render with a layout. This call will cause - # the layout to be transmitted back to your page, and, if you have a full HTML/CSS, will likely mess a lot of things up. + # the layout to be transmitted back to your page, and, if you have a full HTML/CSS, will likely mess a lot of things up. # You can turn the layout off on particular actions by doing the following: # # class SiteController < ActionController::Base @@ -74,8 +74,8 @@ module ActionView # # render :layout => false # - # You can tell the type of request from within your action using the request.xhr? (XmlHttpRequest, the - # method that Ajax uses to make background requests) method. + # You can tell the type of request from within your action using the request.xhr? (XmlHttpRequest, the + # method that Ajax uses to make background requests) method. # def name # # Is this an XmlHttpRequest request? # if (request.xhr?) @@ -93,7 +93,7 @@ module ActionView # # Dropping this in your ApplicationController turns the layout off for every request that is an "xhr" request. # - # If you are just returning a little data or don't want to build a template for your output, you may opt to simply + # If you are just returning a little data or don't want to build a template for your output, you may opt to simply # render text output, like this: # # render :text => 'Return this from my method!' @@ -103,7 +103,7 @@ module ActionView # # == Updating multiple elements # See JavaScriptGenerator for information on updating multiple elements - # on the page in an Ajax response. + # on the page in an Ajax response. module PrototypeHelper unless const_defined? :CALLBACKS CALLBACKS = Set.new([ :uninitialized, :loading, :loaded, @@ -114,64 +114,64 @@ module ActionView :form, :with, :update, :script ]).merge(CALLBACKS) end - # Returns a link to a remote action defined by options[:url] - # (using the url_for format) that's called in the background using + # Returns a link to a remote action defined by options[:url] + # (using the url_for format) that's called in the background using # XMLHttpRequest. The result of that request can then be inserted into a - # DOM object whose id can be specified with options[:update]. + # DOM object whose id can be specified with options[:update]. # Usually, the result would be a partial prepared by the controller with - # render :partial. + # render :partial. # # Examples: - # # Generates: Delete this post - # link_to_remote "Delete this post", :update => "posts", + # link_to_remote "Delete this post", :update => "posts", # :url => { :action => "destroy", :id => post.id } # - # # Generates: Refresh - # link_to_remote(image_tag("refresh"), :update => "emails", + # link_to_remote(image_tag("refresh"), :update => "emails", # :url => { :action => "list_emails" }) - # + # # You can override the generated HTML options by specifying a hash in # options[:html]. - # + # # link_to_remote "Delete this post", :update => "posts", - # :url => post_url(@post), :method => :delete, - # :html => { :class => "destructive" } + # :url => post_url(@post), :method => :delete, + # :html => { :class => "destructive" } # # You can also specify a hash for options[:update] to allow for - # easy redirection of output to an other DOM element if a server-side + # easy redirection of output to an other DOM element if a server-side # error occurs: # # Example: - # # Generates: Delete this post # link_to_remote "Delete this post", # :url => { :action => "destroy", :id => post.id }, # :update => { :success => "posts", :failure => "error" } # - # Optionally, you can use the options[:position] parameter to - # influence how the target DOM element is updated. It must be one of + # Optionally, you can use the options[:position] parameter to + # influence how the target DOM element is updated. It must be one of # :before, :top, :bottom, or :after. # # The method used is by default POST. You can also specify GET or you # can simulate PUT or DELETE over POST. All specified with options[:method] # # Example: - # # Generates: Destroy # link_to_remote "Destroy", :url => person_url(:id => person), :method => :delete # - # By default, these remote requests are processed asynchronous during - # which various JavaScript callbacks can be triggered (for progress - # indicators and the likes). All callbacks get access to the - # request object, which holds the underlying XMLHttpRequest. + # By default, these remote requests are processed asynchronous during + # which various JavaScript callbacks can be triggered (for progress + # indicators and the likes). All callbacks get access to the + # request object, which holds the underlying XMLHttpRequest. # # To access the server response, use request.responseText, to # find out the HTTP status, use request.status. # # Example: - # # Generates: hello # word = 'hello' # link_to_remote word, @@ -180,43 +180,43 @@ module ActionView # # The callbacks that may be specified are (in order): # - # :loading:: Called when the remote document is being + # :loading:: Called when the remote document is being # loaded with data by the browser. # :loaded:: Called when the browser has finished loading # the remote document. - # :interactive:: Called when the user can interact with the - # remote document, even though it has not + # :interactive:: Called when the user can interact with the + # remote document, even though it has not # finished loading. # :success:: Called when the XMLHttpRequest is completed, # and the HTTP status code is in the 2XX range. # :failure:: Called when the XMLHttpRequest is completed, # and the HTTP status code is not in the 2XX # range. - # :complete:: Called when the XMLHttpRequest is complete - # (fires after success/failure if they are + # :complete:: Called when the XMLHttpRequest is complete + # (fires after success/failure if they are # present). - # - # You can further refine :success and :failure by + # + # You can further refine :success and :failure by # adding additional callbacks for specific status codes. # # Example: - # # Generates: hello # link_to_remote word, # :url => { :action => "action" }, # 404 => "alert('Not found...? Wrong URL...?')", # :failure => "alert('HTTP Error ' + request.status + '!')" # - # A status code callback overrides the success/failure handlers if + # A status code callback overrides the success/failure handlers if # present. # # If you for some reason or another need synchronous processing (that'll - # block the browser while the request is happening), you can specify + # block the browser while the request is happening), you can specify # options[:type] = :synchronous. # # You can customize further browser side call logic by passing in - # JavaScript code snippets via some optional parameters. In their order + # JavaScript code snippets via some optional parameters. In their order # of use these are: # # :confirm:: Adds confirmation dialog. @@ -228,7 +228,7 @@ module ActionView # :after:: Called immediately after request was # initiated and before :loading. # :submit:: Specifies the DOM element ID that's used - # as the parent of the form elements. By + # as the parent of the form elements. By # default this is the current form, but # it could just as well be the ID of a # table row or any other DOM element. @@ -238,10 +238,10 @@ module ActionView # URL query string. # # Example: - # + # # :with => "'name=' + $('name').value" # - # You can generate a link that uses AJAX in the general case, while + # You can generate a link that uses AJAX in the general case, while # degrading gracefully to plain link behavior in the absence of # JavaScript by setting html_options[:href] to an alternate URL. # Note the extra curly braces around the options hash separate @@ -251,7 +251,7 @@ module ActionView # link_to_remote "Delete this post", # { :update => "posts", :url => { :action => "destroy", :id => post.id } }, # :href => url_for(:action => "destroy", :id => post.id) - def link_to_remote(name, options = {}, html_options = nil) + def link_to_remote(name, options = {}, html_options = nil) link_to_function(name, remote_function(options), html_options || options.delete(:html)) end @@ -262,15 +262,15 @@ module ActionView # and defining callbacks is the same as link_to_remote. # Examples: # # Call get_averages and put its results in 'avg' every 10 seconds - # # Generates: - # # new PeriodicalExecuter(function() {new Ajax.Updater('avg', '/grades/get_averages', + # # Generates: + # # new PeriodicalExecuter(function() {new Ajax.Updater('avg', '/grades/get_averages', # # {asynchronous:true, evalScripts:true})}, 10) # periodically_call_remote(:url => { :action => 'get_averages' }, :update => 'avg') # # # Call invoice every 10 seconds with the id of the customer # # If it succeeds, update the invoice DIV; if it fails, update the error DIV # # Generates: - # # new PeriodicalExecuter(function() {new Ajax.Updater({success:'invoice',failure:'error'}, + # # new PeriodicalExecuter(function() {new Ajax.Updater({success:'invoice',failure:'error'}, # # '/testing/invoice/16', {asynchronous:true, evalScripts:true})}, 10) # periodically_call_remote(:url => { :action => 'invoice', :id => customer.id }, # :update => { :success => "invoice", :failure => "error" } @@ -286,11 +286,11 @@ module ActionView javascript_tag(code) end - # Returns a form tag that will submit using XMLHttpRequest in the - # background instead of the regular reloading POST arrangement. Even + # Returns a form tag that will submit using XMLHttpRequest in the + # background instead of the regular reloading POST arrangement. Even # though it's using JavaScript to serialize the form elements, the form # submission will work just like a regular submission as viewed by the - # receiving side (all elements available in params). The options for + # receiving side (all elements available in params). The options for # specifying the target with :url and defining callbacks is the same as # +link_to_remote+. # @@ -299,21 +299,21 @@ module ActionView # # Example: # # Generates: - # # - # form_remote_tag :html => { :action => + # form_remote_tag :html => { :action => # url_for(:controller => "some", :action => "place") } # # The Hash passed to the :html key is equivalent to the options (2nd) # argument in the FormTagHelper.form_tag method. # - # By default the fall-through action is the same as the one specified in + # By default the fall-through action is the same as the one specified in # the :url (and the default method is :post). # # form_remote_tag also takes a block, like form_tag: # # Generates: - # #
# # # <% form_remote_tag :url => '/posts' do -%> @@ -323,19 +323,19 @@ module ActionView options[:form] = true options[:html] ||= {} - options[:html][:onsubmit] = - (options[:html][:onsubmit] ? options[:html][:onsubmit] + "; " : "") + + options[:html][:onsubmit] = + (options[:html][:onsubmit] ? options[:html][:onsubmit] + "; " : "") + "#{remote_function(options)}; return false;" form_tag(options[:html].delete(:action) || url_for(options[:url]), options[:html], &block) end - # Creates a form that will submit using XMLHttpRequest in the background - # instead of the regular reloading POST arrangement and a scope around a + # Creates a form that will submit using XMLHttpRequest in the background + # instead of the regular reloading POST arrangement and a scope around a # specific resource that is used as a base for questioning about - # values for the fields. + # values for the fields. # - # === Resource + # === Resource # # Example: # <% remote_form_for(@post) do |f| %> @@ -348,7 +348,7 @@ module ActionView # ... # <% end %> # - # === Nested Resource + # === Nested Resource # # Example: # <% remote_form_for([@post, @comment]) do |f| %> @@ -387,23 +387,23 @@ module ActionView concat('') end alias_method :form_remote_for, :remote_form_for - + # Returns a button input tag with the element name of +name+ and a value (i.e., display text) of +value+ # that will submit form using XMLHttpRequest in the background instead of a regular POST request that - # reloads the page. + # reloads the page. # # # Create a button that submits to the create action - # # - # # Generates: # <%= button_to_remote 'create_btn', 'Create', :url => { :action => 'create' } %> # # # Submit to the remote action update and update the DIV succeed or fail based # # on the success or failure of the request # # - # # Generates: # <%= button_to_remote 'update_btn', 'Update', :url => { :action => 'update' }, # :update => { :success => "succeed", :failure => "fail" } @@ -423,7 +423,7 @@ module ActionView tag("input", options[:html], false) end alias_method :submit_to_remote, :button_to_remote - + # Returns 'eval(request.responseText)' which is the JavaScript function # that +form_remote_tag+ can call in :complete to evaluate a multiple # update return document using +update_element_function+ calls. @@ -433,11 +433,11 @@ module ActionView # Returns the JavaScript needed for a remote function. # Takes the same arguments as link_to_remote. - # + # # Example: - # # Generates: { :action => :update_options }) %>"> # # @@ -455,7 +455,7 @@ module ActionView update << "'#{options[:update]}'" end - function = update.empty? ? + function = update.empty? ? "new Ajax.Request(" : "new Ajax.Updater(#{update}, " @@ -476,9 +476,9 @@ module ActionView # callback when its contents have changed. The default callback is an # Ajax call. By default the value of the observed field is sent as a # parameter with the Ajax call. - # + # # Example: - # # Generates: new Form.Element.Observer('suggest', 0.25, function(element, value) {new Ajax.Updater('suggest', + # # Generates: new Form.Element.Observer('suggest', 0.25, function(element, value) {new Ajax.Updater('suggest', # # '/testing/find_suggestion', {asynchronous:true, evalScripts:true, parameters:'q=' + value})}) # <%= observe_field :suggest, :url => { :action => :find_suggestion }, # :frequency => 0.25, @@ -500,14 +500,14 @@ module ActionView # new Form.Element.Observer('glass', 1, function(element, value) {alert('Element changed')}) # The element parameter is the DOM element being observed, and the value is its value at the # time the observer is triggered. - # + # # Additional options are: # :frequency:: The frequency (in seconds) at which changes to # this field will be detected. Not setting this # option at all or to a value equal to or less than # zero will use event based observation instead of # time based observation. - # :update:: Specifies the DOM ID of the element whose + # :update:: Specifies the DOM ID of the element whose # innerHTML should be updated with the # XMLHttpRequest response text. # :with:: A JavaScript expression specifying the parameters @@ -518,7 +518,7 @@ module ActionView # variable +value+. # # Examples - # + # # :with => "'my_custom_key=' + value" # :with => "'person[name]=' + prompt('New name')" # :with => "Form.Element.serialize('other-field')" @@ -544,7 +544,7 @@ module ActionView # observe_field 'book_title', # :url => 'http://example.com/books/edit/1', # :with => 'title' - # + # # # Sends params: {:book_title => 'Title of the book'} when the focus leaves # # the input field. # observe_field 'book_title', @@ -558,7 +558,7 @@ module ActionView build_observer('Form.Element.EventObserver', field_id, options) end end - + # Observes the form with the DOM ID specified by +form_id+ and calls a # callback when its contents have changed. The default callback is an # Ajax call. By default all fields of the observed field are sent as @@ -574,16 +574,17 @@ module ActionView build_observer('Form.EventObserver', form_id, options) end end - - # All the methods were moved to GeneratorMethods so that + + # All the methods were moved to GeneratorMethods so that # #include_helpers_from_context has nothing to overwrite. class JavaScriptGenerator #:nodoc: def initialize(context, &block) #:nodoc: @context, @lines = context, [] + @context.output_buffer = @lines if @context include_helpers_from_context @context.instance_exec(self, &block) end - + private def include_helpers_from_context @context.extended_by.each do |mod| @@ -591,17 +592,17 @@ module ActionView end extend GeneratorMethods end - - # JavaScriptGenerator generates blocks of JavaScript code that allow you - # to change the content and presentation of multiple DOM elements. Use + + # JavaScriptGenerator generates blocks of JavaScript code that allow you + # to change the content and presentation of multiple DOM elements. Use # this in your Ajax response bodies, either in a