aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib
diff options
context:
space:
mode:
Diffstat (limited to 'activesupport/lib')
-rw-r--r--activesupport/lib/active_support.rb1
-rw-r--r--activesupport/lib/active_support/core_ext/class/attribute.rb36
-rw-r--r--activesupport/lib/active_support/core_ext/string/output_safety.rb106
-rw-r--r--activesupport/lib/active_support/rescuable.rb8
4 files changed, 126 insertions, 25 deletions
diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb
index 833ae351b9..ae31d191c0 100644
--- a/activesupport/lib/active_support.rb
+++ b/activesupport/lib/active_support.rb
@@ -67,5 +67,6 @@ module ActiveSupport
autoload :XmlMini
end
+ autoload :SafeBuffer, "active_support/core_ext/string/output_safety"
autoload :TestCase
end
diff --git a/activesupport/lib/active_support/core_ext/class/attribute.rb b/activesupport/lib/active_support/core_ext/class/attribute.rb
new file mode 100644
index 0000000000..d74219cb93
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/class/attribute.rb
@@ -0,0 +1,36 @@
+require 'active_support/core_ext/object/metaclass'
+require 'active_support/core_ext/module/delegation'
+
+class Class
+ # Declare a class-level attribute whose value is inheritable and
+ # overwritable by subclasses:
+ #
+ # class Base
+ # class_attribute :setting
+ # end
+ #
+ # class Subclass < Base
+ # end
+ #
+ # Base.setting = true
+ # Subclass.setting # => true
+ # Subclass.setting = false
+ # Subclass.setting # => false
+ # Base.setting # => true
+ #
+ # This matches normal Ruby method inheritance: think of writing an attribute
+ # on a subclass as overriding the reader method.
+ #
+ # For convenience, a query method is defined as well:
+ #
+ # Subclass.setting? # => false
+ def class_attribute(*attrs)
+ attrs.each do |attr|
+ metaclass.send(:define_method, attr) { }
+ metaclass.send(:define_method, "#{attr}?") { !!send(attr) }
+ metaclass.send(:define_method, "#{attr}=") do |value|
+ metaclass.send(:define_method, attr) { value }
+ end
+ end
+ end
+end
diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb
index ceed90ce79..3977971e8d 100644
--- a/activesupport/lib/active_support/core_ext/string/output_safety.rb
+++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb
@@ -1,3 +1,53 @@
+require "erb"
+
+class ERB
+ module Util
+ HTML_ESCAPE = { '&' => '&amp;', '>' => '&gt;', '<' => '&lt;', '"' => '&quot;' }
+ JSON_ESCAPE = { '&' => '\u0026', '>' => '\u003E', '<' => '\u003C' }
+
+ # A utility method for escaping HTML tag characters.
+ # This method is also aliased as <tt>h</tt>.
+ #
+ # In your ERb templates, use this method to escape any unsafe content. For example:
+ # <%=h @person.name %>
+ #
+ # ==== Example:
+ # puts html_escape("is a > 0 & a < 10?")
+ # # => is a &gt; 0 &amp; a &lt; 10?
+ def html_escape(s)
+ s = s.to_s
+ if s.html_safe?
+ s
+ else
+ s.gsub(/[&"><]/) { |special| HTML_ESCAPE[special] }.html_safe
+ end
+ end
+
+ undef :h
+ alias h html_escape
+
+ module_function :html_escape
+ module_function :h
+
+ # A utility method for escaping HTML entities in JSON strings.
+ # This method is also aliased as <tt>j</tt>.
+ #
+ # In your ERb templates, use this method to escape any HTML entities:
+ # <%=j @person.to_json %>
+ #
+ # ==== Example:
+ # puts json_escape("is a > 0 & a < 10?")
+ # # => is a \u003E 0 \u0026 a \u003C 10?
+ def json_escape(s)
+ s.to_s.gsub(/[&"><]/) { |special| JSON_ESCAPE[special] }
+ end
+
+ alias j json_escape
+ module_function :j
+ module_function :json_escape
+ end
+end
+
class Object
def html_safe?
false
@@ -10,32 +60,46 @@ class Fixnum
end
end
-class String
- attr_accessor :_rails_html_safe
- alias html_safe? _rails_html_safe
+module ActiveSupport #:nodoc:
+ class SafeBuffer < String
+ alias safe_concat concat
- def html_safe!
- @_rails_html_safe = true
- self
- end
+ def concat(value)
+ if value.html_safe?
+ super(value)
+ else
+ super(ERB::Util.h(value))
+ end
+ end
- def html_safe
- dup.html_safe!
- end
+ def +(other)
+ dup.concat(other)
+ end
+
+ def <<(value)
+ self.concat(value)
+ end
+
+ def html_safe?
+ true
+ end
+
+ def html_safe
+ self
+ end
- alias original_plus +
- def +(other)
- result = original_plus(other)
- result._rails_html_safe = html_safe? && other.html_safe?
- result
+ def to_s
+ self
+ end
end
+end
- alias original_concat <<
- alias safe_concat <<
- def <<(other)
- @_rails_html_safe = false unless other.html_safe?
- result = original_concat(other)
+class String
+ def html_safe!
+ raise "You can't call html_safe! on a String"
end
- alias concat <<
+ def html_safe
+ ActiveSupport::SafeBuffer.new(self)
+ end
end \ No newline at end of file
diff --git a/activesupport/lib/active_support/rescuable.rb b/activesupport/lib/active_support/rescuable.rb
index 6e660f8647..e4c1651acf 100644
--- a/activesupport/lib/active_support/rescuable.rb
+++ b/activesupport/lib/active_support/rescuable.rb
@@ -1,4 +1,4 @@
-require 'active_support/core_ext/class/inheritable_attributes'
+require 'active_support/core_ext/class/attribute'
require 'active_support/core_ext/proc'
require 'active_support/core_ext/string/inflections'
require 'active_support/core_ext/array/extract_options'
@@ -9,7 +9,7 @@ module ActiveSupport
extend Concern
included do
- class_inheritable_accessor :rescue_handlers
+ class_attribute :rescue_handlers
self.rescue_handlers = []
end
@@ -67,7 +67,7 @@ module ActiveSupport
end
# put the new handler at the end because the list is read in reverse
- rescue_handlers << [key, options[:with]]
+ self.rescue_handlers += [[key, options[:with]]]
end
end
end
@@ -83,7 +83,7 @@ module ActiveSupport
def handler_for_rescue(exception)
# We go from right to left because pairs are pushed onto rescue_handlers
# as rescue_from declarations are found.
- _, rescuer = rescue_handlers.reverse.detect do |klass_name, handler|
+ _, rescuer = self.class.rescue_handlers.reverse.detect do |klass_name, handler|
# The purpose of allowing strings in rescue_from is to support the
# declaration of handler associations for exception classes whose
# definition is yet unknown.