diff options
Diffstat (limited to 'actionpack/lib')
7 files changed, 74 insertions, 28 deletions
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 413f6d48e5..3ede681253 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -969,7 +969,9 @@ module ActionController #:nodoc: # If-Modified-Since request header is <= last modified. def last_modified!(utc_time) response.last_modified= utc_time - head(:not_modified) if response.last_modified == request.if_modified_since + if request.if_modified_since && request.if_modified_since <= utc_time + head(:not_modified) + end end # Sets the ETag response header. Returns 304 Not Modified if the diff --git a/actionpack/lib/action_controller/routing/builder.rb b/actionpack/lib/action_controller/routing/builder.rb index 5704d9d01a..7b888fa8d2 100644 --- a/actionpack/lib/action_controller/routing/builder.rb +++ b/actionpack/lib/action_controller/routing/builder.rb @@ -60,12 +60,10 @@ module ActionController # segments are passed alongside in order to distinguish between default values # and requirements. def divide_route_options(segments, options) - options = options.dup + options = options.except(:path_prefix, :name_prefix) if options[:namespace] options[:controller] = "#{options.delete(:namespace).sub(/\/$/, '')}/#{options[:controller]}" - options.delete(:path_prefix) - options.delete(:name_prefix) end requirements = (options.delete(:requirements) || {}).dup diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index 6a39039504..4fc60f0697 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -134,6 +134,9 @@ module ActionController @controller = self.class.controller_class.new @controller.request = @request = TestRequest.new @response = TestResponse.new + + @controller.params = {} + @controller.send(:initialize_current_url) end # Cause the action to be rescued according to the regular rules for rescue_action when the visitor is not local diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb index 63ccde393a..93d38eb929 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb @@ -596,7 +596,7 @@ module ActionView end def missing_extension?(source) - extension && File.extname(source).blank? || File.exist?(File.join(ASSETS_DIR, directory, "#{source}.#{extension}")) + extension && (File.extname(source).blank? || File.exist?(File.join(ASSETS_DIR, directory, "#{source}.#{extension}"))) end def prepend_relative_url_root(source) diff --git a/actionpack/lib/action_view/helpers/atom_feed_helper.rb b/actionpack/lib/action_view/helpers/atom_feed_helper.rb index e65d5d1f60..ccb7df212a 100644 --- a/actionpack/lib/action_view/helpers/atom_feed_helper.rb +++ b/actionpack/lib/action_view/helpers/atom_feed_helper.rb @@ -51,6 +51,7 @@ module ActionView # * <tt>:schema_date</tt>: The date at which the tag scheme for the feed was first used. A good default is the year you # created the feed. See http://feedvalidator.org/docs/error/InvalidTAG.html for more information. If not specified, # 2005 is used (as an "I don't care" value). + # * <tt>:instruct</tt>: Hash of XML processing instructions in the form {target => {attribute => value, }} or {target => [{attribute => value, }, ]} # # Other namespaces can be added to the root element: # @@ -74,8 +75,20 @@ module ActionView # end # end # + # The Atom spec defines five elements (content rights title subtitle + # summary) which may directly contain xhtml content if :type => 'xhtml' + # is specified as an attribute. If so, this helper will take care of + # the enclosing div and xhtml namespace declaration. Example usage: # - # atom_feed yields an AtomFeedBuilder instance. + # entry.summary :type => 'xhtml' do |xhtml| + # xhtml.p pluralize(order.line_items.count, "line item") + # xhtml.p "Shipped to #{order.address}" + # xhtml.p "Paid by #{order.pay_type}" + # end + # + # + # atom_feed yields an AtomFeedBuilder instance. Nested elements yield + # an AtomBuilder instance. def atom_feed(options = {}, &block) if options[:schema_date] options[:schema_date] = options[:schema_date].strftime("%Y-%m-%d") if options[:schema_date].respond_to?(:strftime) @@ -85,6 +98,15 @@ module ActionView xml = options[:xml] || eval("xml", block.binding) xml.instruct! + if options[:instruct] + options[:instruct].each do |target,attrs| + if attrs.respond_to?(:keys) + xml.instruct!(target, attrs) + elsif attrs.respond_to?(:each) + attrs.each { |attr_group| xml.instruct!(target, attr_group) } + end + end + end feed_opts = {"xml:lang" => options[:language] || "en-US", "xmlns" => 'http://www.w3.org/2005/Atom'} feed_opts.merge!(options).reject!{|k,v| !k.to_s.match(/^xml/)} @@ -98,8 +120,38 @@ module ActionView end end + class AtomBuilder + def initialize(xml) + @xml = xml + end + + private + # Delegate to xml builder, first wrapping the element in a xhtml + # namespaced div element if the method and arguments indicate + # that an xhtml_block? is desired. + def method_missing(method, *arguments, &block) + if xhtml_block?(method, arguments) + @xml.__send__(method, *arguments) do + @xml.div(:xmlns => 'http://www.w3.org/1999/xhtml') do |xhtml| + block.call(xhtml) + end + end + else + @xml.__send__(method, *arguments, &block) + end + end + + # True if the method name matches one of the five elements defined + # in the Atom spec as potentially containing XHTML content and + # if :type => 'xhtml' is, in fact, specified. + def xhtml_block?(method, arguments) + %w( content rights title subtitle summary ).include?(method.to_s) && + arguments.last.respond_to?(:[]) && + arguments.last[:type].to_s == 'xhtml' + end + end - class AtomFeedBuilder + class AtomFeedBuilder < AtomBuilder def initialize(xml, view, feed_options = {}) @xml, @view, @feed_options = xml, view, feed_options end @@ -131,15 +183,11 @@ module ActionView @xml.link(:rel => 'alternate', :type => 'text/html', :href => options[:url] || @view.polymorphic_url(record)) - yield @xml + yield AtomBuilder.new(@xml) end end - - private - def method_missing(method, *arguments, &block) - @xml.__send__(method, *arguments, &block) - end end + end end end diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb index 208bf91dd4..7492348c50 100644 --- a/actionpack/lib/action_view/helpers/form_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb @@ -62,7 +62,7 @@ module ActionView # # <option>3</option><option>4</option></select> # # select_tag "colors", "<option>Red</option><option>Green</option><option>Blue</option>", :multiple => true - # # => <select id="colors" multiple="multiple" name="colors"><option>Red</option> + # # => <select id="colors" multiple="multiple" name="colors[]"><option>Red</option> # # <option>Green</option><option>Blue</option></select> # # select_tag "locations", "<option>Home</option><option selected="selected">Work</option><option>Out</option>" @@ -70,14 +70,15 @@ module ActionView # # <option>Out</option></select> # # select_tag "access", "<option>Read</option><option>Write</option>", :multiple => true, :class => 'form_input' - # # => <select class="form_input" id="access" multiple="multiple" name="access"><option>Read</option> + # # => <select class="form_input" id="access" multiple="multiple" name="access[]"><option>Read</option> # # <option>Write</option></select> # # select_tag "destination", "<option>NYC</option><option>Paris</option><option>Rome</option>", :disabled => true # # => <select disabled="disabled" id="destination" name="destination"><option>NYC</option> # # <option>Paris</option><option>Rome</option></select> def select_tag(name, option_tags = nil, options = {}) - content_tag :select, option_tags, { "name" => name, "id" => name }.update(options.stringify_keys) + html_name = (options[:multiple] == true && !name.to_s.ends_with?("[]")) ? "#{name}[]" : name + content_tag :select, option_tags, { "name" => html_name, "id" => name }.update(options.stringify_keys) end # Creates a standard text field; use these text fields to input smaller chunks of text like a username diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb index ff41a6d417..a3eccc741d 100644 --- a/actionpack/lib/action_view/helpers/prototype_helper.rb +++ b/actionpack/lib/action_view/helpers/prototype_helper.rb @@ -405,7 +405,7 @@ module ActionView # # Generates: <input name="create_btn" onclick="new Ajax.Request('/testing/create', # # {asynchronous:true, evalScripts:true, parameters:Form.serialize(this.form)}); # # return false;" type="button" value="Create" /> - # <%= button_to_remote 'create_btn', 'Create', :url => { :action => 'create' } %> + # <%= submit_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 @@ -413,24 +413,18 @@ module ActionView # # Generates: <input name="update_btn" onclick="new Ajax.Updater({success:'succeed',failure:'fail'}, # # '/testing/update', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this.form)}); # # return false;" type="button" value="Update" /> - # <%= button_to_remote 'update_btn', 'Update', :url => { :action => 'update' }, + # <%= submit_to_remote 'update_btn', 'Update', :url => { :action => 'update' }, # :update => { :success => "succeed", :failure => "fail" } # # <tt>options</tt> argument is the same as in form_remote_tag. - # - # 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 = {}) + def submit_to_remote(name, value, options = {}) options[:with] ||= 'Form.serialize(this.form)' - options[:html] ||= {} - options[:html][:type] = 'button' - options[:html][:onclick] = "#{remote_function(options)}; return false;" - options[:html][:name] = name - options[:html][:value] = value + html_options = options.delete(:html) || {} + html_options[:name] = name - tag("input", options[:html], false) + button_to_remote(value, options, html_options) end - alias_method :submit_to_remote, :button_to_remote # Returns '<tt>eval(request.responseText)</tt>' which is the JavaScript function # that +form_remote_tag+ can call in <tt>:complete</tt> to evaluate a multiple |