Rails 2.1.1
Among other things, a security fix.
This commit is contained in:
parent
d2c4c8737c
commit
d4f97345db
354 changed files with 21027 additions and 3072 deletions
|
@ -97,7 +97,7 @@ module ActionController
|
|||
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)
|
||||
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
|
||||
|
|
|
@ -398,47 +398,31 @@ module ActionController
|
|||
# # The same, but shorter.
|
||||
# assert_select "ol>li", 4
|
||||
def assert_select_rjs(*args, &block)
|
||||
rjs_type = nil
|
||||
arg = args.shift
|
||||
rjs_type = args.first.is_a?(Symbol) ? args.shift : nil
|
||||
id = args.first.is_a?(String) ? args.shift : nil
|
||||
|
||||
# If the first argument is a symbol, it's the type of RJS statement we're looking
|
||||
# for (update, replace, insertion, etc). Otherwise, we're looking for just about
|
||||
# any RJS statement.
|
||||
if arg.is_a?(Symbol)
|
||||
rjs_type = arg
|
||||
|
||||
if rjs_type
|
||||
if rjs_type == :insert
|
||||
arg = args.shift
|
||||
insertion = "insert_#{arg}".to_sym
|
||||
raise ArgumentError, "Unknown RJS insertion type #{arg}" unless RJS_STATEMENTS[insertion]
|
||||
position = args.shift
|
||||
insertion = "insert_#{position}".to_sym
|
||||
raise ArgumentError, "Unknown RJS insertion type #{position}" unless RJS_STATEMENTS[insertion]
|
||||
statement = "(#{RJS_STATEMENTS[insertion]})"
|
||||
else
|
||||
raise ArgumentError, "Unknown RJS statement type #{rjs_type}" unless RJS_STATEMENTS[rjs_type]
|
||||
statement = "(#{RJS_STATEMENTS[rjs_type]})"
|
||||
end
|
||||
arg = args.shift
|
||||
else
|
||||
statement = "#{RJS_STATEMENTS[:any]}"
|
||||
end
|
||||
|
||||
# Next argument we're looking for is the element identifier. If missing, we pick
|
||||
# any element.
|
||||
if arg.is_a?(String)
|
||||
id = Regexp.quote(arg)
|
||||
arg = args.shift
|
||||
else
|
||||
id = "[^\"]*"
|
||||
end
|
||||
|
||||
pattern =
|
||||
case rjs_type
|
||||
when :chained_replace, :chained_replace_html
|
||||
Regexp.new("\\$\\(\"#{id}\"\\)#{statement}\\(#{RJS_PATTERN_HTML}\\)", Regexp::MULTILINE)
|
||||
when :remove, :show, :hide, :toggle
|
||||
Regexp.new("#{statement}\\(\"#{id}\"\\)")
|
||||
else
|
||||
Regexp.new("#{statement}\\(\"#{id}\", #{RJS_PATTERN_HTML}\\)", Regexp::MULTILINE)
|
||||
end
|
||||
# any element, otherwise we replace it in the statement.
|
||||
pattern = Regexp.new(
|
||||
id ? statement.gsub(RJS_ANY_ID, "\"#{id}\"") : statement
|
||||
)
|
||||
|
||||
# Duplicate the body since the next step involves destroying it.
|
||||
matches = nil
|
||||
|
@ -447,7 +431,7 @@ module ActionController
|
|||
matches = @response.body.match(pattern)
|
||||
else
|
||||
@response.body.gsub(pattern) do |match|
|
||||
html = unescape_rjs($2)
|
||||
html = unescape_rjs(match)
|
||||
matches ||= []
|
||||
matches.concat HTML::Document.new(html).root.children.select { |n| n.tag? }
|
||||
""
|
||||
|
@ -577,27 +561,23 @@ module ActionController
|
|||
|
||||
protected
|
||||
unless const_defined?(:RJS_STATEMENTS)
|
||||
RJS_STATEMENTS = {
|
||||
:replace => /Element\.replace/,
|
||||
:replace_html => /Element\.update/,
|
||||
:chained_replace => /\.replace/,
|
||||
:chained_replace_html => /\.update/,
|
||||
:remove => /Element\.remove/,
|
||||
:show => /Element\.show/,
|
||||
:hide => /Element\.hide/,
|
||||
:toggle => /Element\.toggle/
|
||||
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}\\)"
|
||||
}
|
||||
RJS_INSERTIONS = [:top, :bottom, :before, :after]
|
||||
RJS_INSERTIONS.each do |insertion|
|
||||
RJS_STATEMENTS["insert_#{insertion}".to_sym] = Regexp.new(Regexp.quote("new Insertion.#{insertion.to_s.camelize}"))
|
||||
[: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_STATEMENTS[:insert_html] = Regexp.new(RJS_INSERTIONS.collect do |insertion|
|
||||
Regexp.quote("new Insertion.#{insertion.to_s.camelize}")
|
||||
end.join('|'))
|
||||
RJS_PATTERN_HTML = /"((\\"|[^"])*)"/
|
||||
RJS_PATTERN_EVERYTHING = Regexp.new("#{RJS_STATEMENTS[:any]}\\(\"([^\"]*)\", #{RJS_PATTERN_HTML}\\)",
|
||||
Regexp::MULTILINE)
|
||||
RJS_PATTERN_UNICODE_ESCAPED_CHAR = /\\u([0-9a-zA-Z]{4})/
|
||||
end
|
||||
|
||||
|
@ -611,8 +591,8 @@ module ActionController
|
|||
root = HTML::Node.new(nil)
|
||||
|
||||
while true
|
||||
next if body.sub!(RJS_PATTERN_EVERYTHING) do |match|
|
||||
html = unescape_rjs($3)
|
||||
next if body.sub!(RJS_STATEMENTS[:any]) do |match|
|
||||
html = unescape_rjs(match)
|
||||
matches = HTML::Document.new(html).root.children.select { |n| n.tag? }
|
||||
root.children.concat matches
|
||||
""
|
||||
|
|
|
@ -613,8 +613,9 @@ module ActionController #:nodoc:
|
|||
#
|
||||
# This takes the current URL as is and only exchanges the action. In contrast, <tt>url_for :action => 'print'</tt>
|
||||
# would have slashed-off the path components after the changed action.
|
||||
def url_for(options = nil) #:doc:
|
||||
case options || {}
|
||||
def url_for(options = {})
|
||||
options ||= {}
|
||||
case options
|
||||
when String
|
||||
options
|
||||
when Hash
|
||||
|
@ -743,6 +744,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
|
||||
|
@ -865,7 +869,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
|
||||
|
@ -1147,7 +1151,7 @@ module ActionController #:nodoc:
|
|||
|
||||
def log_processing
|
||||
if logger && logger.info?
|
||||
logger.info "\n\nProcessing #{controller_class_name}\##{action_name} (for #{request_origin}) [#{request.method.to_s.upcase}]"
|
||||
logger.info "\n\nProcessing #{self.class.name}\##{action_name} (for #{request_origin}) [#{request.method.to_s.upcase}]"
|
||||
logger.info " Session ID: #{@_session.session_id}" if @_session and @_session.respond_to?(:session_id)
|
||||
logger.info " Parameters: #{respond_to?(:filter_parameters) ? filter_parameters(params).inspect : params.inspect}"
|
||||
end
|
||||
|
|
|
@ -135,7 +135,7 @@ module ActionController
|
|||
# be reloaded on the next request without restarting the server.
|
||||
def cleanup_application
|
||||
ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord)
|
||||
Dependencies.clear
|
||||
ActiveSupport::Dependencies.clear
|
||||
ActiveRecord::Base.clear_reloadable_connections! if defined?(ActiveRecord)
|
||||
end
|
||||
|
||||
|
|
|
@ -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 <tt>filters</tt> will be appended to the filter_chain and
|
||||
# will execute before the action on this controller is performed.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -31,18 +31,21 @@ module ActionController
|
|||
module RecordIdentifier
|
||||
extend self
|
||||
|
||||
JOIN = '_'.freeze
|
||||
NEW = 'new'.freeze
|
||||
|
||||
# Returns plural/singular for a record or class. Example:
|
||||
#
|
||||
# partial_path(post) # => "posts/post"
|
||||
# partial_path(Person) # => "people/person"
|
||||
# partial_path(Person, "admin/games") # => "admin/people/person"
|
||||
def partial_path(record_or_class, controller_path = nil)
|
||||
klass = class_from_record_or_class(record_or_class)
|
||||
name = model_name_from_record_or_class(record_or_class)
|
||||
|
||||
if controller_path && controller_path.include?("/")
|
||||
"#{File.dirname(controller_path)}/#{klass.name.tableize}/#{klass.name.demodulize.underscore}"
|
||||
"#{File.dirname(controller_path)}/#{name.partial_path}"
|
||||
else
|
||||
"#{klass.name.tableize}/#{klass.name.demodulize.underscore}"
|
||||
name.partial_path
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -56,21 +59,25 @@ module ActionController
|
|||
# dom_class(post, :edit) # => "edit_post"
|
||||
# dom_class(Person, :edit) # => "edit_person"
|
||||
def dom_class(record_or_class, prefix = nil)
|
||||
[ prefix, singular_class_name(record_or_class) ].compact * '_'
|
||||
singular = singular_class_name(record_or_class)
|
||||
prefix ? "#{prefix}#{JOIN}#{singular}" : singular
|
||||
end
|
||||
|
||||
# The DOM id convention is to use the singular form of an object or class with the id following an underscore.
|
||||
# If no id is found, prefix with "new_" instead. Examples:
|
||||
#
|
||||
# dom_id(Post.new(:id => 45)) # => "post_45"
|
||||
# dom_id(Post.find(45)) # => "post_45"
|
||||
# dom_id(Post.new) # => "new_post"
|
||||
#
|
||||
# If you need to address multiple instances of the same class in the same view, you can prefix the dom_id:
|
||||
#
|
||||
# dom_id(Post.new(:id => 45), :edit) # => "edit_post_45"
|
||||
# dom_id(Post.find(45), :edit) # => "edit_post_45"
|
||||
def dom_id(record, prefix = nil)
|
||||
prefix ||= 'new' unless record.id
|
||||
[ prefix, singular_class_name(record), record.id ].compact * '_'
|
||||
if record_id = record.id
|
||||
"#{dom_class(record, prefix)}#{JOIN}#{record_id}"
|
||||
else
|
||||
dom_class(record, prefix || NEW)
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the plural class name of a record or class. Examples:
|
||||
|
@ -78,7 +85,7 @@ module ActionController
|
|||
# plural_class_name(post) # => "posts"
|
||||
# plural_class_name(Highrise::Person) # => "highrise_people"
|
||||
def plural_class_name(record_or_class)
|
||||
singular_class_name(record_or_class).pluralize
|
||||
model_name_from_record_or_class(record_or_class).plural
|
||||
end
|
||||
|
||||
# Returns the singular class name of a record or class. Examples:
|
||||
|
@ -86,12 +93,12 @@ module ActionController
|
|||
# singular_class_name(post) # => "post"
|
||||
# singular_class_name(Highrise::Person) # => "highrise_person"
|
||||
def singular_class_name(record_or_class)
|
||||
class_from_record_or_class(record_or_class).name.underscore.tr('/', '_')
|
||||
model_name_from_record_or_class(record_or_class).singular
|
||||
end
|
||||
|
||||
private
|
||||
def class_from_record_or_class(record_or_class)
|
||||
record_or_class.is_a?(Class) ? record_or_class : record_or_class.class
|
||||
def model_name_from_record_or_class(record_or_class)
|
||||
(record_or_class.is_a?(Class) ? record_or_class : record_or_class.class).model_name
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -134,14 +134,17 @@ module ActionController
|
|||
# REMOTE_ADDR is a proxy. HTTP_X_FORWARDED_FOR may be a comma-
|
||||
# delimited list in the case of multiple chained proxies; the last
|
||||
# address which is not trusted is the originating IP.
|
||||
|
||||
def remote_ip
|
||||
if TRUSTED_PROXIES !~ @env['REMOTE_ADDR']
|
||||
return @env['REMOTE_ADDR']
|
||||
remote_addr_list = @env['REMOTE_ADDR'] && @env['REMOTE_ADDR'].split(',').collect(&:strip)
|
||||
|
||||
unless remote_addr_list.blank?
|
||||
not_trusted_addrs = remote_addr_list.reject {|addr| addr =~ TRUSTED_PROXIES}
|
||||
return not_trusted_addrs.first unless not_trusted_addrs.empty?
|
||||
end
|
||||
remote_ips = @env['HTTP_X_FORWARDED_FOR'] && @env['HTTP_X_FORWARDED_FOR'].split(',')
|
||||
|
||||
if @env.include? 'HTTP_CLIENT_IP'
|
||||
if @env.include? 'HTTP_X_FORWARDED_FOR'
|
||||
if remote_ips && !remote_ips.include?(@env['HTTP_CLIENT_IP'])
|
||||
# We don't know which came from the proxy, and which from the user
|
||||
raise ActionControllerError.new(<<EOM)
|
||||
IP spoofing attack?!
|
||||
|
@ -149,11 +152,11 @@ HTTP_CLIENT_IP=#{@env['HTTP_CLIENT_IP'].inspect}
|
|||
HTTP_X_FORWARDED_FOR=#{@env['HTTP_X_FORWARDED_FOR'].inspect}
|
||||
EOM
|
||||
end
|
||||
|
||||
return @env['HTTP_CLIENT_IP']
|
||||
end
|
||||
|
||||
if @env.include? 'HTTP_X_FORWARDED_FOR' then
|
||||
remote_ips = @env['HTTP_X_FORWARDED_FOR'].split(',')
|
||||
if remote_ips
|
||||
while remote_ips.size > 1 && TRUSTED_PROXIES =~ remote_ips.last.strip
|
||||
remote_ips.pop
|
||||
end
|
||||
|
|
|
@ -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 <tt>map.name_of_route options</tt>,
|
||||
|
@ -369,7 +373,7 @@ module ActionController
|
|||
|
||||
Routes = RouteSet.new
|
||||
|
||||
::Inflector.module_eval do
|
||||
ActiveSupport::Inflector.module_eval do
|
||||
# Ensures that routes are reloaded when Rails inflections are updated.
|
||||
def inflections_with_route_reloading(&block)
|
||||
returning(inflections_without_route_reloading(&block)) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -248,7 +248,7 @@ module ActionController
|
|||
end
|
||||
|
||||
def extract_value
|
||||
"#{local_name} = hash[:#{key}] && hash[:#{key}].collect { |path_component| CGI.escape(path_component.to_param, ActionController::Routing::Segment::UNSAFE_PCHAR) }.to_param #{"|| #{default.inspect}" if default}"
|
||||
"#{local_name} = hash[:#{key}] && Array(hash[:#{key}]).collect { |path_component| CGI.escape(path_component.to_param, ActionController::Routing::Segment::UNSAFE_PCHAR) }.to_param #{"|| #{default.inspect}" if default}"
|
||||
end
|
||||
|
||||
def default
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Action Controller: Exception caught</title>
|
||||
<style>
|
||||
|
|
|
@ -171,7 +171,7 @@ module ActionController #:nodoc:
|
|||
|
||||
# Was the response successful?
|
||||
def success?
|
||||
response_code == 200
|
||||
(200..299).include?(response_code)
|
||||
end
|
||||
|
||||
# Was the URL not found?
|
||||
|
@ -333,7 +333,7 @@ module ActionController #:nodoc:
|
|||
attr_reader :original_filename
|
||||
|
||||
# The content type of the "uploaded" file
|
||||
attr_reader :content_type
|
||||
attr_accessor :content_type
|
||||
|
||||
def initialize(path, content_type = Mime::TEXT, binary = false)
|
||||
raise "#{path} file does not exist" unless File.exist?(path)
|
||||
|
@ -413,6 +413,8 @@ module ActionController #:nodoc:
|
|||
get(@response.redirected_to.delete(:action), @response.redirected_to.stringify_keys)
|
||||
end
|
||||
|
||||
deprecate :follow_redirect => "If you wish to follow redirects, you should use integration tests"
|
||||
|
||||
def assigns(key = nil)
|
||||
if key.nil?
|
||||
@response.template.assigns
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -116,7 +116,7 @@ module ActionController #:nodoc:
|
|||
end
|
||||
|
||||
def apply_redirect_to(redirect_to_option) # :nodoc:
|
||||
redirect_to_option.is_a?(Symbol) ? self.send!(redirect_to_option) : redirect_to_option
|
||||
(redirect_to_option.is_a?(Symbol) && redirect_to_option != :back) ? self.send!(redirect_to_option) : redirect_to_option
|
||||
end
|
||||
|
||||
def apply_remaining_actions(options) # :nodoc:
|
||||
|
|
|
@ -2,7 +2,7 @@ module ActionPack #:nodoc:
|
|||
module VERSION #:nodoc:
|
||||
MAJOR = 2
|
||||
MINOR = 1
|
||||
TINY = 0
|
||||
TINY = 1
|
||||
|
||||
STRING = [MAJOR, MINOR, TINY].join('.')
|
||||
end
|
||||
|
|
10
vendor/rails/actionpack/lib/action_view/base.rb
vendored
10
vendor/rails/actionpack/lib/action_view/base.rb
vendored
|
@ -178,10 +178,13 @@ module ActionView #:nodoc:
|
|||
# that alert()s the caught exception (and then re-raises it).
|
||||
@@debug_rjs = false
|
||||
cattr_accessor :debug_rjs
|
||||
|
||||
|
||||
@@erb_variable = '_erbout'
|
||||
cattr_accessor :erb_variable
|
||||
|
||||
class << self
|
||||
deprecate :erb_variable= => 'The erb variable will no longer be configurable. Use the concat helper method instead of appending to it directly.'
|
||||
end
|
||||
|
||||
attr_internal :request
|
||||
|
||||
delegate :request_forgery_protection_token, :template, :params, :session, :cookies, :response, :headers,
|
||||
|
@ -253,6 +256,7 @@ If you are rendering a subtemplate, you must now use controller-like partial syn
|
|||
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)
|
||||
|
||||
if partial_layout = options.delete(:layout)
|
||||
|
@ -266,7 +270,7 @@ If you are rendering a subtemplate, you must now use controller-like partial syn
|
|||
end
|
||||
end
|
||||
elsif options[:file]
|
||||
render_file(options[:file], options[:use_full_path], options[:locals])
|
||||
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])
|
||||
elsif options[:partial]
|
||||
|
|
|
@ -485,21 +485,24 @@ module ActionView
|
|||
source = "#{@controller.request.relative_url_root}#{source}"
|
||||
end
|
||||
end
|
||||
source = rewrite_asset_path(source)
|
||||
|
||||
if include_host
|
||||
host = compute_asset_host(source)
|
||||
|
||||
if has_request && !host.blank? && host !~ %r{^[-a-z]+://}
|
||||
host = "#{@controller.request.protocol}#{host}"
|
||||
end
|
||||
|
||||
"#{host}#{source}"
|
||||
else
|
||||
source
|
||||
end
|
||||
rewrite_asset_path(source)
|
||||
end
|
||||
end
|
||||
|
||||
source = ActionView::Base.computed_public_paths[cache_key]
|
||||
|
||||
if include_host && source !~ %r{^[-a-z]+://}
|
||||
host = compute_asset_host(source)
|
||||
|
||||
if has_request && !host.blank? && host !~ %r{^[-a-z]+://}
|
||||
host = "#{@controller.request.protocol}#{host}"
|
||||
end
|
||||
|
||||
"#{host}#{source}"
|
||||
else
|
||||
source
|
||||
end
|
||||
end
|
||||
|
||||
# Pick an asset host for this source. Returns +nil+ if no host is set,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -129,7 +129,7 @@ module ActionView
|
|||
# label_tag 'name', nil, :class => 'small_label'
|
||||
# # => <label for="name" class="small_label">Name</label>
|
||||
def label_tag(name, text = nil, options = {})
|
||||
content_tag :label, text || name.humanize, { "for" => name }.update(options.stringify_keys)
|
||||
content_tag :label, text || name.to_s.humanize, { "for" => name }.update(options.stringify_keys)
|
||||
end
|
||||
|
||||
# Creates a hidden form input field used to transmit data that would be lost due to HTTP's statelessness or
|
||||
|
@ -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;",
|
||||
|
|
|
@ -80,10 +80,9 @@ module ActionView
|
|||
# return false;">Show me more</a>
|
||||
#
|
||||
def link_to_function(name, *args, &block)
|
||||
html_options = args.extract_options!
|
||||
html_options = args.extract_options!.symbolize_keys
|
||||
function = args[0] || ''
|
||||
|
||||
html_options.symbolize_keys!
|
||||
function = update_page(&block) if block_given?
|
||||
content_tag(
|
||||
"a", name,
|
||||
|
@ -111,10 +110,9 @@ module ActionView
|
|||
# page[:details].visual_effect :toggle_slide
|
||||
# end
|
||||
def button_to_function(name, *args, &block)
|
||||
html_options = args.extract_options!
|
||||
html_options = args.extract_options!.symbolize_keys
|
||||
function = args[0] || ''
|
||||
|
||||
html_options.symbolize_keys!
|
||||
function = update_page(&block) if block_given?
|
||||
tag(:input, html_options.merge({
|
||||
:type => "button", :value => name,
|
||||
|
@ -147,6 +145,8 @@ module ActionView
|
|||
javascript << '</script>'
|
||||
end
|
||||
|
||||
deprecate :define_javascript_functions=>"use javascript_include_tag instead"
|
||||
|
||||
# Escape carrier returns and single and double quotes for JavaScript segments.
|
||||
def escape_javascript(javascript)
|
||||
(javascript || '').gsub('\\','\0\0').gsub('</','<\/').gsub(/\r\n|\n|\r/, "\\n").gsub(/["']/) { |m| "\\#{m}" }
|
||||
|
|
|
@ -111,7 +111,7 @@ module ActionView
|
|||
(100..599).to_a)
|
||||
AJAX_OPTIONS = Set.new([ :before, :after, :condition, :url,
|
||||
:asynchronous, :method, :insertion, :position,
|
||||
:form, :with, :update, :script ]).merge(CALLBACKS)
|
||||
:form, :with, :update, :script, :type ]).merge(CALLBACKS)
|
||||
end
|
||||
|
||||
# Returns a link to a remote action defined by <tt>options[:url]</tt>
|
||||
|
@ -603,7 +603,7 @@ module ActionView
|
|||
# Example:
|
||||
#
|
||||
# # Generates:
|
||||
# # new Insertion.Bottom("list", "<li>Some item</li>");
|
||||
# # new Element.insert("list", { bottom: <li>Some item</li>" });
|
||||
# # new Effect.Highlight("list");
|
||||
# # ["status-indicator", "cancel-link"].each(Element.hide);
|
||||
# update_page do |page|
|
||||
|
@ -736,16 +736,16 @@ module ActionView
|
|||
#
|
||||
# # Insert the rendered 'navigation' partial just before the DOM
|
||||
# # element with ID 'content'.
|
||||
# # Generates: new Insertion.Before("content", "-- Contents of 'navigation' partial --");
|
||||
# # Generates: Element.insert("content", { before: "-- Contents of 'navigation' partial --" });
|
||||
# page.insert_html :before, 'content', :partial => 'navigation'
|
||||
#
|
||||
# # Add a list item to the bottom of the <ul> with ID 'list'.
|
||||
# # Generates: new Insertion.Bottom("list", "<li>Last item</li>");
|
||||
# # Generates: Element.insert("list", { bottom: "<li>Last item</li>" });
|
||||
# page.insert_html :bottom, 'list', '<li>Last item</li>'
|
||||
#
|
||||
def insert_html(position, id, *options_for_render)
|
||||
insertion = position.to_s.camelize
|
||||
call "new Insertion.#{insertion}", id, render(*options_for_render)
|
||||
content = javascript_object_for(render(*options_for_render))
|
||||
record "Element.insert(\"#{id}\", { #{position.to_s.downcase}: #{content} });"
|
||||
end
|
||||
|
||||
# Replaces the inner HTML of the DOM element with the given +id+.
|
||||
|
@ -1039,7 +1039,7 @@ module ActionView
|
|||
|
||||
js_options['asynchronous'] = options[:type] != :synchronous
|
||||
js_options['method'] = method_option_to_s(options[:method]) if options[:method]
|
||||
js_options['insertion'] = "Insertion.#{options[:position].to_s.camelize}" if options[:position]
|
||||
js_options['insertion'] = "'#{options[:position].to_s.downcase}'" if options[:position]
|
||||
js_options['evalScripts'] = options[:script].nil? || options[:script]
|
||||
|
||||
if options[:form]
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
require 'cgi'
|
||||
require 'erb'
|
||||
require 'set'
|
||||
|
||||
module ActionView
|
||||
module Helpers #:nodoc:
|
||||
|
@ -8,7 +9,8 @@ module ActionView
|
|||
module TagHelper
|
||||
include ERB::Util
|
||||
|
||||
BOOLEAN_ATTRIBUTES = Set.new(%w(disabled readonly multiple))
|
||||
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
|
||||
|
@ -37,7 +39,7 @@ module ActionView
|
|||
# tag("img", { :src => "open & shut.png" }, false, false)
|
||||
# # => <img src="open & shut.png" />
|
||||
def tag(name, options = nil, open = false, escape = true)
|
||||
"<#{name}#{tag_options(options, escape) if options}" + (open ? ">" : " />")
|
||||
"<#{name}#{tag_options(options, escape) if options}#{open ? ">" : " />"}"
|
||||
end
|
||||
|
||||
# Returns an HTML block tag of type +name+ surrounding the +content+. Add
|
||||
|
@ -114,7 +116,6 @@ module ActionView
|
|||
if escape
|
||||
options.each do |key, value|
|
||||
next unless value
|
||||
key = key.to_s
|
||||
value = BOOLEAN_ATTRIBUTES.include?(key) ? key : escape_once(value)
|
||||
attrs << %(#{key}="#{value}")
|
||||
end
|
||||
|
|
|
@ -464,7 +464,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
|
||||
)
|
||||
|
|
|
@ -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)
|
||||
|
@ -444,7 +442,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
|
||||
"<script type=\"#{Mime::JS}\">eval(unescape('#{string}'))</script>"
|
||||
|
|
|
@ -22,10 +22,10 @@ module ActionView #:nodoc:
|
|||
end
|
||||
|
||||
def render_member(object)
|
||||
@locals[@counter_name] += 1
|
||||
@locals[:object] = @locals[@variable_name] = object
|
||||
|
||||
template = render_template
|
||||
@locals[@counter_name] += 1
|
||||
@locals.delete(@variable_name)
|
||||
@locals.delete(:object)
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue