diff options
author | Xavier Noria <fxn@hashref.com> | 2010-06-28 00:12:15 +0200 |
---|---|---|
committer | Xavier Noria <fxn@hashref.com> | 2010-06-28 00:12:15 +0200 |
commit | 4329f8133fee8e4f3e558787f67de59f0c4a4dd1 (patch) | |
tree | 346ef7340d8348e50d119ca749a16c1654c20a08 /actionpack/lib/action_dispatch | |
parent | c37f7d66e49ffe5ac2115cc30e5529fd1c2924a8 (diff) | |
parent | ebee77a28a7267d5f23a28ba23c1eb88a2d7d527 (diff) | |
download | rails-4329f8133fee8e4f3e558787f67de59f0c4a4dd1.tar.gz rails-4329f8133fee8e4f3e558787f67de59f0c4a4dd1.tar.bz2 rails-4329f8133fee8e4f3e558787f67de59f0c4a4dd1.zip |
Merge remote branch 'rails/master'
Diffstat (limited to 'actionpack/lib/action_dispatch')
9 files changed, 256 insertions, 118 deletions
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index 98f4f5ae18..fd23b1df79 100644 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -194,9 +194,12 @@ module ActionDispatch @env['rack.input'] end + # TODO This should be broken apart into AD::Request::Session and probably + # be included by the session middleware. def reset_session - self.session_options.delete(:id) + session.destroy if session self.session = {} + @env['action_dispatch.request.flash_hash'] = nil end def session=(session) #:nodoc: diff --git a/actionpack/lib/action_dispatch/middleware/flash.rb b/actionpack/lib/action_dispatch/middleware/flash.rb index 18771fe782..bfa30cf5af 100644 --- a/actionpack/lib/action_dispatch/middleware/flash.rb +++ b/actionpack/lib/action_dispatch/middleware/flash.rb @@ -4,7 +4,7 @@ module ActionDispatch # read a notice you put there or <tt>flash["notice"] = "hello"</tt> # to put a new one. def flash - session['flash'] ||= Flash::FlashHash.new + @env['action_dispatch.request.flash_hash'] ||= (session["flash"] || Flash::FlashHash.new) end end @@ -176,7 +176,14 @@ module ActionDispatch @app.call(env) ensure - if (session = env['rack.session']) && session.key?('flash') && session['flash'].empty? + session = env['rack.session'] || {} + flash_hash = env['action_dispatch.request.flash_hash'] + + if flash_hash && (!flash_hash.empty? || session.key?('flash')) + session["flash"] = flash_hash + end + + if session.key?('flash') && session['flash'].empty? session.delete('flash') end end diff --git a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb index 3e8d64b0c6..08bc80dbc2 100644 --- a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb @@ -12,6 +12,35 @@ module ActionDispatch ENV_SESSION_KEY = 'rack.session'.freeze ENV_SESSION_OPTIONS_KEY = 'rack.session.options'.freeze + # thin wrapper around Hash that allows us to lazily + # load session id into session_options + class OptionsHash < Hash + def initialize(by, env, default_options) + @by = by + @env = env + @session_id_loaded = false + merge!(default_options) + end + + def [](key) + if key == :id + load_session_id! unless super(:id) || has_session_id? + end + super(key) + end + + private + + def has_session_id? + @session_id_loaded + end + + def load_session_id! + self[:id] = @by.send(:extract_session_id, @env) + @session_id_loaded = true + end + end + class SessionHash < Hash def initialize(by, env) super() @@ -21,66 +50,75 @@ module ActionDispatch end def [](key) - load! unless @loaded + load_for_read! + super(key.to_s) + end + + def has_key?(key) + load_for_read! super(key.to_s) end def []=(key, value) - load! unless @loaded + load_for_write! super(key.to_s, value) end def to_hash + load_for_read! h = {}.replace(self) h.delete_if { |k,v| v.nil? } h end def update(hash) - load! unless @loaded + load_for_write! super(hash.stringify_keys) end def delete(key) - load! unless @loaded + load_for_write! super(key.to_s) end def inspect - load! unless @loaded + load_for_read! super end + def exists? + return @exists if instance_variable_defined?(:@exists) + @exists = @by.send(:exists?, @env) + end + def loaded? @loaded end + def destroy + clear + @by.send(:destroy, @env) if @by + @env[ENV_SESSION_OPTIONS_KEY][:id] = nil if @env && @env[ENV_SESSION_OPTIONS_KEY] + @loaded = false + end + private - def load! - stale_session_check! do - id, session = @by.send(:load_session, @env) - (@env[ENV_SESSION_OPTIONS_KEY] ||= {})[:id] = id - replace(session.stringify_keys) - @loaded = true - end + + def load_for_read! + load! if !loaded? && exists? end - def stale_session_check! - yield - rescue ArgumentError => argument_error - if argument_error.message =~ %r{undefined class/module ([\w:]*\w)} - begin - # Note that the regexp does not allow $1 to end with a ':' - $1.constantize - rescue LoadError, NameError => const_error - raise ActionDispatch::Session::SessionRestoreError, "Session contains objects whose class definition isn't available.\nRemember to require the classes for all objects kept in the session.\n(Original exception: #{const_error.message} [#{const_error.class}])\n" - end - - retry - else - raise - end + def load_for_write! + load! unless loaded? + end + + def load! + id, session = @by.send(:load_session, @env) + @env[ENV_SESSION_OPTIONS_KEY][:id] = id + replace(session.stringify_keys) + @loaded = true end + end DEFAULT_OPTIONS = { @@ -108,8 +146,8 @@ module ActionDispatch session_data = env[ENV_SESSION_KEY] options = env[ENV_SESSION_OPTIONS_KEY] - if !session_data.is_a?(AbstractStore::SessionHash) || session_data.send(:loaded?) || options[:expire_after] - session_data.send(:load!) if session_data.is_a?(AbstractStore::SessionHash) && !session_data.send(:loaded?) + if !session_data.is_a?(AbstractStore::SessionHash) || session_data.loaded? || options[:expire_after] + session_data.send(:load!) if session_data.is_a?(AbstractStore::SessionHash) && !session_data.loaded? sid = options[:id] || generate_sid session_data = session_data.to_hash @@ -133,7 +171,7 @@ module ActionDispatch def prepare!(env) env[ENV_SESSION_KEY] = SessionHash.new(self, env) - env[ENV_SESSION_OPTIONS_KEY] = @default_options.dup + env[ENV_SESSION_OPTIONS_KEY] = OptionsHash.new(self, env, @default_options) end def generate_sid @@ -141,15 +179,30 @@ module ActionDispatch end def set_cookie(request, options) - request.cookie_jar[@key] = options + if request.cookie_jar[@key] != options[:value] || !options[:expires].nil? + request.cookie_jar[@key] = options + end end def load_session(env) - request = Rack::Request.new(env) - sid = request.cookies[@key] - sid ||= request.params[@key] unless @cookie_only - sid, session = get_session(env, sid) - [sid, session] + stale_session_check! do + sid = current_session_id(env) + sid, session = get_session(env, sid) + [sid, session] + end + end + + def extract_session_id(env) + stale_session_check! do + request = ActionDispatch::Request.new(env) + sid = request.cookies[@key] + sid ||= request.params[@key] unless @cookie_only + sid + end + end + + def current_session_id(env) + env[ENV_SESSION_OPTIONS_KEY][:id] end def ensure_session_key! @@ -161,6 +214,26 @@ module ActionDispatch end end + def stale_session_check! + yield + rescue ArgumentError => argument_error + if argument_error.message =~ %r{undefined class/module ([\w:]*\w)} + begin + # Note that the regexp does not allow $1 to end with a ':' + $1.constantize + rescue LoadError, NameError => const_error + raise ActionDispatch::Session::SessionRestoreError, "Session contains objects whose class definition isn't available.\nRemember to require the classes for all objects kept in the session.\n(Original exception: #{const_error.message} [#{const_error.class}])\n" + end + retry + else + raise + end + end + + def exists?(env) + current_session_id(env).present? + end + def get_session(env, sid) raise '#get_session needs to be implemented.' end @@ -169,6 +242,10 @@ module ActionDispatch raise '#set_session needs to be implemented and should return ' << 'the value to be stored in the cookie (usually the sid)' end + + def destroy(env) + raise '#destroy needs to be implemented.' + end end end end diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb index 92a86ee229..dce47c63bc 100644 --- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb @@ -39,16 +39,6 @@ module ActionDispatch # # Note that changing digest or secret invalidates all existing sessions! class CookieStore < AbstractStore - class OptionsHash < Hash - def initialize(by, env, default_options) - @session_data = env[AbstractStore::ENV_SESSION_KEY] - merge!(default_options) - end - - def [](key) - key == :id ? @session_data[:session_id] : super(key) - end - end def initialize(app, options = {}) super(app, options.merge!(:cookie_only => true)) @@ -57,19 +47,32 @@ module ActionDispatch private - def prepare!(env) - env[ENV_SESSION_KEY] = SessionHash.new(self, env) - env[ENV_SESSION_OPTIONS_KEY] = OptionsHash.new(self, env, @default_options) - end - def load_session(env) - request = ActionDispatch::Request.new(env) - data = request.cookie_jar.signed[@key] + data = unpacked_cookie_data(env) data = persistent_session_id!(data) - data.stringify_keys! [data["session_id"], data] end + def extract_session_id(env) + if data = unpacked_cookie_data(env) + data["session_id"] + else + nil + end + end + + def unpacked_cookie_data(env) + env["action_dispatch.request.unsigned_session_cookie"] ||= begin + stale_session_check! do + request = ActionDispatch::Request.new(env) + if data = request.cookie_jar.signed[@key] + data.stringify_keys! + end + data || {} + end + end + end + def set_cookie(request, options) request.cookie_jar.signed[@key] = options end @@ -78,6 +81,10 @@ module ActionDispatch persistent_session_id!(session_data, sid) end + def destroy(env) + # session data is stored on client; nothing to do here + end + def persistent_session_id!(data, sid=nil) data ||= {} data["session_id"] ||= sid || generate_sid diff --git a/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb b/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb index 8df8f977e8..28e3dbd732 100644 --- a/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb @@ -42,6 +42,15 @@ module ActionDispatch rescue MemCache::MemCacheError, Errno::ECONNREFUSED false end + + def destroy(env) + if sid = current_session_id(env) + @pool.delete(sid) + end + rescue MemCache::MemCacheError, Errno::ECONNREFUSED + false + end + end end end diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index c31f681411..388f695187 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -55,7 +55,7 @@ module ActionDispatch path = args.first end - if @scope[:module] && options[:to] + if @scope[:module] && options[:to] && !options[:to].is_a?(Proc) if options[:to].to_s.include?("#") options[:to] = "#{@scope[:module]}/#{options[:to]}" elsif @scope[:controller].nil? @@ -194,7 +194,7 @@ module ActionDispatch # for root cases, where the latter is the correct one. def self.normalize_path(path) path = Rack::Mount::Utils.normalize_path(path) - path.sub!(%r{/(\(+)/?:}, '\1/:') unless path =~ %r{^/\(+:.*\)$} + path.gsub!(%r{/(\(+)/?}, '\1/') unless path =~ %r{^/\(+[^/]+\)$} path end @@ -299,6 +299,11 @@ module ActionDispatch options = args.extract_options! options = options.dup + if name_prefix = options.delete(:name_prefix) + options[:as] ||= name_prefix + ActiveSupport::Deprecation.warn ":name_prefix was deprecated in the new router syntax. Use :as instead.", caller + end + case args.first when String options[:path] = args.first @@ -341,9 +346,11 @@ module ActionDispatch scope(controller.to_sym) { yield } end - def namespace(path) + def namespace(path, options = {}) path = path.to_s - scope(:path => path, :name_prefix => path, :module => path, :shallow_path => path, :shallow_prefix => path) { yield } + options = { :path => path, :as => path, :module => path, + :shallow_path => path, :shallow_prefix => path }.merge!(options) + scope(options) { yield } end def constraints(constraints = {}) @@ -359,10 +366,10 @@ module ActionDispatch options = (@scope[:options] || {}).merge(options) - if @scope[:name_prefix] && !options[:as].blank? - options[:as] = "#{@scope[:name_prefix]}_#{options[:as]}" - elsif @scope[:name_prefix] && options[:as] == "" - options[:as] = @scope[:name_prefix].to_s + if @scope[:as] && !options[:as].blank? + options[:as] = "#{@scope[:as]}_#{options[:as]}" + elsif @scope[:as] && options[:as] == "" + options[:as] = @scope[:as].to_s end args.push(options) @@ -382,7 +389,7 @@ module ActionDispatch Mapper.normalize_path("#{parent}/#{child}") end - def merge_name_prefix_scope(parent, child) + def merge_as_scope(parent, child) parent ? "#{parent}_#{child}" : child end @@ -411,7 +418,9 @@ module ActionDispatch end def merge_blocks_scope(parent, child) - (parent || []) + [child] + merged = parent ? parent.dup : [] + merged << child if child + merged end def merge_options_scope(parent, child) @@ -434,7 +443,8 @@ module ActionDispatch def initialize(entities, options = {}) @name = entities.to_s @path = options.delete(:path) || @name - @controller = options.delete(:controller) || @name.to_s.pluralize + @controller = (options.delete(:controller) || @name).to_s + @as = options.delete(:as) @options = options end @@ -453,7 +463,7 @@ module ActionDispatch end def name - options[:as] || @name + @as || @name end def plural @@ -505,7 +515,7 @@ module ActionDispatch def nested_options {}.tap do |opts| - opts[:name_prefix] = member_name + opts[:as] = member_name opts["#{singular}_id".to_sym] = id_constraint if id_constraint? opts[:options] = { :shallow => shallow? } unless options[:shallow].nil? end @@ -537,14 +547,18 @@ module ActionDispatch [:show, :create, :update, :destroy, :new, :edit] end - def initialize(entity, options = {}) - super + def initialize(entities, options) + @name = entities.to_s + @path = options.delete(:path) || @name + @controller = (options.delete(:controller) || @name.to_s.pluralize).to_s + @as = options.delete(:as) + @options = options end def member_name name end - alias_method :collection_name, :member_name + alias :collection_name :member_name def nested_path path @@ -552,7 +566,7 @@ module ActionDispatch def nested_options {}.tap do |opts| - opts[:name_prefix] = member_name + opts[:as] = member_name opts[:options] = { :shallow => shallow? } unless @options[:shallow].nil? end end @@ -571,6 +585,10 @@ module ActionDispatch @scope[:path_names] = @set.resources_path_names end + def resources_path_names(options) + @scope[:path_names].merge!(options) + end + def resource(*resources, &block) options = resources.extract_options! options = (@scope[:options] || {}).merge(options) @@ -673,7 +691,7 @@ module ActionDispatch if @scope[:shallow_path].blank? scope(*parent_resource.nested_scope) { yield } else - scope(@scope[:shallow_path], :name_prefix => @scope[:shallow_prefix]) do + scope(@scope[:shallow_path], :as => @scope[:shallow_prefix]) do scope(*parent_resource.nested_scope) { yield } end end @@ -684,7 +702,7 @@ module ActionDispatch end end - def namespace(path) + def namespace(path, options = {}) if resource_scope? nested { super } else @@ -726,10 +744,10 @@ module ActionDispatch return member { match(*args) } end - path_names = options.delete(:path_names) + path = options.delete(:path) if args.first.is_a?(Symbol) - path = path_for_action(args.first, path_names) + path = path_for_action(args.first, path) options = options_for_action(args.first, options) with_exclusive_scope do @@ -758,7 +776,7 @@ module ActionDispatch def root(options={}) if @scope[:scope_level] == :resources with_scope_level(:nested) do - scope(parent_resource.path, :name_prefix => parent_resource.collection_name) do + scope(parent_resource.path, :as => parent_resource.collection_name) do super(options) end end @@ -806,14 +824,14 @@ module ActionDispatch def with_exclusive_scope begin - old_name_prefix, old_path = @scope[:name_prefix], @scope[:path] - @scope[:name_prefix], @scope[:path] = nil, nil + old_name_prefix, old_path = @scope[:as], @scope[:path] + @scope[:as], @scope[:path] = nil, nil with_scope_level(:exclusive) do yield end ensure - @scope[:name_prefix], @scope[:path] = old_name_prefix, old_path + @scope[:as], @scope[:path] = old_name_prefix, old_path end end @@ -850,7 +868,7 @@ module ActionDispatch end end - def path_for_action(action, path_names) + def path_for_action(action, path) case action when :index, :create "#{@scope[:path]}(.:format)" @@ -871,12 +889,12 @@ module ActionDispatch else case @scope[:scope_level] when :collection, :new - "#{@scope[:path]}/#{action_path(action)}(.:format)" + "#{@scope[:path]}/#{action_path(action, path)}(.:format)" else if parent_resource.shallow? - "#{@scope[:shallow_path]}/#{parent_resource.path}/:id/#{action_path(action)}(.:format)" + "#{@scope[:shallow_path]}/#{parent_resource.path}/:id/#{action_path(action, path)}(.:format)" else - "#{@scope[:path]}/#{action_path(action)}(.:format)" + "#{@scope[:path]}/#{action_path(action, path)}(.:format)" end end end @@ -895,9 +913,8 @@ module ActionDispatch end end - def action_path(name, path_names = nil) - path_names ||= @scope[:path_names] - path_names[name.to_sym] || name.to_s + def action_path(name, path = nil) + path || @scope[:path_names][name.to_sym] || name.to_s end def options_for_action(action, options) @@ -908,7 +925,7 @@ module ActionDispatch end def name_for_action(action) - name_prefix = @scope[:name_prefix].blank? ? "" : "#{@scope[:name_prefix]}_" + name_prefix = @scope[:as].blank? ? "" : "#{@scope[:as]}_" shallow_prefix = @scope[:shallow_prefix].blank? ? "" : "#{@scope[:shallow_prefix]}_" case action diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 57a73dde75..7be79d3200 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -185,7 +185,7 @@ module ActionDispatch end end - attr_accessor :routes, :named_routes + attr_accessor :set, :routes, :named_routes attr_accessor :disable_clear_and_finalize, :resources_path_names attr_accessor :default_url_options, :request_class @@ -296,6 +296,7 @@ module ActionDispatch @extras = extras normalize_options! + normalize_recall! normalize_controller_action_id! use_relative_controller! controller.sub!(%r{^/}, '') if controller @@ -336,6 +337,15 @@ module ActionDispatch end end + def normalize_recall! + # If the target route is not a standard route then remove controller and action + # from the options otherwise they will appear in the url parameters + if block_or_proc_route_target? + recall.delete(:controller) unless segment_keys.include?(:controller) + recall.delete(:action) unless segment_keys.include?(:action) + end + end + # This pulls :controller, :action, and :id out of the recall. # The recall key is only used if there is no key in the options # or if the key in the options is identical. If any of @@ -371,7 +381,7 @@ module ActionDispatch def generate error = ActionController::RoutingError.new("No route matches #{options.inspect}") - path, params = @set.generate(:path_info, named_route, options, recall, opts) + path, params = @set.set.generate(:path_info, named_route, options, recall, opts) raise error unless path @@ -402,6 +412,19 @@ module ActionDispatch return false unless current_controller controller.to_param != current_controller.to_param end + + private + def named_route_exists? + named_route && set.named_routes[named_route] + end + + def block_or_proc_route_target? + named_route_exists? && !set.named_routes[named_route].app.is_a?(Dispatcher) + end + + def segment_keys + named_route_exists? ? set.named_routes[named_route].segment_keys : [] + end end # Generate the path indicated by the arguments, and return an array of @@ -415,7 +438,7 @@ module ActionDispatch end def generate(options, recall = {}, extras = false) - Generator.new(options, recall, @set, extras).generate + Generator.new(options, recall, self, extras).generate end RESERVED_OPTIONS = [:anchor, :params, :only_path, :host, :protocol, :port, :trailing_slash] @@ -447,7 +470,7 @@ module ActionDispatch # ROUTES TODO: This can be called directly, so script_name should probably be set in the router rewritten_url << (options[:trailing_slash] ? path.sub(/\?|\z/) { "/" + $& } : path) - rewritten_url << "##{Rack::Utils.escape(options[:anchor].to_param.to_s)}" if options[:anchor] + rewritten_url << "##{Rack::Mount::Utils.escape_uri(options[:anchor].to_param.to_s)}" if options[:anchor] rewritten_url end diff --git a/actionpack/lib/action_dispatch/testing/assertions/routing.rb b/actionpack/lib/action_dispatch/testing/assertions/routing.rb index 1499c03bdf..9338fa9e70 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/routing.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/routing.rb @@ -53,7 +53,6 @@ module ActionDispatch extras.each_key { |key| expected_options.delete key } unless extras.nil? expected_options.stringify_keys! - routing_diff = expected_options.diff(request.path_parameters) msg = build_message(message, "The recognized options <?> did not match <?>, difference: <?>", request.path_parameters, expected_options, expected_options.diff(request.path_parameters)) assert_block(msg) { request.path_parameters == expected_options } diff --git a/actionpack/lib/action_dispatch/testing/assertions/selector.rb b/actionpack/lib/action_dispatch/testing/assertions/selector.rb index b490547da7..2fc9e2b7d6 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/selector.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/selector.rb @@ -7,9 +7,7 @@ require 'action_controller/vendor/html-scanner' module ActionDispatch module Assertions - unless const_defined?(:NO_STRIP) - NO_STRIP = %w{pre script style textarea} - end + NO_STRIP = %w{pre script style textarea} # Adds the +assert_select+ method for use in Rails functional # test cases, which can be used to make assertions on the response HTML of a controller @@ -581,27 +579,25 @@ module ActionDispatch end protected - unless const_defined?(:RJS_STATEMENTS) - RJS_PATTERN_HTML = "\"((\\\\\"|[^\"])*)\"" - RJS_ANY_ID = "\"([^\"])*\"" - RJS_STATEMENTS = { - :chained_replace => "\\$\\(#{RJS_ANY_ID}\\)\\.replace\\(#{RJS_PATTERN_HTML}\\)", - :chained_replace_html => "\\$\\(#{RJS_ANY_ID}\\)\\.update\\(#{RJS_PATTERN_HTML}\\)", - :replace_html => "Element\\.update\\(#{RJS_ANY_ID}, #{RJS_PATTERN_HTML}\\)", - :replace => "Element\\.replace\\(#{RJS_ANY_ID}, #{RJS_PATTERN_HTML}\\)", - :redirect => "window.location.href = #{RJS_ANY_ID}" - } - [:remove, :show, :hide, :toggle].each do |action| - RJS_STATEMENTS[action] = "Element\\.#{action}\\(#{RJS_ANY_ID}\\)" - end - RJS_INSERTIONS = ["top", "bottom", "before", "after"] - RJS_INSERTIONS.each do |insertion| - RJS_STATEMENTS["insert_#{insertion}".to_sym] = "Element.insert\\(#{RJS_ANY_ID}, \\{ #{insertion}: #{RJS_PATTERN_HTML} \\}\\)" - end - RJS_STATEMENTS[:insert_html] = "Element.insert\\(#{RJS_ANY_ID}, \\{ (#{RJS_INSERTIONS.join('|')}): #{RJS_PATTERN_HTML} \\}\\)" - RJS_STATEMENTS[:any] = Regexp.new("(#{RJS_STATEMENTS.values.join('|')})") - RJS_PATTERN_UNICODE_ESCAPED_CHAR = /\\u([0-9a-zA-Z]{4})/ + RJS_PATTERN_HTML = "\"((\\\\\"|[^\"])*)\"" + RJS_ANY_ID = "\"([^\"])*\"" + RJS_STATEMENTS = { + :chained_replace => "\\$\\(#{RJS_ANY_ID}\\)\\.replace\\(#{RJS_PATTERN_HTML}\\)", + :chained_replace_html => "\\$\\(#{RJS_ANY_ID}\\)\\.update\\(#{RJS_PATTERN_HTML}\\)", + :replace_html => "Element\\.update\\(#{RJS_ANY_ID}, #{RJS_PATTERN_HTML}\\)", + :replace => "Element\\.replace\\(#{RJS_ANY_ID}, #{RJS_PATTERN_HTML}\\)", + :redirect => "window.location.href = #{RJS_ANY_ID}" + } + [:remove, :show, :hide, :toggle].each do |action| + RJS_STATEMENTS[action] = "Element\\.#{action}\\(#{RJS_ANY_ID}\\)" + end + RJS_INSERTIONS = ["top", "bottom", "before", "after"] + RJS_INSERTIONS.each do |insertion| + RJS_STATEMENTS["insert_#{insertion}".to_sym] = "Element.insert\\(#{RJS_ANY_ID}, \\{ #{insertion}: #{RJS_PATTERN_HTML} \\}\\)" end + RJS_STATEMENTS[:insert_html] = "Element.insert\\(#{RJS_ANY_ID}, \\{ (#{RJS_INSERTIONS.join('|')}): #{RJS_PATTERN_HTML} \\}\\)" + RJS_STATEMENTS[:any] = Regexp.new("(#{RJS_STATEMENTS.values.join('|')})") + RJS_PATTERN_UNICODE_ESCAPED_CHAR = /\\u([0-9a-zA-Z]{4})/ # +assert_select+ and +css_select+ call this to obtain the content in the HTML # page, or from all the RJS statements, depending on the type of response. |