mirror of
https://github.com/github/rails.git
synced 2026-04-26 03:00:59 -04:00
Merge branch 'master' into arel
This commit is contained in:
@@ -87,8 +87,9 @@ module ActionController #:nodoc:
|
||||
def delete(key, options = {})
|
||||
options.symbolize_keys!
|
||||
options[:path] = "/" unless options.has_key?(:path)
|
||||
super(key.to_s)
|
||||
value = super(key.to_s)
|
||||
@controller.response.delete_cookie(key, options)
|
||||
value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -16,7 +16,7 @@ module ActionController
|
||||
logger.info("Redirected to #{url}") if logger && logger.info?
|
||||
self.status = status
|
||||
self.location = url.gsub(/[\r\n]/, '')
|
||||
self.response_body = "<html><body>You are being <a href=\"#{CGI.escapeHTML(url)}\">redirected</a>.</body></html>"
|
||||
self.response_body = "<html><body>You are being <a href=\"#{ERB::Util.h(url)}\">redirected</a>.</body></html>"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -35,7 +35,7 @@ module ActionController #:nodoc:
|
||||
end
|
||||
|
||||
def cookies
|
||||
@response.cookies
|
||||
@request.cookies.merge(@response.cookies)
|
||||
end
|
||||
|
||||
def redirect_to_url
|
||||
|
||||
@@ -396,8 +396,12 @@ module ActionDispatch
|
||||
# Delegate unhandled messages to the current session instance.
|
||||
def method_missing(sym, *args, &block)
|
||||
reset! unless @integration_session
|
||||
returning @integration_session.__send__(sym, *args, &block) do
|
||||
copy_session_variables!
|
||||
if @integration_session.respond_to?(sym)
|
||||
returning @integration_session.__send__(sym, *args, &block) do
|
||||
copy_session_variables!
|
||||
end
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -167,7 +167,7 @@ module ActionView #:nodoc:
|
||||
module Subclasses
|
||||
end
|
||||
|
||||
include Helpers, Rendering, Partials, ::ERB::Util
|
||||
include Helpers, Rendering, Partials, ::ERB::Util, ActiveSupport::Configurable
|
||||
|
||||
extend ActiveSupport::Memoizable
|
||||
|
||||
|
||||
@@ -133,9 +133,13 @@ module ActionView
|
||||
# change. You can use something like Live HTTP Headers for Firefox to verify
|
||||
# that the cache is indeed working.
|
||||
module AssetTagHelper
|
||||
ASSETS_DIR = defined?(Rails.public_path) ? Rails.public_path : "public"
|
||||
JAVASCRIPTS_DIR = "#{ASSETS_DIR}/javascripts"
|
||||
STYLESHEETS_DIR = "#{ASSETS_DIR}/stylesheets"
|
||||
assets_dir = defined?(Rails.public_path) ? Rails.public_path : "public"
|
||||
ActionView::DEFAULT_CONFIG = {
|
||||
:assets_dir => assets_dir,
|
||||
:javascripts_dir => "#{assets_dir}/javascripts",
|
||||
:stylesheets_dir => "#{assets_dir}/stylesheets",
|
||||
}
|
||||
|
||||
JAVASCRIPT_DEFAULT_SOURCES = ['prototype', 'effects', 'dragdrop', 'controls'].freeze unless const_defined?(:JAVASCRIPT_DEFAULT_SOURCES)
|
||||
|
||||
# Returns a link tag that browsers and news readers can use to auto-detect
|
||||
@@ -280,7 +284,7 @@ module ActionView
|
||||
|
||||
if concat || (ActionController::Base.perform_caching && cache)
|
||||
joined_javascript_name = (cache == true ? "all" : cache) + ".js"
|
||||
joined_javascript_path = File.join(joined_javascript_name[/^#{File::SEPARATOR}/] ? ASSETS_DIR : JAVASCRIPTS_DIR, joined_javascript_name)
|
||||
joined_javascript_path = File.join(joined_javascript_name[/^#{File::SEPARATOR}/] ? config.assets_dir : config.javascripts_dir, joined_javascript_name)
|
||||
|
||||
unless ActionController::Base.perform_caching && File.exists?(joined_javascript_path)
|
||||
write_asset_file_contents(joined_javascript_path, compute_javascript_paths(sources, recursive))
|
||||
@@ -431,7 +435,7 @@ module ActionView
|
||||
|
||||
if concat || (ActionController::Base.perform_caching && cache)
|
||||
joined_stylesheet_name = (cache == true ? "all" : cache) + ".css"
|
||||
joined_stylesheet_path = File.join(joined_stylesheet_name[/^#{File::SEPARATOR}/] ? ASSETS_DIR : STYLESHEETS_DIR, joined_stylesheet_name)
|
||||
joined_stylesheet_path = File.join(joined_stylesheet_name[/^#{File::SEPARATOR}/] ? config.assets_dir : config.stylesheets_dir, joined_stylesheet_name)
|
||||
|
||||
unless ActionController::Base.perform_caching && File.exists?(joined_stylesheet_path)
|
||||
write_asset_file_contents(joined_stylesheet_path, compute_stylesheet_paths(sources, recursive))
|
||||
@@ -630,11 +634,11 @@ module ActionView
|
||||
# Prefix with <tt>/dir/</tt> if lacking a leading +/+. Account for relative URL
|
||||
# roots. Rewrite the asset path for cache-busting asset ids. Include
|
||||
# asset host, if configured, with the correct request protocol.
|
||||
def compute_public_path(source, dir, ext = nil, include_host = true)
|
||||
def compute_public_path(source, dir, ext = nil, include_host = true)
|
||||
has_request = @controller.respond_to?(:request)
|
||||
|
||||
source_ext = File.extname(source)[1..-1]
|
||||
if ext && !is_uri?(source) && (source_ext.blank? || (ext != source_ext && File.exist?(File.join(ASSETS_DIR, dir, "#{source}.#{ext}"))))
|
||||
if ext && !is_uri?(source) && (source_ext.blank? || (ext != source_ext && File.exist?(File.join(config.assets_dir, dir, "#{source}.#{ext}"))))
|
||||
source += ".#{ext}"
|
||||
end
|
||||
|
||||
@@ -700,7 +704,7 @@ module ActionView
|
||||
if @@cache_asset_timestamps && (asset_id = @@asset_timestamps_cache[source])
|
||||
asset_id
|
||||
else
|
||||
path = File.join(ASSETS_DIR, source)
|
||||
path = File.join(config.assets_dir, source)
|
||||
asset_id = File.exist?(path) ? File.mtime(path).to_i.to_s : ''
|
||||
|
||||
if @@cache_asset_timestamps
|
||||
@@ -743,20 +747,20 @@ module ActionView
|
||||
|
||||
def expand_javascript_sources(sources, recursive = false)
|
||||
if sources.include?(:all)
|
||||
all_javascript_files = collect_asset_files(JAVASCRIPTS_DIR, ('**' if recursive), '*.js')
|
||||
all_javascript_files = collect_asset_files(config.javascripts_dir, ('**' if recursive), '*.js')
|
||||
((determine_source(:defaults, @@javascript_expansions).dup & all_javascript_files) + all_javascript_files).uniq
|
||||
else
|
||||
expanded_sources = sources.collect do |source|
|
||||
determine_source(source, @@javascript_expansions)
|
||||
end.flatten
|
||||
expanded_sources << "application" if sources.include?(:defaults) && File.exist?(File.join(JAVASCRIPTS_DIR, "application.js"))
|
||||
expanded_sources << "application" if sources.include?(:defaults) && File.exist?(File.join(config.javascripts_dir, "application.js"))
|
||||
expanded_sources
|
||||
end
|
||||
end
|
||||
|
||||
def expand_stylesheet_sources(sources, recursive)
|
||||
if sources.first == :all
|
||||
collect_asset_files(STYLESHEETS_DIR, ('**' if recursive), '*.css')
|
||||
collect_asset_files(config.stylesheets_dir, ('**' if recursive), '*.css')
|
||||
else
|
||||
sources.collect do |source|
|
||||
determine_source(source, @@stylesheet_expansions)
|
||||
@@ -803,7 +807,7 @@ module ActionView
|
||||
end
|
||||
|
||||
def asset_file_path(path)
|
||||
File.join(ASSETS_DIR, path.split('?').first)
|
||||
File.join(config.assets_dir, path.split('?').first)
|
||||
end
|
||||
|
||||
def asset_file_path!(path)
|
||||
|
||||
@@ -83,7 +83,7 @@ module ActionView
|
||||
options
|
||||
when Hash
|
||||
options = { :only_path => options[:host].nil? }.update(options.symbolize_keys)
|
||||
escape = options.key?(:escape) ? options.delete(:escape) : true
|
||||
escape = options.key?(:escape) ? options.delete(:escape) : false
|
||||
@controller.send(:url_for, options)
|
||||
when :back
|
||||
escape = false
|
||||
@@ -93,7 +93,7 @@ module ActionView
|
||||
polymorphic_path(options)
|
||||
end
|
||||
|
||||
(escape ? escape_once(url) : url).html_safe!
|
||||
escape ? escape_once(url).html_safe! : url
|
||||
end
|
||||
|
||||
# Creates a link tag of the given +name+ using a URL created by the set
|
||||
|
||||
@@ -5,7 +5,7 @@ module ActionView #:nodoc:
|
||||
if value.html_safe?
|
||||
super(value)
|
||||
else
|
||||
super(CGI.escapeHTML(value))
|
||||
super(ERB::Util.h(value))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -118,6 +118,13 @@ class CookieTest < ActionController::TestCase
|
||||
assert_equal %w{1 2 3}, jar["pages"]
|
||||
end
|
||||
|
||||
def test_cookiejar_delete_removes_item_and_returns_its_value
|
||||
@request.cookies["user_name"] = "david"
|
||||
@controller.response = @response
|
||||
jar = ActionController::CookieJar.new(@controller)
|
||||
assert_equal "david", jar.delete("user_name")
|
||||
end
|
||||
|
||||
def test_delete_cookie_with_path
|
||||
get :delete_cookie_with_path
|
||||
assert_cookie_header "user_name=; path=/beaten; expires=Thu, 01-Jan-1970 00:00:00 GMT"
|
||||
|
||||
@@ -199,6 +199,24 @@ class IntegrationTestTest < Test::Unit::TestCase
|
||||
assert_equal ::ActionController::Integration::Session, session2.class
|
||||
assert_not_equal session1, session2
|
||||
end
|
||||
|
||||
# RSpec mixes Matchers (which has a #method_missing) into
|
||||
# IntegrationTest's superclass. Make sure IntegrationTest does not
|
||||
# try to delegate these methods to the session object.
|
||||
def test_does_not_prevent_method_missing_passing_up_to_ancestors
|
||||
mixin = Module.new do
|
||||
def method_missing(name, *args)
|
||||
name.to_s == 'foo' ? 'pass' : super
|
||||
end
|
||||
end
|
||||
@test.class.superclass.__send__(:include, mixin)
|
||||
begin
|
||||
assert_equal 'pass', @test.foo
|
||||
ensure
|
||||
# leave other tests as unaffected as possible
|
||||
mixin.__send__(:remove_method, :method_missing)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Tests that integration tests don't call Controller test methods for processing.
|
||||
|
||||
@@ -108,6 +108,11 @@ XML
|
||||
head :created, :location => 'created resource'
|
||||
end
|
||||
|
||||
def delete_cookie
|
||||
cookies.delete("foo")
|
||||
render :nothing => true
|
||||
end
|
||||
|
||||
private
|
||||
def rescue_action(e)
|
||||
raise e
|
||||
@@ -512,6 +517,18 @@ XML
|
||||
assert @request.params[:foo].blank?
|
||||
end
|
||||
|
||||
def test_should_have_knowledge_of_client_side_cookie_state_even_if_they_are_not_set
|
||||
@request.cookies['foo'] = 'bar'
|
||||
get :no_op
|
||||
assert_equal 'bar', cookies['foo']
|
||||
end
|
||||
|
||||
def test_should_detect_if_cookie_is_deleted
|
||||
@request.cookies['foo'] = 'bar'
|
||||
get :delete_cookie
|
||||
assert_nil cookies['foo']
|
||||
end
|
||||
|
||||
%w(controller response request).each do |variable|
|
||||
%w(get post put delete head process).each do |method|
|
||||
define_method("test_#{variable}_missing_for_#{method}_raises_error") do
|
||||
|
||||
@@ -26,11 +26,11 @@ class ActionController::TestSessionTest < ActiveSupport::TestCase
|
||||
assert_equal('value', session[:key])
|
||||
end
|
||||
|
||||
def test_calling_delete_removes_item
|
||||
def test_calling_delete_removes_item_and_returns_its_value
|
||||
session = ActionController::TestSession.new
|
||||
session[:key] = 'value'
|
||||
assert_equal('value', session[:key])
|
||||
session.delete(:key)
|
||||
assert_equal('value', session.delete(:key))
|
||||
assert_nil(session[:key])
|
||||
end
|
||||
|
||||
|
||||
@@ -3,6 +3,13 @@ require 'abstract_unit'
|
||||
class AssetTagHelperTest < ActionView::TestCase
|
||||
tests ActionView::Helpers::AssetTagHelper
|
||||
|
||||
DEFAULT_CONFIG = ActionView::DEFAULT_CONFIG.merge(
|
||||
:assets_dir => File.dirname(__FILE__) + "/../fixtures/public",
|
||||
:javascripts_dir => File.dirname(__FILE__) + "/../fixtures/public/javascripts",
|
||||
:stylesheets_dir => File.dirname(__FILE__) + "/../fixtures/public/stylesheets")
|
||||
|
||||
include ActiveSupport::Configurable
|
||||
|
||||
def setup
|
||||
super
|
||||
silence_warnings do
|
||||
@@ -872,6 +879,9 @@ end
|
||||
class AssetTagHelperNonVhostTest < ActionView::TestCase
|
||||
tests ActionView::Helpers::AssetTagHelper
|
||||
|
||||
DEFAULT_CONFIG = ActionView::DEFAULT_CONFIG
|
||||
include ActiveSupport::Configurable
|
||||
|
||||
def setup
|
||||
super
|
||||
ActionController::Base.relative_url_root = "/collaboration/hieraki"
|
||||
|
||||
@@ -3,6 +3,9 @@ require 'abstract_unit'
|
||||
class FormTagHelperTest < ActionView::TestCase
|
||||
tests ActionView::Helpers::FormTagHelper
|
||||
|
||||
include ActiveSupport::Configurable
|
||||
DEFAULT_CONFIG = ActionView::DEFAULT_CONFIG
|
||||
|
||||
def setup
|
||||
super
|
||||
@controller = Class.new do
|
||||
|
||||
@@ -5,6 +5,9 @@ require 'controller/fake_controllers'
|
||||
RequestMock = Struct.new("Request", :request_uri, :protocol, :host_with_port, :env)
|
||||
|
||||
class UrlHelperTest < ActionView::TestCase
|
||||
include ActiveSupport::Configurable
|
||||
DEFAULT_CONFIG = ActionView::DEFAULT_CONFIG
|
||||
|
||||
def setup
|
||||
super
|
||||
@controller = Class.new do
|
||||
@@ -19,10 +22,15 @@ class UrlHelperTest < ActionView::TestCase
|
||||
|
||||
def test_url_for_escapes_urls
|
||||
@controller.url = "http://www.example.com?a=b&c=d"
|
||||
assert_equal "http://www.example.com?a=b&c=d", url_for(:a => 'b', :c => 'd')
|
||||
assert_equal "http://www.example.com?a=b&c=d", url_for(:a => 'b', :c => 'd')
|
||||
assert_equal "http://www.example.com?a=b&c=d", url_for(:a => 'b', :c => 'd', :escape => true)
|
||||
assert_equal "http://www.example.com?a=b&c=d", url_for(:a => 'b', :c => 'd', :escape => false)
|
||||
end
|
||||
|
||||
def test_url_for_escaping_is_safety_aware
|
||||
assert url_for(:a => 'b', :c => 'd', :escape => true).html_safe?, "escaped urls should be html_safe?"
|
||||
assert !url_for(:a => 'b', :c => 'd', :escape => false).html_safe?, "non-escaped urls shouldn't be safe"
|
||||
end
|
||||
|
||||
def test_url_for_escapes_url_once
|
||||
@controller.url = "http://www.example.com?a=b&c=d"
|
||||
@@ -39,6 +47,16 @@ class UrlHelperTest < ActionView::TestCase
|
||||
assert_equal 'javascript:history.back()', url_for(:back)
|
||||
end
|
||||
|
||||
def test_url_for_from_hash_doesnt_escape_ampersand
|
||||
@controller = TestController.new
|
||||
@view = ActionView::Base.new
|
||||
@view.controller = @controller
|
||||
|
||||
path = @view.url_for(:controller => :cheeses, :foo => :bar, :baz => :quux)
|
||||
|
||||
assert_equal '/cheeses?baz=quux&foo=bar', path
|
||||
end
|
||||
|
||||
# todo: missing test cases
|
||||
def test_button_to_with_straight_url
|
||||
assert_dom_equal "<form method=\"post\" action=\"http://www.example.com\" class=\"button-to\"><div><input type=\"submit\" value=\"Hello\" /></div></form>", button_to("Hello", "http://www.example.com")
|
||||
@@ -295,7 +313,7 @@ class UrlHelperTest < ActionView::TestCase
|
||||
@controller.request = RequestMock.new("http://www.example.com/weblog/show?order=desc&page=1")
|
||||
@controller.url = "http://www.example.com/weblog/show?order=desc&page=1"
|
||||
assert_equal "Showing", link_to_unless_current("Showing", { :action => "show", :controller => "weblog", :order=>'desc', :page=>'1' })
|
||||
assert_equal "Showing", link_to_unless_current("Showing", "http://www.example.com/weblog/show?order=desc&page=1")
|
||||
assert_equal "Showing", link_to_unless_current("Showing", "http://www.example.com/weblog/show?order=desc&page=1")
|
||||
assert_equal "Showing", link_to_unless_current("Showing", "http://www.example.com/weblog/show?order=desc&page=1")
|
||||
|
||||
@controller.request = RequestMock.new("http://www.example.com/weblog/show?order=desc")
|
||||
@@ -305,7 +323,7 @@ class UrlHelperTest < ActionView::TestCase
|
||||
|
||||
@controller.request = RequestMock.new("http://www.example.com/weblog/show?order=desc&page=1")
|
||||
@controller.url = "http://www.example.com/weblog/show?order=desc&page=2"
|
||||
assert_equal "<a href=\"http://www.example.com/weblog/show?order=desc&page=2\">Showing</a>", link_to_unless_current("Showing", { :action => "show", :controller => "weblog" })
|
||||
assert_equal "<a href=\"http://www.example.com/weblog/show?order=desc&page=2\">Showing</a>", link_to_unless_current("Showing", { :action => "show", :controller => "weblog" })
|
||||
assert_equal "<a href=\"http://www.example.com/weblog/show?order=desc&page=2\">Showing</a>", link_to_unless_current("Showing", "http://www.example.com/weblog/show?order=desc&page=2")
|
||||
|
||||
|
||||
|
||||
@@ -326,6 +326,17 @@ module ActiveResource
|
||||
@password = password
|
||||
end
|
||||
|
||||
def auth_type
|
||||
if defined?(@auth_type)
|
||||
@auth_type
|
||||
end
|
||||
end
|
||||
|
||||
def auth_type=(auth_type)
|
||||
@connection = nil
|
||||
@auth_type = auth_type
|
||||
end
|
||||
|
||||
# Sets the format that attributes are sent and received in from a mime type reference:
|
||||
#
|
||||
# Person.format = :json
|
||||
@@ -397,6 +408,7 @@ module ActiveResource
|
||||
@connection.proxy = proxy if proxy
|
||||
@connection.user = user if user
|
||||
@connection.password = password if password
|
||||
@connection.auth_type = auth_type if auth_type
|
||||
@connection.timeout = timeout if timeout
|
||||
@connection.ssl_options = ssl_options if ssl_options
|
||||
@connection
|
||||
|
||||
@@ -17,7 +17,7 @@ module ActiveResource
|
||||
:head => 'Accept'
|
||||
}
|
||||
|
||||
attr_reader :site, :user, :password, :timeout, :proxy, :ssl_options
|
||||
attr_reader :site, :user, :password, :auth_type, :timeout, :proxy, :ssl_options
|
||||
attr_accessor :format
|
||||
|
||||
class << self
|
||||
@@ -57,6 +57,11 @@ module ActiveResource
|
||||
@password = password
|
||||
end
|
||||
|
||||
# Sets the auth type for remote service.
|
||||
def auth_type=(auth_type)
|
||||
@auth_type = legitimize_auth_type(auth_type)
|
||||
end
|
||||
|
||||
# Sets the number of seconds after which HTTP requests to the remote service should time out.
|
||||
def timeout=(timeout)
|
||||
@timeout = timeout
|
||||
@@ -70,31 +75,31 @@ module ActiveResource
|
||||
# Executes a GET request.
|
||||
# Used to get (find) resources.
|
||||
def get(path, headers = {})
|
||||
format.decode(request(:get, path, build_request_headers(headers, :get)).body)
|
||||
with_auth { format.decode(request(:get, path, build_request_headers(headers, :get, self.site.merge(path))).body) }
|
||||
end
|
||||
|
||||
# Executes a DELETE request (see HTTP protocol documentation if unfamiliar).
|
||||
# Used to delete resources.
|
||||
def delete(path, headers = {})
|
||||
request(:delete, path, build_request_headers(headers, :delete))
|
||||
with_auth { request(:delete, path, build_request_headers(headers, :delete, self.site.merge(path))) }
|
||||
end
|
||||
|
||||
# Executes a PUT request (see HTTP protocol documentation if unfamiliar).
|
||||
# Used to update resources.
|
||||
def put(path, body = '', headers = {})
|
||||
request(:put, path, body.to_s, build_request_headers(headers, :put))
|
||||
with_auth { request(:put, path, body.to_s, build_request_headers(headers, :put, self.site.merge(path))) }
|
||||
end
|
||||
|
||||
# Executes a POST request.
|
||||
# Used to create new resources.
|
||||
def post(path, body = '', headers = {})
|
||||
request(:post, path, body.to_s, build_request_headers(headers, :post))
|
||||
with_auth { request(:post, path, body.to_s, build_request_headers(headers, :post, self.site.merge(path))) }
|
||||
end
|
||||
|
||||
# Executes a HEAD request.
|
||||
# Used to obtain meta-information about resources, such as whether they exist and their size (via response headers).
|
||||
def head(path, headers = {})
|
||||
request(:head, path, build_request_headers(headers, :head))
|
||||
with_auth { request(:head, path, build_request_headers(headers, :head, self.site.merge(path))) }
|
||||
end
|
||||
|
||||
|
||||
@@ -198,13 +203,70 @@ module ActiveResource
|
||||
end
|
||||
|
||||
# Builds headers for request to remote service.
|
||||
def build_request_headers(headers, http_method=nil)
|
||||
authorization_header.update(default_header).update(http_format_header(http_method)).update(headers)
|
||||
def build_request_headers(headers, http_method, uri)
|
||||
authorization_header(http_method, uri).update(default_header).update(http_format_header(http_method)).update(headers)
|
||||
end
|
||||
|
||||
# Sets authorization header
|
||||
def authorization_header
|
||||
(@user || @password ? { 'Authorization' => 'Basic ' + ["#{@user}:#{ @password}"].pack('m').delete("\r\n") } : {})
|
||||
def response_auth_header
|
||||
@response_auth_header ||= ""
|
||||
end
|
||||
|
||||
def with_auth
|
||||
retried ||= false
|
||||
yield
|
||||
rescue UnauthorizedAccess => e
|
||||
raise if retried || auth_type != :digest
|
||||
@response_auth_header = e.response['WWW-Authenticate']
|
||||
retried = true
|
||||
retry
|
||||
end
|
||||
|
||||
def authorization_header(http_method, uri)
|
||||
if @user || @password
|
||||
if auth_type == :digest
|
||||
{ 'Authorization' => digest_auth_header(http_method, uri) }
|
||||
else
|
||||
{ 'Authorization' => 'Basic ' + ["#{@user}:#{@password}"].pack('m').delete("\r\n") }
|
||||
end
|
||||
else
|
||||
{}
|
||||
end
|
||||
end
|
||||
|
||||
def digest_auth_header(http_method, uri)
|
||||
params = extract_params_from_response
|
||||
|
||||
ha1 = Digest::MD5.hexdigest("#{@user}:#{params['realm']}:#{@password}")
|
||||
ha2 = Digest::MD5.hexdigest("#{http_method.to_s.upcase}:#{uri.path}")
|
||||
|
||||
params.merge!('cnonce' => client_nonce)
|
||||
request_digest = Digest::MD5.hexdigest([ha1, params['nonce'], "0", params['cnonce'], params['qop'], ha2].join(":"))
|
||||
"Digest #{auth_attributes_for(uri, request_digest, params)}"
|
||||
end
|
||||
|
||||
def client_nonce
|
||||
Digest::MD5.hexdigest("%x" % (Time.now.to_i + rand(65535)))
|
||||
end
|
||||
|
||||
def extract_params_from_response
|
||||
params = {}
|
||||
if response_auth_header =~ /^(\w+) (.*)/
|
||||
$2.gsub(/(\w+)="(.*?)"/) { params[$1] = $2 }
|
||||
end
|
||||
params
|
||||
end
|
||||
|
||||
def auth_attributes_for(uri, request_digest, params)
|
||||
[
|
||||
%Q(username="#{@user}"),
|
||||
%Q(realm="#{params['realm']}"),
|
||||
%Q(qop="#{params['qop']}"),
|
||||
%Q(uri="#{uri.path}"),
|
||||
%Q(nonce="#{params['nonce']}"),
|
||||
%Q(nc="0"),
|
||||
%Q(cnonce="#{params['cnonce']}"),
|
||||
%Q(opaque="#{params['opaque']}"),
|
||||
%Q(response="#{request_digest}")].join(", ")
|
||||
end
|
||||
|
||||
def http_format_header(http_method)
|
||||
@@ -214,5 +276,11 @@ module ActiveResource
|
||||
def logger #:nodoc:
|
||||
Base.logger
|
||||
end
|
||||
|
||||
def legitimize_auth_type(auth_type)
|
||||
return :basic if auth_type.nil?
|
||||
auth_type = auth_type.to_sym
|
||||
[:basic, :digest].include?(auth_type) ? auth_type : :basic
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
require 'rubygems'
|
||||
require 'test/unit'
|
||||
require 'active_support'
|
||||
require 'active_support/test_case'
|
||||
|
||||
$:.unshift "#{File.dirname(__FILE__)}/../lib"
|
||||
|
||||
@@ -8,46 +8,75 @@ class AuthorizationTest < Test::Unit::TestCase
|
||||
@matz = { :id => 1, :name => 'Matz' }.to_xml(:root => 'person')
|
||||
@david = { :id => 2, :name => 'David' }.to_xml(:root => 'person')
|
||||
@authenticated_conn = ActiveResource::Connection.new("http://david:test123@localhost")
|
||||
@authorization_request_header = { 'Authorization' => 'Basic ZGF2aWQ6dGVzdDEyMw==' }
|
||||
@basic_authorization_request_header = { 'Authorization' => 'Basic ZGF2aWQ6dGVzdDEyMw==' }
|
||||
|
||||
@nonce = "MTI0OTUxMzc4NzpjYWI3NDM3NDNmY2JmODU4ZjQ2ZjcwNGZkMTJiMjE0NA=="
|
||||
|
||||
ActiveResource::HttpMock.respond_to do |mock|
|
||||
mock.get "/people/2.xml", @authorization_request_header, @david
|
||||
mock.put "/people/2.xml", @authorization_request_header, nil, 204
|
||||
mock.delete "/people/2.xml", @authorization_request_header, nil, 200
|
||||
mock.post "/people/2/addresses.xml", @authorization_request_header, nil, 201, 'Location' => '/people/1/addresses/5'
|
||||
mock.get "/people/2.xml", @basic_authorization_request_header, @david
|
||||
mock.get "/people/1.xml", @basic_authorization_request_header, nil, 401, { 'WWW-Authenticate' => 'i_should_be_ignored' }
|
||||
mock.put "/people/2.xml", @basic_authorization_request_header, nil, 204
|
||||
mock.delete "/people/2.xml", @basic_authorization_request_header, nil, 200
|
||||
mock.post "/people/2/addresses.xml", @basic_authorization_request_header, nil, 201, 'Location' => '/people/1/addresses/5'
|
||||
mock.head "/people/2.xml", @basic_authorization_request_header, nil, 200
|
||||
|
||||
mock.get "/people/2.xml", { 'Authorization' => blank_digest_auth_header("/people/2.xml", "a10c9bd131c9d4d7755b8f4706fd04af") }, nil, 401, { 'WWW-Authenticate' => response_digest_auth_header }
|
||||
mock.get "/people/2.xml", { 'Authorization' => request_digest_auth_header("/people/2.xml", "912c7a643f18cda562b8d9662c47b6f5") }, @david, 200
|
||||
mock.get "/people/1.xml", { 'Authorization' => request_digest_auth_header("/people/1.xml", "d76e675c0ecfa2bb1abe01491b068a06") }, @matz, 200
|
||||
|
||||
mock.put "/people/2.xml", { 'Authorization' => blank_digest_auth_header("/people/2.xml", "7de8a265a5be3c4c2d3a246562ecd6bd") }, nil, 401, { 'WWW-Authenticate' => response_digest_auth_header }
|
||||
mock.put "/people/2.xml", { 'Authorization' => request_digest_auth_header("/people/2.xml", "3fb3b33d9d0b869cc75815aa11faacd9") }, nil, 204
|
||||
|
||||
mock.delete "/people/2.xml", { 'Authorization' => blank_digest_auth_header("/people/2.xml", "07dfc32769a34ea3510d3a77d64ca495") }, nil, 401, { 'WWW-Authenticate' => response_digest_auth_header }
|
||||
mock.delete "/people/2.xml", { 'Authorization' => request_digest_auth_header("/people/2.xml", "5d438610de7ec163b29096c9afcbb254") }, nil, 200
|
||||
|
||||
mock.post "/people/2/addresses.xml", { 'Authorization' => blank_digest_auth_header("/people/2/addresses.xml", "966dab13620421f928d051f2b9d7b9af") }, nil, 401, { 'WWW-Authenticate' => response_digest_auth_header }
|
||||
mock.post "/people/2/addresses.xml", { 'Authorization' => request_digest_auth_header("/people/2/addresses.xml", "ed540d032c63f8ee34959116c090ec45") }, nil, 201, 'Location' => '/people/1/addresses/5'
|
||||
|
||||
mock.head "/people/2.xml", { 'Authorization' => blank_digest_auth_header("/people/2.xml", "2854eeb92cce2aed29350ea0ce7ba1e2") }, nil, 401, { 'WWW-Authenticate' => response_digest_auth_header }
|
||||
mock.head "/people/2.xml", { 'Authorization' => request_digest_auth_header("/people/2.xml", "07cd4d247e9c130f92ba2501a080b328") }, nil, 200
|
||||
end
|
||||
|
||||
# Make client nonce deterministic
|
||||
class << @authenticated_conn
|
||||
private
|
||||
|
||||
def client_nonce
|
||||
'i-am-a-client-nonce'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_authorization_header
|
||||
authorization_header = @authenticated_conn.__send__(:authorization_header)
|
||||
assert_equal @authorization_request_header['Authorization'], authorization_header['Authorization']
|
||||
authorization_header = @authenticated_conn.__send__(:authorization_header, :get, URI.parse('/people/2.xml'))
|
||||
assert_equal @basic_authorization_request_header['Authorization'], authorization_header['Authorization']
|
||||
authorization = authorization_header["Authorization"].to_s.split
|
||||
|
||||
|
||||
assert_equal "Basic", authorization[0]
|
||||
assert_equal ["david", "test123"], ActiveSupport::Base64.decode64(authorization[1]).split(":")[0..1]
|
||||
end
|
||||
|
||||
|
||||
def test_authorization_header_with_username_but_no_password
|
||||
@conn = ActiveResource::Connection.new("http://david:@localhost")
|
||||
authorization_header = @conn.__send__(:authorization_header)
|
||||
authorization_header = @conn.__send__(:authorization_header, :get, URI.parse('/people/2.xml'))
|
||||
authorization = authorization_header["Authorization"].to_s.split
|
||||
|
||||
|
||||
assert_equal "Basic", authorization[0]
|
||||
assert_equal ["david"], ActiveSupport::Base64.decode64(authorization[1]).split(":")[0..1]
|
||||
end
|
||||
|
||||
|
||||
def test_authorization_header_with_password_but_no_username
|
||||
@conn = ActiveResource::Connection.new("http://:test123@localhost")
|
||||
authorization_header = @conn.__send__(:authorization_header)
|
||||
authorization_header = @conn.__send__(:authorization_header, :get, URI.parse('/people/2.xml'))
|
||||
authorization = authorization_header["Authorization"].to_s.split
|
||||
|
||||
|
||||
assert_equal "Basic", authorization[0]
|
||||
assert_equal ["", "test123"], ActiveSupport::Base64.decode64(authorization[1]).split(":")[0..1]
|
||||
end
|
||||
|
||||
|
||||
def test_authorization_header_with_decoded_credentials_from_url
|
||||
@conn = ActiveResource::Connection.new("http://my%40email.com:%31%32%33@localhost")
|
||||
authorization_header = @conn.__send__(:authorization_header)
|
||||
authorization_header = @conn.__send__(:authorization_header, :get, URI.parse('/people/2.xml'))
|
||||
authorization = authorization_header["Authorization"].to_s.split
|
||||
|
||||
assert_equal "Basic", authorization[0]
|
||||
@@ -58,8 +87,8 @@ class AuthorizationTest < Test::Unit::TestCase
|
||||
@authenticated_conn = ActiveResource::Connection.new("http://@localhost")
|
||||
@authenticated_conn.user = 'david'
|
||||
@authenticated_conn.password = 'test123'
|
||||
authorization_header = @authenticated_conn.__send__(:authorization_header)
|
||||
assert_equal @authorization_request_header['Authorization'], authorization_header['Authorization']
|
||||
authorization_header = @authenticated_conn.__send__(:authorization_header, :get, URI.parse('/people/2.xml'))
|
||||
assert_equal @basic_authorization_request_header['Authorization'], authorization_header['Authorization']
|
||||
authorization = authorization_header["Authorization"].to_s.split
|
||||
|
||||
assert_equal "Basic", authorization[0]
|
||||
@@ -69,7 +98,7 @@ class AuthorizationTest < Test::Unit::TestCase
|
||||
def test_authorization_header_explicitly_setting_username_but_no_password
|
||||
@conn = ActiveResource::Connection.new("http://@localhost")
|
||||
@conn.user = "david"
|
||||
authorization_header = @conn.__send__(:authorization_header)
|
||||
authorization_header = @conn.__send__(:authorization_header, :get, URI.parse('/people/2.xml'))
|
||||
authorization = authorization_header["Authorization"].to_s.split
|
||||
|
||||
assert_equal "Basic", authorization[0]
|
||||
@@ -79,38 +108,119 @@ class AuthorizationTest < Test::Unit::TestCase
|
||||
def test_authorization_header_explicitly_setting_password_but_no_username
|
||||
@conn = ActiveResource::Connection.new("http://@localhost")
|
||||
@conn.password = "test123"
|
||||
authorization_header = @conn.__send__(:authorization_header)
|
||||
authorization_header = @conn.__send__(:authorization_header, :get, URI.parse('/people/2.xml'))
|
||||
authorization = authorization_header["Authorization"].to_s.split
|
||||
|
||||
assert_equal "Basic", authorization[0]
|
||||
assert_equal ["", "test123"], ActiveSupport::Base64.decode64(authorization[1]).split(":")[0..1]
|
||||
end
|
||||
|
||||
def test_authorization_header_if_credentials_supplied_and_auth_type_is_basic
|
||||
@authenticated_conn.auth_type = :basic
|
||||
authorization_header = @authenticated_conn.__send__(:authorization_header, :get, URI.parse('/people/2.xml'))
|
||||
assert_equal @basic_authorization_request_header['Authorization'], authorization_header['Authorization']
|
||||
authorization = authorization_header["Authorization"].to_s.split
|
||||
|
||||
assert_equal "Basic", authorization[0]
|
||||
assert_equal ["david", "test123"], ActiveSupport::Base64.decode64(authorization[1]).split(":")[0..1]
|
||||
end
|
||||
|
||||
def test_authorization_header_if_credentials_supplied_and_auth_type_is_digest
|
||||
@authenticated_conn.auth_type = :digest
|
||||
authorization_header = @authenticated_conn.__send__(:authorization_header, :get, URI.parse('/people/2.xml'))
|
||||
assert_equal blank_digest_auth_header("/people/2.xml", "a10c9bd131c9d4d7755b8f4706fd04af"), authorization_header['Authorization']
|
||||
end
|
||||
|
||||
def test_get
|
||||
david = @authenticated_conn.get("/people/2.xml")
|
||||
assert_equal "David", david["name"]
|
||||
end
|
||||
|
||||
|
||||
def test_post
|
||||
response = @authenticated_conn.post("/people/2/addresses.xml")
|
||||
assert_equal "/people/1/addresses/5", response["Location"]
|
||||
end
|
||||
|
||||
|
||||
def test_put
|
||||
response = @authenticated_conn.put("/people/2.xml")
|
||||
assert_equal 204, response.code
|
||||
end
|
||||
|
||||
|
||||
def test_delete
|
||||
response = @authenticated_conn.delete("/people/2.xml")
|
||||
assert_equal 200, response.code
|
||||
end
|
||||
|
||||
def test_head
|
||||
response = @authenticated_conn.head("/people/2.xml")
|
||||
assert_equal 200, response.code
|
||||
end
|
||||
|
||||
def test_get_with_digest_auth_handles_initial_401_response_and_retries
|
||||
@authenticated_conn.auth_type = :digest
|
||||
response = @authenticated_conn.get("/people/2.xml")
|
||||
assert_equal "David", response["name"]
|
||||
end
|
||||
|
||||
def test_post_with_digest_auth_handles_initial_401_response_and_retries
|
||||
@authenticated_conn.auth_type = :digest
|
||||
response = @authenticated_conn.post("/people/2/addresses.xml")
|
||||
assert_equal "/people/1/addresses/5", response["Location"]
|
||||
assert_equal 201, response.code
|
||||
end
|
||||
|
||||
def test_put_with_digest_auth_handles_initial_401_response_and_retries
|
||||
@authenticated_conn.auth_type = :digest
|
||||
response = @authenticated_conn.put("/people/2.xml")
|
||||
assert_equal 204, response.code
|
||||
end
|
||||
|
||||
def test_delete_with_digest_auth_handles_initial_401_response_and_retries
|
||||
@authenticated_conn.auth_type = :digest
|
||||
response = @authenticated_conn.delete("/people/2.xml")
|
||||
assert_equal 200, response.code
|
||||
end
|
||||
|
||||
def test_head_with_digest_auth_handles_initial_401_response_and_retries
|
||||
@authenticated_conn.auth_type = :digest
|
||||
response = @authenticated_conn.head("/people/2.xml")
|
||||
assert_equal 200, response.code
|
||||
end
|
||||
|
||||
def test_get_with_digest_auth_caches_nonce
|
||||
@authenticated_conn.auth_type = :digest
|
||||
response = @authenticated_conn.get("/people/2.xml")
|
||||
assert_equal "David", response["name"]
|
||||
|
||||
# There is no mock for this request with a non-cached nonce.
|
||||
response = @authenticated_conn.get("/people/1.xml")
|
||||
assert_equal "Matz", response["name"]
|
||||
end
|
||||
|
||||
def test_retry_on_401_only_happens_with_digest_auth
|
||||
assert_raise(ActiveResource::UnauthorizedAccess) { @authenticated_conn.get("/people/1.xml") }
|
||||
assert_equal "", @authenticated_conn.send(:response_auth_header)
|
||||
end
|
||||
|
||||
def test_raises_invalid_request_on_unauthorized_requests
|
||||
assert_raise(ActiveResource::InvalidRequestError) { @conn.post("/people/2.xml") }
|
||||
assert_raise(ActiveResource::InvalidRequestError) { @conn.get("/people/2.xml") }
|
||||
assert_raise(ActiveResource::InvalidRequestError) { @conn.post("/people/2/addresses.xml") }
|
||||
assert_raise(ActiveResource::InvalidRequestError) { @conn.put("/people/2.xml") }
|
||||
assert_raise(ActiveResource::InvalidRequestError) { @conn.delete("/people/2.xml") }
|
||||
assert_raise(ActiveResource::InvalidRequestError) { @conn.head("/people/2.xml") }
|
||||
end
|
||||
|
||||
def test_raises_invalid_request_on_unauthorized_requests_with_digest_auth
|
||||
@conn.auth_type = :digest
|
||||
assert_raise(ActiveResource::InvalidRequestError) { @conn.get("/people/2.xml") }
|
||||
assert_raise(ActiveResource::InvalidRequestError) { @conn.post("/people/2/addresses.xml") }
|
||||
assert_raise(ActiveResource::InvalidRequestError) { @conn.put("/people/2.xml") }
|
||||
assert_raise(ActiveResource::InvalidRequestError) { @conn.delete("/people/2.xml") }
|
||||
assert_raise(ActiveResource::InvalidRequestError) { @conn.head("/people/2.xml") }
|
||||
end
|
||||
|
||||
def test_client_nonce_is_not_nil
|
||||
assert_not_nil ActiveResource::Connection.new("http://david:test123@localhost").send(:client_nonce)
|
||||
end
|
||||
|
||||
protected
|
||||
@@ -119,4 +229,16 @@ class AuthorizationTest < Test::Unit::TestCase
|
||||
@conn.__send__(:handle_response, Response.new(code))
|
||||
end
|
||||
end
|
||||
|
||||
def blank_digest_auth_header(uri, response)
|
||||
%Q(Digest username="david", realm="", qop="", uri="#{uri}", nonce="", nc="0", cnonce="i-am-a-client-nonce", opaque="", response="#{response}")
|
||||
end
|
||||
|
||||
def request_digest_auth_header(uri, response)
|
||||
%Q(Digest username="david", realm="RailsTestApp", qop="auth", uri="#{uri}", nonce="#{@nonce}", nc="0", cnonce="i-am-a-client-nonce", opaque="ef6dfb078ba22298d366f99567814ffb", response="#{response}")
|
||||
end
|
||||
|
||||
def response_digest_auth_header
|
||||
%Q(Digest realm="RailsTestApp", qop="auth", algorithm=MD5, nonce="#{@nonce}", opaque="ef6dfb078ba22298d366f99567814ffb")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -163,6 +163,12 @@ class BaseTest < Test::Unit::TestCase
|
||||
assert_equal('test123', Forum.connection.password)
|
||||
end
|
||||
|
||||
def test_should_accept_setting_auth_type
|
||||
Forum.auth_type = :digest
|
||||
assert_equal(:digest, Forum.auth_type)
|
||||
assert_equal(:digest, Forum.connection.auth_type)
|
||||
end
|
||||
|
||||
def test_should_accept_setting_timeout
|
||||
Forum.timeout = 5
|
||||
assert_equal(5, Forum.timeout)
|
||||
|
||||
@@ -225,6 +225,21 @@ class ConnectionTest < Test::Unit::TestCase
|
||||
assert_raise(ActiveResource::SSLError) { @conn.get('/people/1.xml') }
|
||||
end
|
||||
|
||||
def test_auth_type_can_be_string
|
||||
@conn.auth_type = 'digest'
|
||||
assert_equal(:digest, @conn.auth_type)
|
||||
end
|
||||
|
||||
def test_auth_type_defaults_to_basic
|
||||
@conn.auth_type = nil
|
||||
assert_equal(:basic, @conn.auth_type)
|
||||
end
|
||||
|
||||
def test_auth_type_ignores_nonsensical_values
|
||||
@conn.auth_type = :wibble
|
||||
assert_equal(:basic, @conn.auth_type)
|
||||
end
|
||||
|
||||
protected
|
||||
def assert_response_raises(klass, code)
|
||||
assert_raise(klass, "Expected response code #{code} to raise #{klass}") do
|
||||
|
||||
@@ -7,6 +7,8 @@ module ActiveSupport
|
||||
autoload :Callbacks, 'active_support/callbacks'
|
||||
autoload :Concern, 'active_support/concern'
|
||||
autoload :ConcurrentHash, 'active_support/concurrent_hash'
|
||||
autoload :Configurable, 'active_support/configurable'
|
||||
autoload :DependencyModule, 'active_support/dependency_module'
|
||||
autoload :DeprecatedCallbacks, 'active_support/deprecated_callbacks'
|
||||
autoload :Deprecation, 'active_support/deprecation'
|
||||
autoload :Gzip, 'active_support/gzip'
|
||||
|
||||
35
activesupport/lib/active_support/configurable.rb
Normal file
35
activesupport/lib/active_support/configurable.rb
Normal file
@@ -0,0 +1,35 @@
|
||||
require "active_support/concern"
|
||||
|
||||
module ActiveSupport
|
||||
module Configurable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
module ClassMethods
|
||||
def get_config
|
||||
module_parts = name.split("::")
|
||||
modules = [Object]
|
||||
module_parts.each {|name| modules.push modules.last.const_get(name) }
|
||||
modules.reverse_each do |mod|
|
||||
return mod.const_get(:DEFAULT_CONFIG) if const_defined?(:DEFAULT_CONFIG)
|
||||
end
|
||||
{}
|
||||
end
|
||||
|
||||
def config
|
||||
self.config = get_config unless @config
|
||||
@config
|
||||
end
|
||||
|
||||
def config=(hash)
|
||||
@config = ActiveSupport::OrderedOptions.new
|
||||
hash.each do |key, value|
|
||||
@config[key] = value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def config
|
||||
self.class.config
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,5 +1,3 @@
|
||||
require 'active_support/core_ext/load_error'
|
||||
|
||||
module ActiveSupport
|
||||
module Testing
|
||||
class ProxyTestResult
|
||||
|
||||
@@ -3,10 +3,8 @@ module ActiveSupport
|
||||
module SetupAndTeardown
|
||||
def self.included(base)
|
||||
base.class_eval do
|
||||
extend ClassMethods
|
||||
|
||||
include ActiveSupport::Callbacks
|
||||
define_callbacks :test
|
||||
include ActiveSupport::DeprecatedCallbacks
|
||||
define_callbacks :setup, :teardown
|
||||
|
||||
if defined?(MiniTest::Assertions) && TestCase < MiniTest::Assertions
|
||||
include ForMiniTest
|
||||
@@ -16,33 +14,20 @@ module ActiveSupport
|
||||
end
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
def setup(*args, &block)
|
||||
set_callback(:test, :before, *args, &block)
|
||||
end
|
||||
|
||||
def teardown(*args, &block)
|
||||
set_callback(:test, :after, *args, &block)
|
||||
end
|
||||
|
||||
def wrap(*args, &block)
|
||||
set_callback(:test, :around, *args, &block)
|
||||
end
|
||||
end
|
||||
|
||||
module ForMiniTest
|
||||
def run(runner)
|
||||
result = '.'
|
||||
begin
|
||||
run_callbacks :test do
|
||||
begin
|
||||
result = super
|
||||
rescue Exception => e
|
||||
result = runner.puke(self.class, self.name, e)
|
||||
end
|
||||
end
|
||||
run_callbacks :setup
|
||||
result = super
|
||||
rescue Exception => e
|
||||
result = runner.puke(self.class, self.name, e)
|
||||
ensure
|
||||
begin
|
||||
run_callbacks :teardown, :enumerator => :reverse_each
|
||||
rescue Exception => e
|
||||
result = runner.puke(self.class, self.name, e)
|
||||
end
|
||||
end
|
||||
result
|
||||
end
|
||||
@@ -70,27 +55,27 @@ module ActiveSupport
|
||||
@_result = result
|
||||
begin
|
||||
begin
|
||||
run_callbacks :test do
|
||||
begin
|
||||
setup
|
||||
__send__(@method_name)
|
||||
mocha_verify(assertion_counter) if using_mocha
|
||||
rescue Mocha::ExpectationError => e
|
||||
add_failure(e.message, e.backtrace)
|
||||
rescue Test::Unit::AssertionFailedError => e
|
||||
add_failure(e.message, e.backtrace)
|
||||
rescue Exception => e
|
||||
raise if PASSTHROUGH_EXCEPTIONS.include?(e.class)
|
||||
add_error(e)
|
||||
ensure
|
||||
teardown
|
||||
end
|
||||
end
|
||||
run_callbacks :setup
|
||||
setup
|
||||
__send__(@method_name)
|
||||
mocha_verify(assertion_counter) if using_mocha
|
||||
rescue Mocha::ExpectationError => e
|
||||
add_failure(e.message, e.backtrace)
|
||||
rescue Test::Unit::AssertionFailedError => e
|
||||
add_failure(e.message, e.backtrace)
|
||||
rescue Exception => e
|
||||
raise if PASSTHROUGH_EXCEPTIONS.include?(e.class)
|
||||
add_error(e)
|
||||
ensure
|
||||
begin
|
||||
teardown
|
||||
run_callbacks :teardown, :enumerator => :reverse_each
|
||||
rescue Test::Unit::AssertionFailedError => e
|
||||
add_failure(e.message, e.backtrace)
|
||||
rescue Exception => e
|
||||
raise if PASSTHROUGH_EXCEPTIONS.include?(e.class)
|
||||
add_error(e)
|
||||
end
|
||||
end
|
||||
ensure
|
||||
mocha_teardown if using_mocha
|
||||
|
||||
@@ -13,8 +13,6 @@ module ActiveSupport
|
||||
data = StringIO.new(data || '')
|
||||
end
|
||||
|
||||
LibXML::XML.default_keep_blanks = false
|
||||
|
||||
char = data.getc
|
||||
if char.nil?
|
||||
{}
|
||||
@@ -44,9 +42,9 @@ module LibXML #:nodoc:
|
||||
# hash::
|
||||
# Hash to merge the converted element into.
|
||||
def to_hash(hash={})
|
||||
if text?
|
||||
raise LibXML::XML::Error if content.length >= LIB_XML_LIMIT
|
||||
hash[CONTENT_ROOT] = content
|
||||
if text? || cdata?
|
||||
raise LibXML::XML::Error if hash[CONTENT_ROOT].to_s.length + content.length >= LIB_XML_LIMIT
|
||||
hash[CONTENT_ROOT] = hash[CONTENT_ROOT].to_s + content
|
||||
else
|
||||
sub_hash = insert_name_into_hash(hash, name)
|
||||
attributes_to_hash(sub_hash)
|
||||
@@ -88,6 +86,11 @@ module LibXML #:nodoc:
|
||||
# Hash to merge the children into.
|
||||
def children_to_hash(hash={})
|
||||
each { |child| child.to_hash(hash) }
|
||||
|
||||
if hash.length > 1 && hash[CONTENT_ROOT].blank?
|
||||
hash.delete(CONTENT_ROOT)
|
||||
end
|
||||
|
||||
attributes_to_hash(hash)
|
||||
hash
|
||||
end
|
||||
|
||||
@@ -95,3 +95,55 @@ end
|
||||
|
||||
class AlsoDoingNothingTest < ActiveSupport::TestCase
|
||||
end
|
||||
|
||||
# Setup and teardown callbacks.
|
||||
class SetupAndTeardownTest < ActiveSupport::TestCase
|
||||
setup :reset_callback_record, :foo
|
||||
teardown :foo, :sentinel, :foo
|
||||
|
||||
def test_inherited_setup_callbacks
|
||||
assert_equal [:reset_callback_record, :foo], self.class.setup_callback_chain.map(&:method)
|
||||
assert_equal [:foo], @called_back
|
||||
assert_equal [:foo, :sentinel, :foo], self.class.teardown_callback_chain.map(&:method)
|
||||
end
|
||||
|
||||
def setup
|
||||
end
|
||||
|
||||
def teardown
|
||||
end
|
||||
|
||||
protected
|
||||
def reset_callback_record
|
||||
@called_back = []
|
||||
end
|
||||
|
||||
def foo
|
||||
@called_back << :foo
|
||||
end
|
||||
|
||||
def sentinel
|
||||
assert_equal [:foo, :foo], @called_back
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class SubclassSetupAndTeardownTest < SetupAndTeardownTest
|
||||
setup :bar
|
||||
teardown :bar
|
||||
|
||||
def test_inherited_setup_callbacks
|
||||
assert_equal [:reset_callback_record, :foo, :bar], self.class.setup_callback_chain.map(&:method)
|
||||
assert_equal [:foo, :bar], @called_back
|
||||
assert_equal [:foo, :sentinel, :foo, :bar], self.class.teardown_callback_chain.map(&:method)
|
||||
end
|
||||
|
||||
protected
|
||||
def bar
|
||||
@called_back << :bar
|
||||
end
|
||||
|
||||
def sentinel
|
||||
assert_equal [:foo, :bar, :bar, :foo], @called_back
|
||||
end
|
||||
end
|
||||
|
||||
194
activesupport/test/xml_mini/libxml_engine_test.rb
Normal file
194
activesupport/test/xml_mini/libxml_engine_test.rb
Normal file
@@ -0,0 +1,194 @@
|
||||
require 'abstract_unit'
|
||||
require 'active_support/xml_mini'
|
||||
require 'active_support/core_ext/hash/conversions'
|
||||
|
||||
begin
|
||||
require 'libxml'
|
||||
rescue LoadError
|
||||
# Skip libxml tests
|
||||
else
|
||||
|
||||
class LibxmlEngineTest < Test::Unit::TestCase
|
||||
include ActiveSupport
|
||||
|
||||
def setup
|
||||
@default_backend = XmlMini.backend
|
||||
XmlMini.backend = 'LibXML'
|
||||
|
||||
LibXML::XML::Error.set_handler(&lambda { |error| }) #silence libxml, exceptions will do
|
||||
end
|
||||
|
||||
def teardown
|
||||
XmlMini.backend = @default_backend
|
||||
end
|
||||
|
||||
def test_exception_thrown_on_expansion_attack
|
||||
assert_raise LibXML::XML::Error do
|
||||
attack_xml = %{<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE member [
|
||||
<!ENTITY a "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
|
||||
<!ENTITY b "&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;">
|
||||
<!ENTITY c "&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;">
|
||||
<!ENTITY d "&e;&e;&e;&e;&e;&e;&e;&e;&e;&e;">
|
||||
<!ENTITY e "&f;&f;&f;&f;&f;&f;&f;&f;&f;&f;">
|
||||
<!ENTITY f "&g;&g;&g;&g;&g;&g;&g;&g;&g;&g;">
|
||||
<!ENTITY g "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx">
|
||||
]>
|
||||
<member>
|
||||
&a;
|
||||
</member>
|
||||
}
|
||||
Hash.from_xml(attack_xml)
|
||||
end
|
||||
end
|
||||
|
||||
def test_setting_libxml_as_backend
|
||||
XmlMini.backend = 'LibXML'
|
||||
assert_equal XmlMini_LibXML, XmlMini.backend
|
||||
end
|
||||
|
||||
def test_blank_returns_empty_hash
|
||||
assert_equal({}, XmlMini.parse(nil))
|
||||
assert_equal({}, XmlMini.parse(''))
|
||||
end
|
||||
|
||||
def test_array_type_makes_an_array
|
||||
assert_equal_rexml(<<-eoxml)
|
||||
<blog>
|
||||
<posts type="array">
|
||||
<post>a post</post>
|
||||
<post>another post</post>
|
||||
</posts>
|
||||
</blog>
|
||||
eoxml
|
||||
end
|
||||
|
||||
def test_one_node_document_as_hash
|
||||
assert_equal_rexml(<<-eoxml)
|
||||
<products/>
|
||||
eoxml
|
||||
end
|
||||
|
||||
def test_one_node_with_attributes_document_as_hash
|
||||
assert_equal_rexml(<<-eoxml)
|
||||
<products foo="bar"/>
|
||||
eoxml
|
||||
end
|
||||
|
||||
def test_products_node_with_book_node_as_hash
|
||||
assert_equal_rexml(<<-eoxml)
|
||||
<products>
|
||||
<book name="awesome" id="12345" />
|
||||
</products>
|
||||
eoxml
|
||||
end
|
||||
|
||||
def test_products_node_with_two_book_nodes_as_hash
|
||||
assert_equal_rexml(<<-eoxml)
|
||||
<products>
|
||||
<book name="awesome" id="12345" />
|
||||
<book name="america" id="67890" />
|
||||
</products>
|
||||
eoxml
|
||||
end
|
||||
|
||||
def test_single_node_with_content_as_hash
|
||||
assert_equal_rexml(<<-eoxml)
|
||||
<products>
|
||||
hello world
|
||||
</products>
|
||||
eoxml
|
||||
end
|
||||
|
||||
def test_children_with_children
|
||||
assert_equal_rexml(<<-eoxml)
|
||||
<root>
|
||||
<products>
|
||||
<book name="america" id="67890" />
|
||||
</products>
|
||||
</root>
|
||||
eoxml
|
||||
end
|
||||
|
||||
def test_children_with_text
|
||||
assert_equal_rexml(<<-eoxml)
|
||||
<root>
|
||||
<products>
|
||||
hello everyone
|
||||
</products>
|
||||
</root>
|
||||
eoxml
|
||||
end
|
||||
|
||||
def test_children_with_non_adjacent_text
|
||||
assert_equal_rexml(<<-eoxml)
|
||||
<root>
|
||||
good
|
||||
<products>
|
||||
hello everyone
|
||||
</products>
|
||||
morning
|
||||
</root>
|
||||
eoxml
|
||||
end
|
||||
|
||||
def test_parse_from_io
|
||||
io = StringIO.new(<<-eoxml)
|
||||
<root>
|
||||
good
|
||||
<products>
|
||||
hello everyone
|
||||
</products>
|
||||
morning
|
||||
</root>
|
||||
eoxml
|
||||
XmlMini.parse(io)
|
||||
end
|
||||
|
||||
def test_children_with_simple_cdata
|
||||
assert_equal_rexml(<<-eoxml)
|
||||
<root>
|
||||
<products>
|
||||
<![CDATA[cdatablock]]>
|
||||
</products>
|
||||
</root>
|
||||
eoxml
|
||||
end
|
||||
|
||||
def test_children_with_multiple_cdata
|
||||
assert_equal_rexml(<<-eoxml)
|
||||
<root>
|
||||
<products>
|
||||
<![CDATA[cdatablock1]]><![CDATA[cdatablock2]]>
|
||||
</products>
|
||||
</root>
|
||||
eoxml
|
||||
end
|
||||
|
||||
def test_children_with_text_and_cdata
|
||||
assert_equal_rexml(<<-eoxml)
|
||||
<root>
|
||||
<products>
|
||||
hello <![CDATA[cdatablock]]>
|
||||
morning
|
||||
</products>
|
||||
</root>
|
||||
eoxml
|
||||
end
|
||||
|
||||
def test_children_with_blank_text
|
||||
assert_equal_rexml(<<-eoxml)
|
||||
<root>
|
||||
<products> </products>
|
||||
</root>
|
||||
eoxml
|
||||
end
|
||||
|
||||
private
|
||||
def assert_equal_rexml(xml)
|
||||
hash = XmlMini.with_backend('REXML') { XmlMini.parse(xml) }
|
||||
assert_equal(hash, XmlMini.parse(xml))
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -28,6 +28,7 @@ task :default => :test
|
||||
task :test do
|
||||
dir = ENV["TEST_DIR"] || "**"
|
||||
Dir["test/#{dir}/*_test.rb"].all? do |file|
|
||||
next true if file.include?("fixtures")
|
||||
ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME'))
|
||||
system(ruby, '-Itest', "-I#{File.dirname(__FILE__)}/../activesupport/lib", file)
|
||||
end or raise "Failures"
|
||||
|
||||
@@ -18,6 +18,10 @@ module Rails
|
||||
@plugin_loader ||= config.plugin_loader.new(self)
|
||||
end
|
||||
|
||||
def root
|
||||
config.root
|
||||
end
|
||||
|
||||
def routes
|
||||
ActionController::Routing::Routes
|
||||
end
|
||||
@@ -102,7 +106,7 @@ module Rails
|
||||
# Create tmp directories
|
||||
initializer :ensure_tmp_directories_exist do
|
||||
%w(cache pids sessions sockets).each do |dir_to_make|
|
||||
FileUtils.mkdir_p(File.join(config.root_path, 'tmp', dir_to_make))
|
||||
FileUtils.mkdir_p(File.join(config.root, 'tmp', dir_to_make))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -346,7 +350,7 @@ module Rails
|
||||
# Loads all plugins in <tt>config.plugin_paths</tt>. <tt>plugin_paths</tt>
|
||||
# defaults to <tt>vendor/plugins</tt> but may also be set to a list of
|
||||
# paths, such as
|
||||
# config.plugin_paths = ["#{RAILS_ROOT}/lib/plugins", "#{RAILS_ROOT}/vendor/plugins"]
|
||||
# config.plugin_paths = ["#{config.root}/lib/plugins", "#{config.root}/vendor/plugins"]
|
||||
#
|
||||
# In the default implementation, as each plugin discovered in <tt>plugin_paths</tt> is initialized:
|
||||
# * its +lib+ directory, if present, is added to the load path (immediately after the applications lib directory)
|
||||
@@ -394,7 +398,7 @@ module Rails
|
||||
|
||||
initializer :load_application_initializers do
|
||||
if config.gems_dependencies_loaded
|
||||
Dir["#{configuration.root_path}/config/initializers/**/*.rb"].sort.each do |initializer|
|
||||
Dir["#{configuration.root}/config/initializers/**/*.rb"].sort.each do |initializer|
|
||||
load(initializer)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
require 'rails/plugin/loader'
|
||||
require 'rails/plugin/locator'
|
||||
|
||||
module Rails
|
||||
class Configuration
|
||||
attr_accessor :cache_classes, :load_paths, :eager_load_paths, :framework_paths,
|
||||
attr_accessor :cache_classes, :load_paths,
|
||||
:load_once_paths, :gems_dependencies_loaded, :after_initialize_blocks,
|
||||
:frameworks, :framework_root_path, :root_path, :plugin_paths, :plugins,
|
||||
:frameworks, :framework_root_path, :root, :plugin_paths, :plugins,
|
||||
:plugin_loader, :plugin_locators, :gems, :loaded_plugins, :reload_plugins,
|
||||
:i18n, :gems, :whiny_nils, :consider_all_requests_local,
|
||||
:action_controller, :active_record, :action_view, :active_support,
|
||||
@@ -13,31 +16,13 @@ module Rails
|
||||
:eager_load_paths, :dependency_loading, :paths, :serve_static_assets
|
||||
|
||||
def initialize
|
||||
set_root_path!
|
||||
|
||||
@framework_paths = []
|
||||
@load_once_paths = []
|
||||
@after_initialize_blocks = []
|
||||
@loaded_plugins = []
|
||||
@dependency_loading = true
|
||||
@eager_load_paths = default_eager_load_paths
|
||||
@load_paths = default_load_paths
|
||||
@plugin_paths = default_plugin_paths
|
||||
@frameworks = default_frameworks
|
||||
@plugin_loader = default_plugin_loader
|
||||
@plugin_locators = default_plugin_locators
|
||||
@gems = default_gems
|
||||
@i18n = default_i18n
|
||||
@log_path = default_log_path
|
||||
@log_level = default_log_level
|
||||
@cache_store = default_cache_store
|
||||
@view_path = default_view_path
|
||||
@controller_paths = default_controller_paths
|
||||
@routes_configuration_file = default_routes_configuration_file
|
||||
@database_configuration_file = default_database_configuration_file
|
||||
@serve_static_assets = default_serve_static_assets
|
||||
@serve_static_assets = true
|
||||
|
||||
for framework in default_frameworks
|
||||
for framework in frameworks
|
||||
self.send("#{framework}=", Rails::OrderedOptions.new)
|
||||
end
|
||||
self.active_support = Rails::OrderedOptions.new
|
||||
@@ -47,38 +32,60 @@ module Rails
|
||||
@after_initialize_blocks << blk if blk
|
||||
end
|
||||
|
||||
def set_root_path!
|
||||
raise 'RAILS_ROOT is not set' unless defined?(RAILS_ROOT)
|
||||
raise 'RAILS_ROOT is not a directory' unless File.directory?(RAILS_ROOT)
|
||||
|
||||
self.root_path =
|
||||
# Pathname is incompatible with Windows, but Windows doesn't have
|
||||
# real symlinks so File.expand_path is safe.
|
||||
if RUBY_PLATFORM =~ /(:?mswin|mingw)/
|
||||
File.expand_path(RAILS_ROOT)
|
||||
|
||||
# Otherwise use Pathname#realpath which respects symlinks.
|
||||
def root
|
||||
@root ||= begin
|
||||
if defined?(RAILS_ROOT)
|
||||
root = RAILS_ROOT
|
||||
else
|
||||
Pathname.new(RAILS_ROOT).realpath.to_s
|
||||
call_stack = caller.map { |p| p.split(':').first }
|
||||
root_path = call_stack.detect { |p| p !~ %r[railties/lib/rails] }
|
||||
root_path = File.dirname(root_path)
|
||||
|
||||
while root_path && File.directory?(root_path) && !File.exist?("#{root_path}/config.ru")
|
||||
parent = File.dirname(root_path)
|
||||
root_path = parent != root_path && parent
|
||||
end
|
||||
|
||||
Object.class_eval("RAILS_ROOT = ''")
|
||||
|
||||
root = File.exist?("#{root_path}/config.ru") ? root_path : Dir.pwd
|
||||
end
|
||||
|
||||
@paths = Rails::Application::Root.new(root_path)
|
||||
@paths.app "app", :load_path => true
|
||||
@paths.app.metals "app/metal", :eager_load => true
|
||||
@paths.app.models "app/models", :eager_load => true
|
||||
@paths.app.controllers "app/controllers", builtin_directories, :eager_load => true
|
||||
@paths.app.helpers "app/helpers", :eager_load => true
|
||||
@paths.app.services "app/services", :load_path => true
|
||||
@paths.lib "lib", :load_path => true
|
||||
@paths.vendor "vendor", :load_path => true
|
||||
@paths.vendor.plugins "vendor/plugins"
|
||||
@paths.tmp "tmp"
|
||||
@paths.tmp.cache "tmp/cache"
|
||||
@paths.config "config"
|
||||
@paths.config.locales "config/locales"
|
||||
@paths.config.environments "config/environments", :glob => "#{RAILS_ENV}.rb"
|
||||
root = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ?
|
||||
Pathname.new(root).expand_path.to_s :
|
||||
Pathname.new(root).realpath.to_s
|
||||
|
||||
RAILS_ROOT.replace root_path
|
||||
# TODO: Remove RAILS_ROOT
|
||||
RAILS_ROOT.replace(root)
|
||||
root
|
||||
end
|
||||
end
|
||||
|
||||
def root=(root)
|
||||
Object.class_eval("RAILS_ROOT = ''") unless defined?(RAILS_ROOT)
|
||||
RAILS_ROOT.replace(root)
|
||||
@root = root
|
||||
end
|
||||
|
||||
def paths
|
||||
@paths ||= begin
|
||||
paths = Rails::Application::Root.new(root)
|
||||
paths.app "app", :load_path => true
|
||||
paths.app.metals "app/metal", :eager_load => true
|
||||
paths.app.models "app/models", :eager_load => true
|
||||
paths.app.controllers "app/controllers", builtin_directories, :eager_load => true
|
||||
paths.app.helpers "app/helpers", :eager_load => true
|
||||
paths.app.services "app/services", :load_path => true
|
||||
paths.lib "lib", :load_path => true
|
||||
paths.vendor "vendor", :load_path => true
|
||||
paths.vendor.plugins "vendor/plugins"
|
||||
paths.tmp "tmp"
|
||||
paths.tmp.cache "tmp/cache"
|
||||
paths.config "config"
|
||||
paths.config.locales "config/locales"
|
||||
paths.config.environments "config/environments", :glob => "#{RAILS_ENV}.rb"
|
||||
paths
|
||||
end
|
||||
end
|
||||
|
||||
# Enable threaded mode. Allows concurrent requests to controller actions and
|
||||
@@ -105,7 +112,7 @@ module Rails
|
||||
end
|
||||
|
||||
def framework_root_path
|
||||
defined?(::RAILS_FRAMEWORK_ROOT) ? ::RAILS_FRAMEWORK_ROOT : "#{root_path}/vendor/rails"
|
||||
defined?(::RAILS_FRAMEWORK_ROOT) ? ::RAILS_FRAMEWORK_ROOT : "#{root}/vendor/rails"
|
||||
end
|
||||
|
||||
def middleware
|
||||
@@ -121,63 +128,69 @@ module Rails
|
||||
YAML::load(ERB.new(IO.read(database_configuration_file)).result)
|
||||
end
|
||||
|
||||
def default_routes_configuration_file
|
||||
File.join(root_path, 'config', 'routes.rb')
|
||||
def routes_configuration_file
|
||||
@routes_configuration_file ||= File.join(root, 'config', 'routes.rb')
|
||||
end
|
||||
|
||||
def default_controller_paths
|
||||
paths = [File.join(root_path, 'app', 'controllers')]
|
||||
paths.concat builtin_directories
|
||||
paths
|
||||
end
|
||||
|
||||
def default_cache_store
|
||||
if File.exist?("#{root_path}/tmp/cache/")
|
||||
[ :file_store, "#{root_path}/tmp/cache/" ]
|
||||
else
|
||||
:memory_store
|
||||
def controller_paths
|
||||
@controller_paths ||= begin
|
||||
paths = [File.join(root, 'app', 'controllers')]
|
||||
paths.concat builtin_directories
|
||||
paths
|
||||
end
|
||||
end
|
||||
|
||||
def default_database_configuration_file
|
||||
File.join(root_path, 'config', 'database.yml')
|
||||
def cache_store
|
||||
@cache_store ||= begin
|
||||
if File.exist?("#{root}/tmp/cache/")
|
||||
[ :file_store, "#{root}/tmp/cache/" ]
|
||||
else
|
||||
:memory_store
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def default_view_path
|
||||
File.join(root_path, 'app', 'views')
|
||||
def database_configuration_file
|
||||
@database_configuration_file ||= File.join(root, 'config', 'database.yml')
|
||||
end
|
||||
|
||||
def default_eager_load_paths
|
||||
%w(
|
||||
def view_path
|
||||
@view_path ||= File.join(root, 'app', 'views')
|
||||
end
|
||||
|
||||
def eager_load_paths
|
||||
@eager_load_paths ||= %w(
|
||||
app/metal
|
||||
app/models
|
||||
app/controllers
|
||||
app/helpers
|
||||
).map { |dir| "#{root_path}/#{dir}" }.select { |dir| File.directory?(dir) }
|
||||
).map { |dir| "#{root}/#{dir}" }.select { |dir| File.directory?(dir) }
|
||||
end
|
||||
|
||||
def default_load_paths
|
||||
paths = []
|
||||
def load_paths
|
||||
@load_paths ||= begin
|
||||
paths = []
|
||||
|
||||
# Add the old mock paths only if the directories exists
|
||||
paths.concat(Dir["#{root_path}/test/mocks/#{RAILS_ENV}"]) if File.exists?("#{root_path}/test/mocks/#{RAILS_ENV}")
|
||||
# Add the old mock paths only if the directories exists
|
||||
paths.concat(Dir["#{root}/test/mocks/#{RAILS_ENV}"]) if File.exists?("#{root}/test/mocks/#{RAILS_ENV}")
|
||||
|
||||
# Add the app's controller directory
|
||||
paths.concat(Dir["#{root_path}/app/controllers/"])
|
||||
# Add the app's controller directory
|
||||
paths.concat(Dir["#{root}/app/controllers/"])
|
||||
|
||||
# Followed by the standard includes.
|
||||
paths.concat %w(
|
||||
app
|
||||
app/metal
|
||||
app/models
|
||||
app/controllers
|
||||
app/helpers
|
||||
app/services
|
||||
lib
|
||||
vendor
|
||||
).map { |dir| "#{root_path}/#{dir}" }.select { |dir| File.directory?(dir) }
|
||||
# Followed by the standard includes.
|
||||
paths.concat %w(
|
||||
app
|
||||
app/metal
|
||||
app/models
|
||||
app/controllers
|
||||
app/helpers
|
||||
app/services
|
||||
lib
|
||||
vendor
|
||||
).map { |dir| "#{root}/#{dir}" }.select { |dir| File.directory?(dir) }
|
||||
|
||||
paths.concat builtin_directories
|
||||
paths.concat builtin_directories
|
||||
end
|
||||
end
|
||||
|
||||
def builtin_directories
|
||||
@@ -185,48 +198,48 @@ module Rails
|
||||
(RAILS_ENV == 'development') ? Dir["#{RAILTIES_PATH}/builtin/*/"] : []
|
||||
end
|
||||
|
||||
def default_log_path
|
||||
File.join(root_path, 'log', "#{RAILS_ENV}.log")
|
||||
def log_path
|
||||
@log_path ||= File.join(root, 'log', "#{RAILS_ENV}.log")
|
||||
end
|
||||
|
||||
def default_log_level
|
||||
RAILS_ENV == 'production' ? :info : :debug
|
||||
def log_level
|
||||
@log_level ||= RAILS_ENV == 'production' ? :info : :debug
|
||||
end
|
||||
|
||||
def default_frameworks
|
||||
[ :active_record, :action_controller, :action_view, :action_mailer, :active_resource ]
|
||||
def frameworks
|
||||
@frameworks ||= [ :active_record, :action_controller, :action_view, :action_mailer, :active_resource ]
|
||||
end
|
||||
|
||||
def default_plugin_paths
|
||||
["#{root_path}/vendor/plugins"]
|
||||
def plugin_paths
|
||||
@plugin_paths ||= ["#{root}/vendor/plugins"]
|
||||
end
|
||||
|
||||
def default_plugin_loader
|
||||
require 'rails/plugin/loader'
|
||||
Plugin::Loader
|
||||
end
|
||||
|
||||
def default_plugin_locators
|
||||
require 'rails/plugin/locator'
|
||||
locators = []
|
||||
locators << Plugin::GemLocator if defined? Gem
|
||||
locators << Plugin::FileSystemLocator
|
||||
end
|
||||
|
||||
def default_i18n
|
||||
i18n = Rails::OrderedOptions.new
|
||||
i18n.load_path = []
|
||||
|
||||
if File.exist?(File.join(RAILS_ROOT, 'config', 'locales'))
|
||||
i18n.load_path << Dir[File.join(RAILS_ROOT, 'config', 'locales', '*.{rb,yml}')]
|
||||
i18n.load_path.flatten!
|
||||
def plugin_loader
|
||||
@plugin_loader ||= begin
|
||||
Plugin::Loader
|
||||
end
|
||||
|
||||
i18n
|
||||
end
|
||||
|
||||
def default_serve_static_assets
|
||||
true
|
||||
def plugin_locators
|
||||
@plugin_locators ||= begin
|
||||
locators = []
|
||||
locators << Plugin::GemLocator if defined? Gem
|
||||
locators << Plugin::FileSystemLocator
|
||||
end
|
||||
end
|
||||
|
||||
def i18n
|
||||
@i18n ||= begin
|
||||
i18n = Rails::OrderedOptions.new
|
||||
i18n.load_path = []
|
||||
|
||||
if File.exist?(File.join(root, 'config', 'locales'))
|
||||
i18n.load_path << Dir[File.join(root, 'config', 'locales', '*.{rb,yml}')]
|
||||
i18n.load_path.flatten!
|
||||
end
|
||||
|
||||
i18n
|
||||
end
|
||||
end
|
||||
|
||||
# Adds a single Gem dependency to the rails application. By default, it will require
|
||||
@@ -241,15 +254,15 @@ module Rails
|
||||
#
|
||||
# config.gem 'qrp', :version => '0.4.1', :lib => false
|
||||
def gem(name, options = {})
|
||||
@gems << Rails::GemDependency.new(name, options)
|
||||
gems << Rails::GemDependency.new(name, options)
|
||||
end
|
||||
|
||||
def default_gems
|
||||
[]
|
||||
def gems
|
||||
@gems ||= []
|
||||
end
|
||||
|
||||
def environment_path
|
||||
"#{root_path}/config/environments/#{RAILS_ENV}.rb"
|
||||
"#{root}/config/environments/#{RAILS_ENV}.rb"
|
||||
end
|
||||
|
||||
def reload_plugins?
|
||||
|
||||
@@ -54,6 +54,7 @@ module Rails::Generators
|
||||
copy_file "Rakefile"
|
||||
copy_file "README"
|
||||
copy_file "config.ru"
|
||||
template "Gemfile"
|
||||
end
|
||||
|
||||
def create_app_files
|
||||
|
||||
10
railties/lib/rails/generators/rails/app/templates/Gemfile
Normal file
10
railties/lib/rails/generators/rails/app/templates/Gemfile
Normal file
@@ -0,0 +1,10 @@
|
||||
# Gemfile is where you list all of your application's dependencies
|
||||
#
|
||||
gem "rails", "<%= Rails::VERSION::STRING %>"
|
||||
#
|
||||
# Bundling edge rails:
|
||||
# gem "rails", "<%= Rails::VERSION::STRING %>", :git => "git://github.com/rails/rails.git"
|
||||
|
||||
# You can list more dependencies here
|
||||
# gem "nokogiri"
|
||||
# gem "merb" # ;)
|
||||
@@ -19,14 +19,14 @@ module Rails
|
||||
class Root
|
||||
include PathParent
|
||||
|
||||
attr_reader :path
|
||||
attr_accessor :path
|
||||
|
||||
def initialize(path)
|
||||
raise unless path.is_a?(String)
|
||||
raise if path.is_a?(Array)
|
||||
|
||||
@children = {}
|
||||
|
||||
# TODO: Move logic from set_root_path initializer
|
||||
@path = File.expand_path(path)
|
||||
@path = path
|
||||
@root = self
|
||||
@all_paths = []
|
||||
end
|
||||
@@ -123,8 +123,10 @@ module Rails
|
||||
end
|
||||
|
||||
def paths
|
||||
raise "You need to set a path root" unless @root.path
|
||||
|
||||
@paths.map do |path|
|
||||
path.index('/') == 0 ? path : File.join(@root.path, path)
|
||||
path.index('/') == 0 ? path : File.expand_path(File.join(@root.path, path))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
49
railties/test/application/configuration_test.rb
Normal file
49
railties/test/application/configuration_test.rb
Normal file
@@ -0,0 +1,49 @@
|
||||
require "isolation/abstract_unit"
|
||||
|
||||
module ApplicationTests
|
||||
class InitializerTest < Test::Unit::TestCase
|
||||
include ActiveSupport::Testing::Isolation
|
||||
|
||||
def setup
|
||||
build_app
|
||||
boot_rails
|
||||
Object.send(:remove_const, :RAILS_ROOT)
|
||||
end
|
||||
|
||||
test "the application root is set correctly" do
|
||||
require "#{app_path}/config/environment"
|
||||
assert_equal app_path, Rails.application.root
|
||||
end
|
||||
|
||||
test "the application root can be set" do
|
||||
FileUtils.mkdir_p("#{app_path}/hello")
|
||||
add_to_config <<-RUBY
|
||||
config.frameworks = []
|
||||
config.root = '#{app_path}/hello'
|
||||
RUBY
|
||||
require "#{app_path}/config/environment"
|
||||
assert_equal "#{app_path}/hello", Rails.application.root
|
||||
end
|
||||
|
||||
test "the application root is detected as where config.ru is located" do
|
||||
add_to_config <<-RUBY
|
||||
config.frameworks = []
|
||||
RUBY
|
||||
FileUtils.mv "#{app_path}/config.ru", "#{app_path}/config/config.ru"
|
||||
require "#{app_path}/config/environment"
|
||||
assert_equal "#{app_path}/config", Rails.application.root
|
||||
end
|
||||
|
||||
test "the application root is Dir.pwd if there is no config.ru" do
|
||||
File.delete("#{app_path}/config.ru")
|
||||
add_to_config <<-RUBY
|
||||
config.frameworks = []
|
||||
RUBY
|
||||
|
||||
Dir.chdir("#{app_path}/app") do
|
||||
require "#{app_path}/config/environment"
|
||||
assert_equal "#{app_path}/app", Rails.application.root
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -5,9 +5,9 @@ module ApplicationTests
|
||||
include ActiveSupport::Testing::Isolation
|
||||
|
||||
def setup
|
||||
require "rails/generators"
|
||||
build_app
|
||||
boot_rails
|
||||
require "rails/generators"
|
||||
end
|
||||
|
||||
test "generators default values" do
|
||||
|
||||
@@ -8,12 +8,17 @@ else
|
||||
RAILS_ROOT = fixtures
|
||||
end
|
||||
|
||||
$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../../activemodel/lib"
|
||||
$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../../activerecord/lib"
|
||||
$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../../actionpack/lib"
|
||||
$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../lib"
|
||||
# TODO: Fix this RAILS_ENV stuff
|
||||
RAILS_ENV = 'test'
|
||||
require "rails/core"
|
||||
require 'rails/generators'
|
||||
|
||||
require 'rubygems'
|
||||
$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../../activerecord/lib"
|
||||
$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../../actionpack/lib"
|
||||
|
||||
require 'active_record'
|
||||
require 'action_dispatch'
|
||||
|
||||
|
||||
@@ -25,8 +25,10 @@ module TestHelpers
|
||||
module Paths
|
||||
module_function
|
||||
|
||||
TMP_PATH = File.expand_path(File.join(File.dirname(__FILE__), *%w[.. .. tmp]))
|
||||
|
||||
def tmp_path(*args)
|
||||
File.expand_path(File.join(File.dirname(__FILE__), *%w[.. .. tmp] + args))
|
||||
File.join(TMP_PATH, *args)
|
||||
end
|
||||
|
||||
def app_path(*args)
|
||||
@@ -88,10 +90,14 @@ module TestHelpers
|
||||
end
|
||||
end
|
||||
|
||||
add_to_config 'config.action_controller.session = { :key => "_myapp_session", :secret => "bac838a849c1d5c4de2e6a50af826079" }'
|
||||
end
|
||||
|
||||
def add_to_config(str)
|
||||
environment = File.read("#{app_path}/config/environment.rb")
|
||||
if environment =~ /(\n\s*end\s*)\Z/
|
||||
File.open("#{app_path}/config/environment.rb", 'w') do |f|
|
||||
f.puts $` + %'\nconfig.action_controller.session = { :key => "_myapp_session", :secret => "bac838a849c1d5c4de2e6a50af826079" }\n' + $1
|
||||
f.puts $` + "\n#{str}\n" + $1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -12,11 +12,32 @@ class PathsTest < ActiveSupport::TestCase
|
||||
assert_equal "/fiz/baz", root.path
|
||||
end
|
||||
|
||||
test "the paths object can be initialized with nil" do
|
||||
assert_nothing_raised do
|
||||
Rails::Application::Root.new(nil)
|
||||
end
|
||||
end
|
||||
|
||||
test "a paths object initialized with nil can be updated" do
|
||||
root = Rails::Application::Root.new(nil)
|
||||
root.app = "app"
|
||||
root.path = "/root"
|
||||
assert_equal ["/root/app"], root.app.to_a
|
||||
end
|
||||
|
||||
test "creating a root level path" do
|
||||
@root.app = "/foo/bar"
|
||||
assert_equal ["/foo/bar"], @root.app.to_a
|
||||
end
|
||||
|
||||
test "raises exception if root path never set" do
|
||||
root = Rails::Application::Root.new(nil)
|
||||
root.app = "app"
|
||||
assert_raises RuntimeError do
|
||||
root.app.to_a
|
||||
end
|
||||
end
|
||||
|
||||
test "creating a root level path without assignment" do
|
||||
@root.app "/foo/bar"
|
||||
assert_equal ["/foo/bar"], @root.app.to_a
|
||||
|
||||
Reference in New Issue
Block a user