New Version

Sync with Latest Instiki Trunk.
Migrate to Rails 1.2.5.
Bump version number.
This commit is contained in:
Jacques Distler 2007-10-15 12:16:54 -05:00
parent de125367b0
commit 207fb1f7f2
120 changed files with 2592 additions and 662 deletions

View file

@ -1,3 +1,19 @@
*1.4.4* (October 12th, 2007)
* Backport: allow array and hash query parameters. Array route parameters are converted/to/a/path as before. #6765, #7047, #7462 [bgipsy, Jeremy McAnally, Dan Kubb, brendan, Diego Algorta Casamayou]
*1.4.3* (October 4th, 2007)
* Demote Hash#to_xml to use XmlSimple#xml_in_string so it can't read files or stdin. #8453 [candlerb, Jeremy Kemper]
* Document Object#blank?. #6491 [Chris Mear]
* Update Dependencies to ignore constants inherited from ancestors. Closes #6951. [Nicholas Seckar]
* Improved multibyte performance by relying less on exception raising #8159 [Blaine]
*1.4.2* (March 12th, 2007)
* Ruby 1.8.6 and 1.9 define private Time#to_date and #to_datetime; make them

View file

@ -1,5 +1,11 @@
class Object #:nodoc:
# "", " ", nil, [], and {} are blank
class Object
# An object is blank if it's nil, empty, or a whitespace string.
# For example, "", " ", nil, [], and {} are blank.
#
# This simplifies
# if !address.nil? && !address.empty?
# to
# if !address.blank?
def blank?
if respond_to?(:empty?) && respond_to?(:strip)
empty? or strip.empty?
@ -47,4 +53,4 @@ class Numeric #:nodoc:
def blank?
false
end
end
end

View file

@ -1,5 +1,44 @@
require 'date'
require 'xml_simple'
require 'cgi'
# Extensions needed for Hash#to_query
class Object
def to_param #:nodoc:
to_s
end
def to_query(key) #:nodoc:
"#{CGI.escape(key.to_s)}=#{CGI.escape(to_param.to_s)}"
end
end
class Array
def to_query(key) #:nodoc:
collect { |value| value.to_query("#{key}[]") }.sort * '&'
end
end
# Locked down XmlSimple#xml_in_string
class XmlSimple
# Same as xml_in but doesn't try to smartly shoot itself in the foot.
def xml_in_string(string, options = nil)
handle_options('in', options)
@doc = parse(string)
result = collapse(@doc.root)
if @options['keeproot']
merge({}, @doc.root.name, result)
else
result
end
end
def self.xml_in_string(string, options = nil)
new.xml_in_string(string, options)
end
end
module ActiveSupport #:nodoc:
module CoreExtensions #:nodoc:
@ -27,6 +66,12 @@ module ActiveSupport #:nodoc:
klass.extend(ClassMethods)
end
def to_query(namespace = nil)
collect do |key, value|
value.to_query(namespace ? "#{namespace}[#{key}]" : key)
end.sort * '&'
end
def to_xml(options = {})
options[:indent] ||= 2
options.reverse_merge!({ :builder => Builder::XmlMarkup.new(:indent => options[:indent]),
@ -81,14 +126,14 @@ module ActiveSupport #:nodoc:
module ClassMethods
def from_xml(xml)
# TODO: Refactor this into something much cleaner that doesn't rely on XmlSimple
undasherize_keys(typecast_xml_value(XmlSimple.xml_in(xml,
undasherize_keys(typecast_xml_value(XmlSimple.xml_in_string(xml,
'forcearray' => false,
'forcecontent' => true,
'keeproot' => true,
'contentkey' => '__content__')
))
))
end
def create_from_xml(xml)
ActiveSupport::Deprecation.warn("Hash.create_from_xml has been renamed to Hash.from_xml", caller)
from_xml(xml)

View file

@ -18,4 +18,18 @@ class Module
parents << Object unless parents.include? Object
parents
end
# Return the constants that have been defined locally by this object and not
# in an ancestor. This method may miss some constants if their definition in
# the ancestor is identical to their definition in the receiver.
def local_constants
inherited = {}
ancestors.each do |anc|
next if anc == self
anc.constants.each { |const| inherited[const] = anc.const_get(const) }
end
constants.select do |const|
! inherited.key?(const) || inherited[const].object_id != const_get(const).object_id
end
end
end

View file

@ -318,13 +318,13 @@ module Dependencies #:nodoc:
watch_frames = descs.collect do |desc|
if desc.is_a? Module
mod_name = desc.name
initial_constants = desc.constants
initial_constants = desc.local_constants
elsif desc.is_a?(String) || desc.is_a?(Symbol)
mod_name = desc.to_s
# Handle the case where the module has yet to be defined.
initial_constants = if qualified_const_defined?(mod_name)
mod_name.constantize.constants
mod_name.constantize.local_constants
else
[]
end
@ -349,7 +349,7 @@ module Dependencies #:nodoc:
mod = mod_name.constantize
next [] unless mod.is_a? Module
new_constants = mod.constants - prior_constants
new_constants = mod.local_constants - prior_constants
# Make sure no other frames takes credit for these constants.
constant_watch_stack.each do |frame_name, constants|

View file

@ -23,12 +23,14 @@ module ActiveSupport
"\n" => '\n',
"\r" => '\r',
"\t" => '\t',
'"' => '\"',
'\\' => '\\\\'
'"' => '\"',
'\\' => '\\\\',
'<' => '\\074',
'>' => '\\076'
}
define_encoder String do |string|
'"' + string.gsub(/[\010\f\n\r\t"\\]/) { |s|
'"' + string.gsub(/[\010\f\n\r\t"\\<>]/) { |s|
ESCAPED_CHARS[s]
}.gsub(/([\xC0-\xDF][\x80-\xBF]|
[\xE0-\xEF][\x80-\xBF]{2}|

View file

@ -43,7 +43,7 @@ module ActiveSupport::Multibyte #:nodoc:
# Create a new Chars instance.
def initialize(str)
@string = (str.string rescue str)
@string = str.respond_to?(:string) ? str.string : str
end
# Returns -1, 0 or +1 depending on whether the Chars object is to be sorted before, equal or after the
@ -70,18 +70,18 @@ module ActiveSupport::Multibyte #:nodoc:
def method_missing(m, *a, &b)
begin
# Simulate methods with a ! at the end because we can't touch the enclosed string from the handlers.
if m.to_s =~ /^(.*)\!$/
if m.to_s =~ /^(.*)\!$/ && handler.respond_to?($1)
result = handler.send($1, @string, *a, &b)
if result == @string
result = nil
else
@string.replace result
end
else
elsif handler.respond_to?(m)
result = handler.send(m, @string, *a, &b)
else
result = @string.send(m, *a, &b)
end
rescue NoMethodError
result = @string.send(m, *a, &b)
rescue Handlers::EncodingError
@string.replace handler.tidy_bytes(@string)
retry
@ -126,4 +126,4 @@ begin
ActiveSupport::Multibyte::Chars.handler = ActiveSupport::Multibyte::Handlers::UTF8HandlerProc
rescue LoadError
ActiveSupport::Multibyte::Chars.handler = ActiveSupport::Multibyte::Handlers::UTF8Handler
end
end

View file

@ -2,7 +2,7 @@ module ActiveSupport
module VERSION #:nodoc:
MAJOR = 1
MINOR = 4
TINY = 2
TINY = 4
STRING = [MAJOR, MINOR, TINY].join('.')
end

View file

@ -470,3 +470,40 @@ class HashToXmlTest < Test::Unit::TestCase
end
end
end
class QueryTest < Test::Unit::TestCase
def test_simple_conversion
assert_query_equal 'a=10', :a => 10
end
def test_cgi_escaping
assert_query_equal 'a%3Ab=c+d', 'a:b' => 'c d'
end
def test_nil_parameter_value
empty = Object.new
def empty.to_param; nil end
assert_query_equal 'a=', 'a' => empty
end
def test_nested_conversion
assert_query_equal 'person%5Bname%5D=Nicholas&person%5Blogin%5D=seckar',
:person => {:name => 'Nicholas', :login => 'seckar'}
end
def test_multiple_nested
assert_query_equal 'account%5Bperson%5D%5Bid%5D=20&person%5Bid%5D=10',
:person => {:id => 10}, :account => {:person => {:id => 20}}
end
def test_array_values
assert_query_equal 'person%5Bid%5D%5B%5D=10&person%5Bid%5D%5B%5D=20',
:person => {:id => [10, 20]}
end
private
def assert_query_equal(expected, actual, message = nil)
assert_equal expected.split('&').sort, actual.to_query.split('&').sort
end
end

View file

@ -1,10 +1,14 @@
require File.dirname(__FILE__) + '/../abstract_unit'
module One
Constant1 = "Hello World"
Constant2 = "What's up?"
end
class Ab
include One
Constant1 = "Hello World" # Will have different object id than One::Constant1
Constant3 = "Goodbye World"
end
module Xy
@ -91,6 +95,10 @@ class ModuleTest < Test::Unit::TestCase
assert_equal [Yz::Zy, Yz, Object], Yz::Zy::Cd.parents
assert_equal [Yz, Object], Yz::Zy.parents
end
def test_local_constants
assert_equal %w(Constant1 Constant3), Ab.local_constants.sort
end
def test_as_load_path
assert_equal 'yz/zy', Yz::Zy.as_load_path

View file

@ -9,6 +9,10 @@ module ModuleWithMissing
end
end
module ModuleWithConstant
InheritedConstant = "Hello"
end
class DependenciesTest < Test::Unit::TestCase
def teardown
Dependencies.clear
@ -574,6 +578,13 @@ class DependenciesTest < Test::Unit::TestCase
Object.send :remove_const, :M rescue nil
end
def test_new_constants_in_with_inherited_constants
m = Dependencies.new_constants_in(:Object) do
Object.send :include, ModuleWithConstant
end
assert_equal [], m
end
def test_file_with_multiple_constants_and_require_dependency
with_loading 'autoloading_fixtures' do
assert ! defined?(MultipleConstantFile)

View file

@ -0,0 +1,97 @@
require File.dirname(__FILE__) + '/abstract_unit'
class JsonFoo
def initialize(a, b)
@a, @b = a, b
end
end
class TestJSONEmitters < Test::Unit::TestCase
TrueTests = [[ true, %(true) ]]
FalseTests = [[ false, %(false) ]]
NilTests = [[ nil, %(null) ]]
NumericTests = [[ 1, %(1) ],
[ 2.5, %(2.5) ]]
StringTests = [[ 'this is the string', %("this is the string") ],
[ 'a "string" with quotes<script>', %("a \\"string\\" with quotes\\074script\\076") ]]
ArrayTests = [[ ['a', 'b', 'c'], %([\"a\", \"b\", \"c\"]) ],
[ [1, 'a', :b, nil, false], %([1, \"a\", \"b\", null, false]) ]]
SymbolTests = [[ :a, %("a") ],
[ :this, %("this") ],
[ :"a b", %("a b") ]]
ObjectTests = [[ JsonFoo.new(1, 2), %({\"a\": 1, \"b\": 2}) ]]
VariableTests = [[ ActiveSupport::JSON::Variable.new('foo'), 'foo'],
[ ActiveSupport::JSON::Variable.new('alert("foo")'), 'alert("foo")']]
RegexpTests = [[ /^a/, '/^a/' ], [/^\w{1,2}[a-z]+/ix, '/^\\w{1,2}[a-z]+/ix']]
constants.grep(/Tests$/).each do |class_tests|
define_method("test_#{class_tests[0..-6].downcase}") do
self.class.const_get(class_tests).each do |pair|
assert_equal pair.last, pair.first.to_json
end
end
end
def setup
unquote(false)
end
def teardown
unquote(true)
end
def test_hash_encoding
assert_equal %({\"a\": \"b\"}), { :a => :b }.to_json
assert_equal %({\"a\": 1}), { 'a' => 1 }.to_json
assert_equal %({\"a\": [1, 2]}), { 'a' => [1,2] }.to_json
sorted_json =
'{' + {:a => :b, :c => :d}.to_json[1..-2].split(', ').sort.join(', ') + '}'
assert_equal %({\"a\": \"b\", \"c\": \"d\"}), sorted_json
end
def test_utf8_string_encoded_properly_when_kcode_is_utf8
old_kcode, $KCODE = $KCODE, 'UTF8'
assert_equal '"\\u20ac2.99"', '€2.99'.to_json
assert_equal '"\\u270e\\u263a"', '✎☺'.to_json
ensure
$KCODE = old_kcode
end
def test_exception_raised_when_encoding_circular_reference
a = [1]
a << a
assert_raises(ActiveSupport::JSON::CircularReferenceError) { a.to_json }
end
def test_unquote_hash_key_identifiers
values = {0 => 0, 1 => 1, :_ => :_, "$" => "$", "a" => "a", :A => :A, :A0 => :A0, "A0B" => "A0B"}
assert_equal %({"a": "a"}), {"a"=>"a"}.to_json
assert_equal %({0: 0}), { 0 => 0 }.to_json
assert_equal %({"_": "_"}), {:_ =>:_ }.to_json
assert_equal %({"$": "$"}), {"$"=>"$"}.to_json
unquote(true) do
assert_equal %({a: "a"}), {"a"=>"a"}.to_json
assert_equal %({0: 0}), { 0 => 0 }.to_json
assert_equal %({_: "_"}), {:_ =>:_ }.to_json
assert_equal %({$: "$"}), {"$"=>"$"}.to_json
end
end
protected
def unquote(value)
previous_value = ActiveSupport::JSON.unquote_hash_key_identifiers
ActiveSupport::JSON.unquote_hash_key_identifiers = value
yield if block_given?
ensure
ActiveSupport::JSON.unquote_hash_key_identifiers = previous_value if block_given?
end
end