diff options
72 files changed, 830 insertions, 762 deletions
diff --git a/activerecord/.gitignore b/.gitignore index 2bf1ef8c0e..2bf1ef8c0e 100644 --- a/activerecord/.gitignore +++ b/.gitignore diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 1e53a39667..9c72fd945a 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,11 @@ *SVN* +* Add conditional options to caches_page method. [Paul Horsfall] + +* Move missing template logic to ActionView. [Pratik] + +* Introduce ActionView::InlineTemplate class. [Pratik] + * Automatically parse posted JSON content for Mime::JSON requests. [rick] POST /posts diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 63ad4d042a..c0f3122fbf 100755 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -16,9 +16,6 @@ module ActionController #:nodoc: class SessionRestoreError < ActionControllerError #:nodoc: end - class MissingTemplate < ActionControllerError #:nodoc: - end - class RenderError < ActionControllerError #:nodoc: end @@ -330,9 +327,6 @@ module ActionController #:nodoc: # Can be set to nil for no logging. Compatible with both Ruby's own Logger and Log4r loggers. cattr_accessor :logger - # Turn on +ignore_missing_templates+ if you want to unit test actions without making the associated templates. - cattr_accessor :ignore_missing_templates - # Controls the resource action separator @@resource_action_separator = "/" cattr_accessor :resource_action_separator @@ -870,7 +864,7 @@ module ActionController #:nodoc: elsif inline = options[:inline] add_variables_to_assigns - tmpl = ActionView::Template.new(@template, options[:inline], false, options[:locals], true, options[:type]) + tmpl = ActionView::InlineTemplate.new(@template, options[:inline], options[:locals], options[:type]) render_for_text(@template.render_template(tmpl), options[:status]) elsif action_name = options[:action] @@ -1105,7 +1099,6 @@ module ActionController #:nodoc: private def render_for_file(template_path, status = nil, use_full_path = false, locals = {}) #:nodoc: add_variables_to_assigns - assert_existence_of_template_file(template_path) if use_full_path logger.info("Rendering #{template_path}" + (status ? " (#{status})" : '')) if logger render_for_text(@template.render_file(template_path, use_full_path, locals), status) end @@ -1223,7 +1216,7 @@ module ActionController #:nodoc: end def add_class_variables_to_assigns - %w(view_paths logger ignore_missing_templates).each do |cvar| + %w(view_paths logger).each do |cvar| @assigns[cvar] = self.send(cvar) end end @@ -1267,15 +1260,6 @@ module ActionController #:nodoc: @@exempt_from_layout.any? { |ext| name_with_extension =~ ext } end - def assert_existence_of_template_file(template_name) - unless template_exists?(template_name) || ignore_missing_templates - full_template_path = template_name.include?('.') ? template_name : "#{template_name}.#{@template.template_format}.erb" - display_paths = view_paths.join(':') - template_type = (template_name =~ /layouts/i) ? 'layout' : 'template' - raise(MissingTemplate, "Missing #{template_type} #{full_template_path} in view path #{display_paths}") - end - end - def default_template_name(action_name = self.action_name) if action_name action_name = action_name.to_s diff --git a/actionpack/lib/action_controller/caching/pages.rb b/actionpack/lib/action_controller/caching/pages.rb index 4307f39583..7aa6ce154b 100644 --- a/actionpack/lib/action_controller/caching/pages.rb +++ b/actionpack/lib/action_controller/caching/pages.rb @@ -36,7 +36,7 @@ module ActionController #:nodoc: # == Setting the cache directory # # The cache directory should be the document root for the web server and is set using Base.page_cache_directory = "/document/root". - # For Rails, this directory has already been set to RAILS_ROOT + "/public". + # For Rails, this directory has already been set to Rails.public_path (which is usually set to RAILS_ROOT + "/public"). # # == Setting the cache extension # @@ -46,7 +46,7 @@ module ActionController #:nodoc: def self.included(base) #:nodoc: base.extend(ClassMethods) base.class_eval do - @@page_cache_directory = defined?(RAILS_ROOT) ? "#{RAILS_ROOT}/public" : "" + @@page_cache_directory = defined?(Rails.public_path) ? Rails.public_path : "" cattr_accessor :page_cache_directory @@page_cache_extension = '.html' @@ -78,10 +78,18 @@ module ActionController #:nodoc: # Caches the +actions+ using the page-caching approach that'll store the cache in a path within the page_cache_directory that # matches the triggering url. + # + # Usage: + # + # # cache the index action + # caches_page :index + # + # # cache the index action except for JSON requests + # caches_page :index, :if => Proc.new { |c| !c.request.format.json? } def caches_page(*actions) return unless perform_caching - actions = actions.map(&:to_s) - after_filter { |c| c.cache_page if actions.include?(c.action_name) } + options = actions.extract_options! + after_filter({:only => actions}.merge(options)) { |c| c.cache_page } end private diff --git a/actionpack/lib/action_controller/dispatcher.rb b/actionpack/lib/action_controller/dispatcher.rb index 92576bdb2b..6e1e7a261f 100644 --- a/actionpack/lib/action_controller/dispatcher.rb +++ b/actionpack/lib/action_controller/dispatcher.rb @@ -5,6 +5,30 @@ module ActionController @@guard = Mutex.new class << self + def define_dispatcher_callbacks(cache_classes) + unless cache_classes + # Development mode callbacks + before_dispatch :reload_application + after_dispatch :cleanup_application + end + + # Common callbacks + to_prepare :load_application_controller do + begin + require_dependency 'application' unless defined?(::ApplicationController) + rescue LoadError => error + raise unless error.message =~ /application\.rb/ + end + end + + if defined?(ActiveRecord) + before_dispatch { ActiveRecord::Base.verify_active_connections! } + to_prepare(:activerecord_instantiate_observers) { ActiveRecord::Base.instantiate_observers } + end + + after_dispatch :flush_logger if defined?(RAILS_DEFAULT_LOGGER) && RAILS_DEFAULT_LOGGER.respond_to?(:flush) + end + # Backward-compatible class method takes CGI-specific args. Deprecated # in favor of Dispatcher.new(output, request, response).dispatch. def dispatch(cgi = nil, session_options = CgiRequest::DEFAULT_SESSION_OPTIONS, output = $stdout) @@ -22,7 +46,7 @@ module ActionController def to_prepare(identifier = nil, &block) @prepare_dispatch_callbacks ||= ActiveSupport::Callbacks::CallbackChain.new callback = ActiveSupport::Callbacks::Callback.new(:prepare_dispatch, block, :identifier => identifier) - @prepare_dispatch_callbacks.replace_or_append_callback(callback) + @prepare_dispatch_callbacks | callback end # If the block raises, send status code as a last-ditch response. @@ -67,25 +91,11 @@ module ActionController end cattr_accessor :error_file_path - self.error_file_path = "#{::RAILS_ROOT}/public" if defined? ::RAILS_ROOT - - cattr_accessor :unprepared - self.unprepared = true + self.error_file_path = Rails.public_path if defined?(Rails.public_path) include ActiveSupport::Callbacks define_callbacks :prepare_dispatch, :before_dispatch, :after_dispatch - before_dispatch :reload_application - before_dispatch :prepare_application - after_dispatch :flush_logger - after_dispatch :cleanup_application - - if defined? ActiveRecord - to_prepare :activerecord_instantiate_observers do - ActiveRecord::Base.instantiate_observers - end - end - def initialize(output, request = nil, response = nil) @output, @request, @response = output, request, response end @@ -114,40 +124,23 @@ module ActionController end def reload_application - if Dependencies.load? - Routing::Routes.reload - self.unprepared = true - end - end + # Run prepare callbacks before every request in development mode + run_callbacks :prepare_dispatch - def prepare_application(force = false) - begin - require_dependency 'application' unless defined?(::ApplicationController) - rescue LoadError => error - raise unless error.message =~ /application\.rb/ - end - - ActiveRecord::Base.verify_active_connections! if defined?(ActiveRecord) - - if unprepared || force - run_callbacks :prepare_dispatch - ActionView::TemplateFinder.reload! unless ActionView::Base.cache_template_loading - self.unprepared = false - end + Routing::Routes.reload + ActionView::TemplateFinder.reload! unless ActionView::Base.cache_template_loading end # Cleanup the application by clearing out loaded classes so they can # be reloaded on the next request without restarting the server. - def cleanup_application(force = false) - if Dependencies.load? || force - ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord) - Dependencies.clear - ActiveRecord::Base.clear_reloadable_connections! if defined?(ActiveRecord) - end + def cleanup_application + ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord) + Dependencies.clear + ActiveRecord::Base.clear_reloadable_connections! if defined?(ActiveRecord) end def flush_logger - RAILS_DEFAULT_LOGGER.flush if defined?(RAILS_DEFAULT_LOGGER) && RAILS_DEFAULT_LOGGER.respond_to?(:flush) + RAILS_DEFAULT_LOGGER.flush end protected diff --git a/actionpack/lib/action_controller/filters.rb b/actionpack/lib/action_controller/filters.rb index 73721cd1ec..8c97787741 100644 --- a/actionpack/lib/action_controller/filters.rb +++ b/actionpack/lib/action_controller/filters.rb @@ -265,7 +265,7 @@ module ActionController #:nodoc: def skip_filter_in_chain(*filters, &test) filters, conditions = extract_options(filters) filters.each do |filter| - if callback = find_callback(filter) then delete(callback) end + if callback = find(filter) then delete(callback) end end if conditions.empty? update_filter_in_chain(filters, :skip => conditions, &test) end @@ -302,7 +302,7 @@ module ActionController #:nodoc: def find_or_create_filter(filter, filter_type, options = {}) update_filter_in_chain([filter], options) - if found_filter = find_callback(filter) { |f| f.type == filter_type } + if found_filter = find(filter) { |f| f.type == filter_type } found_filter else filter_kind = case @@ -326,7 +326,7 @@ module ActionController #:nodoc: end def update_filter_in_chain(filters, options, &test) - filters.map! { |f| block_given? ? find_callback(f, &test) : find_callback(f) } + filters.map! { |f| block_given? ? find(f, &test) : find(f) } filters.compact! map! do |filter| diff --git a/actionpack/lib/action_controller/layout.rb b/actionpack/lib/action_controller/layout.rb index 5484add3b5..b5b59f2d7c 100644 --- a/actionpack/lib/action_controller/layout.rb +++ b/actionpack/lib/action_controller/layout.rb @@ -244,9 +244,7 @@ module ActionController #:nodoc: def render_with_a_layout(options = nil, extra_options = {}, &block) #:nodoc: template_with_options = options.is_a?(Hash) - if apply_layout?(template_with_options, options) && (layout = pick_layout(template_with_options, options)) - assert_existence_of_template_file(layout) - + if (layout = pick_layout(template_with_options, options)) && apply_layout?(template_with_options, options) options = options.merge :layout => false if template_with_options logger.info("Rendering template within #{layout}") if logger diff --git a/actionpack/lib/action_controller/rescue.rb b/actionpack/lib/action_controller/rescue.rb index b91115a93c..d4d561bdb7 100644 --- a/actionpack/lib/action_controller/rescue.rb +++ b/actionpack/lib/action_controller/rescue.rb @@ -26,7 +26,7 @@ module ActionController #:nodoc: DEFAULT_RESCUE_TEMPLATE = 'diagnostics' DEFAULT_RESCUE_TEMPLATES = { - 'ActionController::MissingTemplate' => 'missing_template', + 'ActionView::MissingTemplate' => 'missing_template', 'ActionController::RoutingError' => 'routing_error', 'ActionController::UnknownAction' => 'unknown_action', 'ActionView::TemplateError' => 'template_error' @@ -153,7 +153,7 @@ module ActionController #:nodoc: # If the file doesn't exist, the body of the response will be left empty. def render_optional_error_file(status_code) status = interpret_status(status_code) - path = "#{RAILS_ROOT}/public/#{status[0,3]}.html" + path = "#{Rails.public_path}/#{status[0,3]}.html" if File.exist?(path) render :file => path, :status => status else diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index e20812d308..609334d52d 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -30,6 +30,7 @@ require 'action_view/template_handlers/rjs' require 'action_view/template_finder' require 'action_view/template' require 'action_view/partial_template' +require 'action_view/inline_template' require 'action_view/base' require 'action_view/partials' @@ -37,6 +38,8 @@ require 'action_view/template_error' ActionView::Base.class_eval do include ActionView::Partials -end -ActionView::Base.load_helpers + ActionView::Base.helper_modules.each do |helper_module| + include helper_module + end +end diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index e83c8b6bd3..12dd7d2bc9 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -1,6 +1,9 @@ module ActionView #:nodoc: class ActionViewError < StandardError #:nodoc: end + + class MissingTemplate < ActionViewError #:nodoc: + end # Action View templates can be written in three ways. If the template file has a +.erb+ (or +.rhtml+) extension then it uses a mixture of ERb # (included in Ruby) and HTML. If the template file has a +.builder+ (or +.rxml+) extension then Jim Weirich's Builder::XmlMarkup library is used. @@ -202,15 +205,17 @@ module ActionView #:nodoc: class ObjectWrapper < Struct.new(:value) #:nodoc: end - def self.load_helpers #:nodoc: - Dir.entries("#{File.dirname(__FILE__)}/helpers").sort.each do |file| + def self.helper_modules #:nodoc: + helpers = [] + Dir.entries(File.expand_path("#{File.dirname(__FILE__)}/helpers")).sort.each do |file| next unless file =~ /^([a-z][a-z_]*_helper).rb$/ require "action_view/helpers/#{$1}" helper_module_name = $1.camelize if Helpers.const_defined?(helper_module_name) - include Helpers.const_get(helper_module_name) + helpers << Helpers.const_get(helper_module_name) end end + return helpers end def initialize(view_paths = [], assigns_for_first_render = {}, controller = nil)#:nodoc: @@ -279,7 +284,7 @@ If you are rendering a subtemplate, you must now use controller-like partial syn elsif options[:partial] render_partial(options[:partial], ActionView::Base::ObjectWrapper.new(options[:object]), options[:locals]) elsif options[:inline] - template = Template.new(self, options[:inline], false, options[:locals], true, options[:type]) + template = InlineTemplate.new(self, options[:inline], options[:locals], options[:type]) render_template(template) end end @@ -320,7 +325,7 @@ If you are rendering a subtemplate, you must now use controller-like partial syn end end - private + private def wrap_content_for_layout(content) original_content_for_layout = @content_for_layout @content_for_layout = content diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb index d57d1e0903..0cce96b184 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb @@ -101,7 +101,7 @@ module ActionView # something like Live HTTP Headers for Firefox to verify that the cache is indeed working (and that the assets are not being # requested over and over). module AssetTagHelper - ASSETS_DIR = defined?(RAILS_ROOT) ? "#{RAILS_ROOT}/public" : "public" + ASSETS_DIR = defined?(Rails.public_path) ? Rails.public_path : "public" JAVASCRIPTS_DIR = "#{ASSETS_DIR}/javascripts" STYLESHEETS_DIR = "#{ASSETS_DIR}/stylesheets" @@ -474,7 +474,7 @@ module ActionView ActionView::Base.computed_public_paths[cache_key] ||= begin - source += ".#{ext}" if File.extname(source).blank? && ext + source += ".#{ext}" if ext && File.extname(source).blank? || File.exist?(File.join(ASSETS_DIR, dir, "#{source}.#{ext}")) if source =~ %r{^[-a-z]+://} source @@ -566,7 +566,7 @@ module ActionView def expand_javascript_sources(sources) if sources.include?(:all) - all_javascript_files = Dir[File.join(JAVASCRIPTS_DIR, '*.js')].collect { |file| File.basename(file).split(".", 0).first }.sort + all_javascript_files = Dir[File.join(JAVASCRIPTS_DIR, '*.js')].collect { |file| File.basename(file).gsub(/\.\w+$/, '') }.sort @@all_javascript_sources ||= ((determine_source(:defaults, @@javascript_expansions).dup & all_javascript_files) + all_javascript_files).uniq else expanded_sources = sources.collect do |source| @@ -579,7 +579,7 @@ module ActionView def expand_stylesheet_sources(sources) if sources.first == :all - @@all_stylesheet_sources ||= Dir[File.join(STYLESHEETS_DIR, '*.css')].collect { |file| File.basename(file).split(".", 0).first }.sort + @@all_stylesheet_sources ||= Dir[File.join(STYLESHEETS_DIR, '*.css')].collect { |file| File.basename(file).gsub(/\.\w+$/, '') }.sort else sources.collect do |source| determine_source(source, @@stylesheet_expansions) diff --git a/actionpack/lib/action_view/inline_template.rb b/actionpack/lib/action_view/inline_template.rb new file mode 100644 index 0000000000..87c012d181 --- /dev/null +++ b/actionpack/lib/action_view/inline_template.rb @@ -0,0 +1,20 @@ +module ActionView #:nodoc: + class InlineTemplate < Template #:nodoc: + + def initialize(view, source, locals = {}, type = nil) + @view = view + @finder = @view.finder + + @source = source + @extension = type + @locals = locals || {} + + @handler = self.class.handler_class_for_extension(@extension).new(@view) + end + + def method_key + @source + end + + end +end diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 0cd6784fd8..bc3d8d5e52 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -2,22 +2,18 @@ module ActionView #:nodoc: class Template #:nodoc: attr_accessor :locals - attr_reader :handler, :path, :source, :extension, :filename, :path_without_extension, :method + attr_reader :handler, :path, :extension, :filename, :path_without_extension, :method - def initialize(view, path_or_source, use_full_path, locals = {}, inline = false, inline_type = nil) + def initialize(view, path, use_full_path, locals = {}) @view = view @finder = @view.finder - unless inline - # Clear the forward slash at the beginning if exists - @path = use_full_path ? path_or_source.sub(/^\//, '') : path_or_source - @view.first_render ||= @path - @source = nil # Don't read the source until we know that it is required - set_extension_and_file_name(use_full_path) - else - @source = path_or_source - @extension = inline_type - end + # Clear the forward slash at the beginning if exists + @path = use_full_path ? path.sub(/^\//, '') : path + @view.first_render ||= @path + @source = nil # Don't read the source until we know that it is required + set_extension_and_file_name(use_full_path) + @locals = locals || {} @handler = self.class.handler_class_for_extension(@extension).new(@view) end @@ -32,7 +28,7 @@ module ActionView #:nodoc: end def method_key - @method_key ||= (@filename || @source) + @filename end def base_path_for_exception @@ -58,9 +54,8 @@ module ActionView #:nodoc: @filename = @finder.pick_template(@path_without_extension, @extension) else @extension = @finder.pick_template_extension(@path).to_s - unless @extension - raise ActionViewError, "No template found for #{@path} in #{@finder.view_paths.inspect}" - end + raise_missing_template_exception unless @extension + @filename = @finder.pick_template(@path, @extension) @extension = @extension.gsub(/^.+\./, '') # strip off any formats end @@ -68,9 +63,14 @@ module ActionView #:nodoc: @filename = @path end - if @filename.blank? - raise ActionViewError, "Couldn't find template file for #{@path} in #{@finder.view_paths.inspect}" - end + raise_missing_template_exception if @filename.blank? + end + + def raise_missing_template_exception + full_template_path = @path.include?('.') ? @path : "#{@path}.#{@view.template_format}.erb" + display_paths = @finder.view_paths.join(':') + template_type = (@path =~ /layouts/i) ? 'layout' : 'template' + raise(MissingTemplate, "Missing #{template_type} #{full_template_path} in view path #{display_paths}") end # Template Handlers diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb new file mode 100644 index 0000000000..b2e6589d81 --- /dev/null +++ b/actionpack/lib/action_view/test_case.rb @@ -0,0 +1,64 @@ +require 'active_support/test_case' + +module ActionView + class NonInferrableHelperError < ActionViewError + def initialize(name) + super "Unable to determine the helper to test from #{name}. " + + "You'll need to specify it using tests YourHelper in your " + + "test case definition" + end + end + + class TestCase < ActiveSupport::TestCase + class_inheritable_accessor :helper_class + @@helper_class = nil + + class << self + def tests(helper_class) + self.helper_class = helper_class + end + + def helper_class + if current_helper_class = read_inheritable_attribute(:helper_class) + current_helper_class + else + self.helper_class = determine_default_helper_class(name) + end + end + + def determine_default_helper_class(name) + name.sub(/Test$/, '').constantize + rescue NameError + raise NonInferrableHelperError.new(name) + end + end + + ActionView::Base.helper_modules.each do |helper_module| + include helper_module + end + include ActionController::PolymorphicRoutes + include ActionController::RecordIdentifier + + setup :setup_with_helper_class + + def setup_with_helper_class + self.class.send(:include, helper_class) + end + + class TestController < ActionController::Base + attr_accessor :request, :response + + def initialize + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + end + end + + private + def method_missing(selector, *args) + controller = TestController.new + return controller.send!(selector, *args) if ActionController::Routing::Routes.named_routes.helpers.include?(selector) + super + end + end +end diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index 700bc1f5e3..fa1c3293b4 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -8,6 +8,7 @@ require 'test/unit' require 'action_controller' require 'action_controller/cgi_ext' require 'action_controller/test_process' +require 'action_view/test_case' begin require 'ruby-debug' @@ -19,7 +20,6 @@ end ActiveSupport::Deprecation.debug = true ActionController::Base.logger = nil -ActionController::Base.ignore_missing_templates = false ActionController::Routing::Routes.reload rescue nil diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb index 7bd64e2870..ddc1c68383 100644 --- a/actionpack/test/controller/caching_test.rb +++ b/actionpack/test/controller/caching_test.rb @@ -8,7 +8,8 @@ ActionController::Base.page_cache_directory = FILE_STORE_PATH ActionController::Base.cache_store = :file_store, FILE_STORE_PATH class PageCachingTestController < ActionController::Base - caches_page :ok, :no_content, :found, :not_found + caches_page :ok, :no_content, :if => Proc.new { |c| !c.request.format.json? } + caches_page :found, :not_found def ok head :ok @@ -127,6 +128,12 @@ class PageCachingTest < Test::Unit::TestCase end end end + + def test_page_caching_conditional_options + @request.env['HTTP_ACCEPT'] = 'application/json' + get :ok + assert_page_not_cached :ok + end private def assert_page_cached(action, message = "#{action} should have been cached") diff --git a/actionpack/test/controller/cookie_test.rb b/actionpack/test/controller/cookie_test.rb index 0483fe918a..42f3bd26a4 100644 --- a/actionpack/test/controller/cookie_test.rb +++ b/actionpack/test/controller/cookie_test.rb @@ -37,7 +37,7 @@ class CookieTest < Test::Unit::TestCase end def rescue_action(e) - raise unless ActionController::MissingTemplate # No templates here, and we don't care about the output + raise unless ActionView::MissingTemplate # No templates here, and we don't care about the output end end diff --git a/actionpack/test/controller/custom_handler_test.rb b/actionpack/test/controller/custom_handler_test.rb index cf1e2361bd..ac484ae17e 100644 --- a/actionpack/test/controller/custom_handler_test.rb +++ b/actionpack/test/controller/custom_handler_test.rb @@ -20,7 +20,7 @@ class CustomHandlerTest < Test::Unit::TestCase end def test_custom_render - template = ActionView::Template.new(@view, "hello <%= one %>", false, { :one => "two" }, true, "foo") + template = ActionView::InlineTemplate.new(@view, "hello <%= one %>", { :one => "two" }, "foo") result = @view.render_template(template) assert_equal( @@ -29,7 +29,7 @@ class CustomHandlerTest < Test::Unit::TestCase end def test_custom_render2 - template = ActionView::Template.new(@view, "hello <%= one %>", false, { :one => "two" }, true, "foo2") + template = ActionView::InlineTemplate.new(@view, "hello <%= one %>", { :one => "two" }, "foo2") result = @view.render_template(template) assert_equal( [ "hello <%= one %>", { :one => "two" }, @view ], @@ -38,7 +38,7 @@ class CustomHandlerTest < Test::Unit::TestCase def test_unhandled_extension # uses the ERb handler by default if the extension isn't recognized - template = ActionView::Template.new(@view, "hello <%= one %>", false, { :one => "two" }, true, "bar") + template = ActionView::InlineTemplate.new(@view, "hello <%= one %>", { :one => "two" }, "bar") result = @view.render_template(template) assert_equal "hello two", result end diff --git a/actionpack/test/controller/dispatcher_test.rb b/actionpack/test/controller/dispatcher_test.rb index 9f90872734..eea0813ed5 100644 --- a/actionpack/test/controller/dispatcher_test.rb +++ b/actionpack/test/controller/dispatcher_test.rb @@ -11,7 +11,13 @@ class DispatcherTest < Test::Unit::TestCase @output = StringIO.new ENV['REQUEST_METHOD'] = 'GET' + # Clear callbacks as they are redefined by Dispatcher#define_dispatcher_callbacks Dispatcher.instance_variable_set("@prepare_dispatch_callbacks", ActiveSupport::Callbacks::CallbackChain.new) + Dispatcher.instance_variable_set("@before_dispatch_callbacks", ActiveSupport::Callbacks::CallbackChain.new) + Dispatcher.instance_variable_set("@after_dispatch_callbacks", ActiveSupport::Callbacks::CallbackChain.new) + + Dispatcher.stubs(:require_dependency) + @dispatcher = Dispatcher.new(@output) end @@ -20,68 +26,52 @@ class DispatcherTest < Test::Unit::TestCase end def test_clears_dependencies_after_dispatch_if_in_loading_mode - Dependencies.stubs(:load?).returns(true) - ActionController::Routing::Routes.expects(:reload).once Dependencies.expects(:clear).once - dispatch + dispatch(@output, false) end def test_leaves_dependencies_after_dispatch_if_not_in_loading_mode - Dependencies.stubs(:load?).returns(false) - ActionController::Routing::Routes.expects(:reload).never Dependencies.expects(:clear).never dispatch end + # Stub out dispatch error logger + class << Dispatcher + def log_failsafe_exception(status, exception); end + end + def test_failsafe_response CGI.expects(:new).raises('some multipart parsing failure') - - ActionController::Routing::Routes.stubs(:reload) - Dispatcher.any_instance.stubs(:log_failsafe_exception) + Dispatcher.expects(:log_failsafe_exception) assert_nothing_raised { dispatch } assert_equal "Status: 400 Bad Request\r\nContent-Type: text/html\r\n\r\n<html><body><h1>400 Bad Request</h1></body></html>", @output.string end - def test_reload_application_sets_unprepared_if_loading_dependencies - Dependencies.stubs(:load?).returns(false) - ActionController::Routing::Routes.expects(:reload).never - @dispatcher.unprepared = false - @dispatcher.send!(:reload_application) - assert !@dispatcher.unprepared - - Dependencies.stubs(:load?).returns(true) - ActionController::Routing::Routes.expects(:reload).once - @dispatcher.send!(:reload_application) - assert @dispatcher.unprepared - end - - def test_prepare_application_runs_callbacks_if_unprepared + def test_prepare_callbacks a = b = c = nil Dispatcher.to_prepare { |*args| a = b = c = 1 } Dispatcher.to_prepare { |*args| b = c = 2 } Dispatcher.to_prepare { |*args| c = 3 } - # Skip the callbacks when already prepared. - @dispatcher.unprepared = false - @dispatcher.send! :prepare_application + # Ensure to_prepare callbacks are not run when defined assert_nil a || b || c - # Perform the callbacks when unprepared. - @dispatcher.unprepared = true - @dispatcher.send! :prepare_application + # Run callbacks + @dispatcher.send :run_callbacks, :prepare_dispatch + assert_equal 1, a assert_equal 2, b assert_equal 3, c - # But when not :load, make sure they are only run once + # Make sure they are only run once a = b = c = nil - @dispatcher.send! :prepare_application + @dispatcher.send :dispatch assert_nil a || b || c end @@ -90,28 +80,20 @@ class DispatcherTest < Test::Unit::TestCase Dispatcher.to_prepare(:unique_id) { |*args| a = b = 1 } Dispatcher.to_prepare(:unique_id) { |*args| a = 2 } - @dispatcher.unprepared = true - @dispatcher.send! :prepare_application + @dispatcher.send :run_callbacks, :prepare_dispatch assert_equal 2, a assert_equal nil, b end - def test_to_prepare_only_runs_once_if_not_loading_dependencies - Dependencies.stubs(:load?).returns(false) - called = 0 - Dispatcher.to_prepare(:unprepared_test) { |*args| called += 1 } - 2.times { dispatch } - assert_equal 1, called - end - private - def dispatch(output = @output) + def dispatch(output = @output, cache_classes = true) controller = mock controller.stubs(:process).returns(controller) controller.stubs(:out).with(output).returns('response') ActionController::Routing::Routes.stubs(:recognize).returns(controller) + Dispatcher.define_dispatcher_callbacks(cache_classes) Dispatcher.dispatch(nil, {}, output) end diff --git a/actionpack/test/controller/flash_test.rb b/actionpack/test/controller/flash_test.rb index f672f2f427..e562531bf3 100644 --- a/actionpack/test/controller/flash_test.rb +++ b/actionpack/test/controller/flash_test.rb @@ -52,7 +52,7 @@ class FlashTest < Test::Unit::TestCase end def rescue_action(e) - raise unless ActionController::MissingTemplate === e + raise unless ActionView::MissingTemplate === e end # methods for test_sweep_after_halted_filter_chain diff --git a/actionpack/test/controller/layout_test.rb b/actionpack/test/controller/layout_test.rb index 145543a357..3dc311b78a 100644 --- a/actionpack/test/controller/layout_test.rb +++ b/actionpack/test/controller/layout_test.rb @@ -216,7 +216,7 @@ class LayoutExceptionRaised < Test::Unit::TestCase @controller = SetsNonExistentLayoutFile.new get :hello @response.template.class.module_eval { attr_accessor :exception } - assert_equal ActionController::MissingTemplate, @response.template.exception.class + assert_equal ActionView::MissingTemplate, @response.template.exception.class end end diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb index c34643ddd5..c617cb2e84 100644 --- a/actionpack/test/controller/mime_responds_test.rb +++ b/actionpack/test/controller/mime_responds_test.rb @@ -468,7 +468,7 @@ class MimeControllerTest < Test::Unit::TestCase assert_equal '<html><div id="html_missing">Hello future from Firefox!</div></html>', @response.body @request.env["HTTP_ACCEPT"] = "text/iphone" - assert_raises(ActionController::MissingTemplate) { get :iphone_with_html_response_type_without_layout } + assert_raises(ActionView::MissingTemplate) { get :iphone_with_html_response_type_without_layout } end end diff --git a/actionpack/test/controller/new_render_test.rb b/actionpack/test/controller/new_render_test.rb index 342e2e7f87..80cf09e5f3 100644 --- a/actionpack/test/controller/new_render_test.rb +++ b/actionpack/test/controller/new_render_test.rb @@ -652,7 +652,7 @@ EOS end def test_bad_render_to_string_still_throws_exception - assert_raises(ActionController::MissingTemplate) { get :render_to_string_with_exception } + assert_raises(ActionView::MissingTemplate) { get :render_to_string_with_exception } end def test_render_to_string_that_throws_caught_exception_doesnt_break_assigns @@ -787,7 +787,7 @@ EOS end def test_render_missing_partial_template - assert_raises(ActionView::ActionViewError) do + assert_raises(ActionView::MissingTemplate) do get :missing_partial end end diff --git a/actionpack/test/controller/rescue_test.rb b/actionpack/test/controller/rescue_test.rb index 55631e0777..27fcc5e04c 100644 --- a/actionpack/test/controller/rescue_test.rb +++ b/actionpack/test/controller/rescue_test.rb @@ -279,7 +279,7 @@ class RescueTest < Test::Unit::TestCase assert_equal ActionController::Rescue::DEFAULT_RESCUE_TEMPLATE, templates.default assert_equal ActionController::Rescue::DEFAULT_RESCUE_TEMPLATE, templates[Exception.new] - assert_equal 'missing_template', templates[ActionController::MissingTemplate.name] + assert_equal 'missing_template', templates[ActionView::MissingTemplate.name] assert_equal 'routing_error', templates[ActionController::RoutingError.name] assert_equal 'unknown_action', templates[ActionController::UnknownAction.name] assert_equal 'template_error', templates[ActionView::TemplateError.name] @@ -305,7 +305,9 @@ class RescueTest < Test::Unit::TestCase def test_not_implemented with_all_requests_local false do - head :not_implemented + with_rails_public_path(".") do + head :not_implemented + end end assert_response :not_implemented assert_equal "GET, PUT", @response.headers['Allow'] @@ -313,7 +315,9 @@ class RescueTest < Test::Unit::TestCase def test_method_not_allowed with_all_requests_local false do - get :method_not_allowed + with_rails_public_path(".") do + get :method_not_allowed + end end assert_response :method_not_allowed assert_equal "GET, HEAD, PUT", @response.headers['Allow'] @@ -391,7 +395,19 @@ class RescueTest < Test::Unit::TestCase @request.remote_addr = old_remote_addr end - def with_rails_root(path = nil) + def with_rails_public_path(rails_root) + old_rails = Object.const_get(:Rails) rescue nil + mod = Object.const_set(:Rails, Module.new) + (class << mod; self; end).instance_eval do + define_method(:public_path) { "#{rails_root}/public" } + end + yield + ensure + Object.module_eval { remove_const(:Rails) } if defined?(Rails) + Object.const_set(:Rails, old_rails) if old_rails + end + + def with_rails_root(path = nil,&block) old_rails_root = RAILS_ROOT if defined?(RAILS_ROOT) if path silence_warnings { Object.const_set(:RAILS_ROOT, path) } @@ -399,7 +415,7 @@ class RescueTest < Test::Unit::TestCase Object.remove_const(:RAILS_ROOT) rescue nil end - yield + with_rails_public_path(path, &block) ensure if old_rails_root diff --git a/actionpack/test/fixtures/public/javascripts/version.1.0.js b/actionpack/test/fixtures/public/javascripts/version.1.0.js new file mode 100644 index 0000000000..cfd5fce70e --- /dev/null +++ b/actionpack/test/fixtures/public/javascripts/version.1.0.js @@ -0,0 +1 @@ +// version.1.0 js
\ No newline at end of file diff --git a/actionpack/test/fixtures/public/stylesheets/version.1.0.css b/actionpack/test/fixtures/public/stylesheets/version.1.0.css new file mode 100644 index 0000000000..30f5f9ba6e --- /dev/null +++ b/actionpack/test/fixtures/public/stylesheets/version.1.0.css @@ -0,0 +1 @@ +/* version.1.0.css */
\ No newline at end of file diff --git a/actionpack/test/template/active_record_helper_test.rb b/actionpack/test/template/active_record_helper_test.rb index 31fe7bbc29..dfc30e651a 100644 --- a/actionpack/test/template/active_record_helper_test.rb +++ b/actionpack/test/template/active_record_helper_test.rb @@ -1,12 +1,7 @@ require 'abstract_unit' -class ActiveRecordHelperTest < Test::Unit::TestCase - include ActionView::Helpers::FormHelper - include ActionView::Helpers::ActiveRecordHelper - include ActionView::Helpers::TextHelper - include ActionView::Helpers::TagHelper - include ActionView::Helpers::UrlHelper - include ActionView::Helpers::FormTagHelper +class ActiveRecordHelperTest < ActionView::TestCase + tests ActionView::Helpers::ActiveRecordHelper silence_warnings do Post = Struct.new("Post", :title, :author_name, :body, :secret, :written_on) diff --git a/actionpack/test/template/asset_tag_helper_test.rb b/actionpack/test/template/asset_tag_helper_test.rb index be605329fc..4a8117a88a 100644 --- a/actionpack/test/template/asset_tag_helper_test.rb +++ b/actionpack/test/template/asset_tag_helper_test.rb @@ -1,9 +1,7 @@ require 'abstract_unit' -class AssetTagHelperTest < Test::Unit::TestCase - include ActionView::Helpers::TagHelper - include ActionView::Helpers::UrlHelper - include ActionView::Helpers::AssetTagHelper +class AssetTagHelperTest < ActionView::TestCase + tests ActionView::Helpers::AssetTagHelper def setup silence_warnings do @@ -84,7 +82,7 @@ class AssetTagHelperTest < Test::Unit::TestCase %(javascript_include_tag("xmlhr", :lang => "vbscript")) => %(<script lang="vbscript" src="/javascripts/xmlhr.js" type="text/javascript"></script>), %(javascript_include_tag("common.javascript", "/elsewhere/cools")) => %(<script src="/javascripts/common.javascript" type="text/javascript"></script>\n<script src="/elsewhere/cools.js" type="text/javascript"></script>), %(javascript_include_tag(:defaults)) => %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), - %(javascript_include_tag(:all)) => %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>), + %(javascript_include_tag(:all)) => %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>\n<script src="/javascripts/version.1.0.js" type="text/javascript"></script>), %(javascript_include_tag(:defaults, "test")) => %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/test.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), %(javascript_include_tag("test", :defaults)) => %(<script src="/javascripts/test.js" type="text/javascript"></script>\n<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>) } @@ -109,8 +107,8 @@ class AssetTagHelperTest < Test::Unit::TestCase %(stylesheet_link_tag("/dir/file")) => %(<link href="/dir/file.css" media="screen" rel="stylesheet" type="text/css" />), %(stylesheet_link_tag("dir/file")) => %(<link href="/stylesheets/dir/file.css" media="screen" rel="stylesheet" type="text/css" />), %(stylesheet_link_tag("style", :media => "all")) => %(<link href="/stylesheets/style.css" media="all" rel="stylesheet" type="text/css" />), - %(stylesheet_link_tag(:all)) => %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />), - %(stylesheet_link_tag(:all, :media => "all")) => %(<link href="/stylesheets/bank.css" media="all" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="all" rel="stylesheet" type="text/css" />), + %(stylesheet_link_tag(:all)) => %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" type="text/css" />), + %(stylesheet_link_tag(:all, :media => "all")) => %(<link href="/stylesheets/bank.css" media="all" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="all" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/version.1.0.css" media="all" rel="stylesheet" type="text/css" />), %(stylesheet_link_tag("random.styles", "/css/stylish")) => %(<link href="/stylesheets/random.styles" media="screen" rel="stylesheet" type="text/css" />\n<link href="/css/stylish.css" media="screen" rel="stylesheet" type="text/css" />), %(stylesheet_link_tag("http://www.example.com/styles/style")) => %(<link href="http://www.example.com/styles/style.css" media="screen" rel="stylesheet" type="text/css" />) } @@ -358,7 +356,7 @@ class AssetTagHelperTest < Test::Unit::TestCase assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'combined.js')) assert_equal( - %(// prototype js\n\n// effects js\n\n// dragdrop js\n\n// controls js\n\n// application js\n\n// bank js\n\n// robber js), + %(// prototype js\n\n// effects js\n\n// dragdrop js\n\n// controls js\n\n// application js\n\n// bank js\n\n// robber js\n\n// version.1.0 js), IO.read(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'combined.js')) ) @@ -371,14 +369,14 @@ class AssetTagHelperTest < Test::Unit::TestCase ActionController::Base.perform_caching = false assert_dom_equal( - %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>), + %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>\n<script src="/javascripts/version.1.0.js" type="text/javascript"></script>), javascript_include_tag(:all, :cache => true) ) assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'all.js')) assert_dom_equal( - %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>), + %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>\n<script src="/javascripts/version.1.0.js" type="text/javascript"></script>), javascript_include_tag(:all, :cache => "money") ) @@ -430,14 +428,14 @@ class AssetTagHelperTest < Test::Unit::TestCase ActionController::Base.perform_caching = false assert_dom_equal( - %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" type="text/css" />), stylesheet_link_tag(:all, :cache => true) ) assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css')) assert_dom_equal( - %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" type="text/css" />), stylesheet_link_tag(:all, :cache => "money") ) @@ -445,10 +443,8 @@ class AssetTagHelperTest < Test::Unit::TestCase end end -class AssetTagHelperNonVhostTest < Test::Unit::TestCase - include ActionView::Helpers::TagHelper - include ActionView::Helpers::UrlHelper - include ActionView::Helpers::AssetTagHelper +class AssetTagHelperNonVhostTest < ActionView::TestCase + tests ActionView::Helpers::AssetTagHelper def setup @controller = Class.new do diff --git a/actionpack/test/template/benchmark_helper_test.rb b/actionpack/test/template/benchmark_helper_test.rb index 76c0780482..d95a3dee26 100644 --- a/actionpack/test/template/benchmark_helper_test.rb +++ b/actionpack/test/template/benchmark_helper_test.rb @@ -1,8 +1,8 @@ require 'abstract_unit' require 'action_view/helpers/benchmark_helper' -class BenchmarkHelperTest < Test::Unit::TestCase - include ActionView::Helpers::BenchmarkHelper +class BenchmarkHelperTest < ActionView::TestCase + tests ActionView::Helpers::BenchmarkHelper class MockLogger attr_reader :logged diff --git a/actionpack/test/template/date_helper_test.rb b/actionpack/test/template/date_helper_test.rb index 25b1f9f002..9bd433e76b 100755 --- a/actionpack/test/template/date_helper_test.rb +++ b/actionpack/test/template/date_helper_test.rb @@ -1,8 +1,7 @@ require 'abstract_unit' -class DateHelperTest < Test::Unit::TestCase - include ActionView::Helpers::DateHelper - include ActionView::Helpers::FormHelper +class DateHelperTest < ActionView::TestCase + tests ActionView::Helpers::DateHelper silence_warnings do Post = Struct.new("Post", :id, :written_on, :updated_at) diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb index 766e88375b..c48d5dfd2d 100644 --- a/actionpack/test/template/form_helper_test.rb +++ b/actionpack/test/template/form_helper_test.rb @@ -30,15 +30,8 @@ end class Comment::Nested < Comment; end -class FormHelperTest < Test::Unit::TestCase - include ActionView::Helpers::FormHelper - include ActionView::Helpers::FormTagHelper - include ActionView::Helpers::UrlHelper - include ActionView::Helpers::TagHelper - include ActionView::Helpers::TextHelper - include ActionView::Helpers::ActiveRecordHelper - include ActionView::Helpers::RecordIdentificationHelper - include ActionController::PolymorphicRoutes +class FormHelperTest < ActionView::TestCase + tests ActionView::Helpers::FormHelper def setup @post = Post.new diff --git a/actionpack/test/template/form_options_helper_test.rb b/actionpack/test/template/form_options_helper_test.rb index f3ecc18233..48a26deea9 100644 --- a/actionpack/test/template/form_options_helper_test.rb +++ b/actionpack/test/template/form_options_helper_test.rb @@ -22,9 +22,8 @@ end ActionView::Helpers::FormOptionsHelper::TimeZone = MockTimeZone -class FormOptionsHelperTest < Test::Unit::TestCase - include ActionView::Helpers::FormHelper - include ActionView::Helpers::FormOptionsHelper +class FormOptionsHelperTest < ActionView::TestCase + tests ActionView::Helpers::FormOptionsHelper silence_warnings do Post = Struct.new('Post', :title, :author_name, :body, :secret, :written_on, :category, :origin) diff --git a/actionpack/test/template/form_tag_helper_test.rb b/actionpack/test/template/form_tag_helper_test.rb index 7caa85802a..73a8bd4d87 100644 --- a/actionpack/test/template/form_tag_helper_test.rb +++ b/actionpack/test/template/form_tag_helper_test.rb @@ -1,11 +1,7 @@ require 'abstract_unit' -class FormTagHelperTest < Test::Unit::TestCase - include ActionView::Helpers::UrlHelper - include ActionView::Helpers::TagHelper - include ActionView::Helpers::FormTagHelper - include ActionView::Helpers::TextHelper - include ActionView::Helpers::CaptureHelper +class FormTagHelperTest < ActionView::TestCase + tests ActionView::Helpers::FormTagHelper def setup @controller = Class.new do diff --git a/actionpack/test/template/javascript_helper_test.rb b/actionpack/test/template/javascript_helper_test.rb index 581ca58f89..f18adb990c 100644 --- a/actionpack/test/template/javascript_helper_test.rb +++ b/actionpack/test/template/javascript_helper_test.rb @@ -1,13 +1,7 @@ require 'abstract_unit' -class JavaScriptHelperTest < Test::Unit::TestCase - include ActionView::Helpers::JavaScriptHelper - - include ActionView::Helpers::UrlHelper - include ActionView::Helpers::TagHelper - include ActionView::Helpers::TextHelper - include ActionView::Helpers::FormHelper - include ActionView::Helpers::CaptureHelper +class JavaScriptHelperTest < ActionView::TestCase + tests ActionView::Helpers::JavaScriptHelper def test_define_javascript_functions # check if prototype.js is included first diff --git a/actionpack/test/template/number_helper_test.rb b/actionpack/test/template/number_helper_test.rb index 7065ca7a84..4a8d09b544 100644 --- a/actionpack/test/template/number_helper_test.rb +++ b/actionpack/test/template/number_helper_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' -class NumberHelperTest < Test::Unit::TestCase - include ActionView::Helpers::NumberHelper +class NumberHelperTest < ActionView::TestCase + tests ActionView::Helpers::NumberHelper def test_number_to_phone assert_equal("800-555-1212", number_to_phone(8005551212)) diff --git a/actionpack/test/template/prototype_helper_test.rb b/actionpack/test/template/prototype_helper_test.rb index 28e58b0a08..a84d4e72af 100644 --- a/actionpack/test/template/prototype_helper_test.rb +++ b/actionpack/test/template/prototype_helper_test.rb @@ -24,24 +24,11 @@ end class Author::Nested < Author; end -module BaseTest - def self.included(base) - base.send :attr_accessor, :template_format - end +class PrototypeHelperBaseTest < ActionView::TestCase + tests ActionView::Helpers::PrototypeHelper + + attr_accessor :template_format - include ActionView::Helpers::JavaScriptHelper - include ActionView::Helpers::PrototypeHelper - include ActionView::Helpers::ScriptaculousHelper - - include ActionView::Helpers::UrlHelper - include ActionView::Helpers::TagHelper - include ActionView::Helpers::TextHelper - include ActionView::Helpers::FormTagHelper - include ActionView::Helpers::FormHelper - include ActionView::Helpers::CaptureHelper - include ActionView::Helpers::RecordIdentificationHelper - include ActionController::PolymorphicRoutes - def setup @template = nil @controller = Class.new do @@ -59,25 +46,22 @@ module BaseTest end.new end -protected - - def request_forgery_protection_token - nil - end - - def protect_against_forgery? - false - end - - def create_generator - block = Proc.new { |*args| yield *args if block_given? } - JavaScriptGenerator.new self, &block - end + protected + def request_forgery_protection_token + nil + end + + def protect_against_forgery? + false + end + + def create_generator + block = Proc.new { |*args| yield *args if block_given? } + JavaScriptGenerator.new self, &block + end end -class PrototypeHelperTest < Test::Unit::TestCase - include BaseTest - +class PrototypeHelperTest < PrototypeHelperBaseTest def setup @record = @author = Author.new @article = Article.new @@ -294,9 +278,7 @@ class PrototypeHelperTest < Test::Unit::TestCase end end -class JavaScriptGeneratorTest < Test::Unit::TestCase - include BaseTest - +class JavaScriptGeneratorTest < PrototypeHelperBaseTest def setup super @generator = create_generator diff --git a/actionpack/test/template/record_tag_helper_test.rb b/actionpack/test/template/record_tag_helper_test.rb index bb5440be20..0afbb54f57 100644 --- a/actionpack/test/template/record_tag_helper_test.rb +++ b/actionpack/test/template/record_tag_helper_test.rb @@ -9,14 +9,9 @@ class Post end end -class RecordTagHelperTest < Test::Unit::TestCase - include ActionView::Helpers::RecordTagHelper - include ActionView::Helpers::CaptureHelper - include ActionView::Helpers::RecordIdentificationHelper - include ActionView::Helpers::TagHelper - include ActionView::Helpers::TextHelper - include ActionView::Helpers::UrlHelper - +class RecordTagHelperTest < ActionView::TestCase + tests ActionView::Helpers::RecordTagHelper + def setup @post = Post.new end diff --git a/actionpack/test/template/sanitize_helper_test.rb b/actionpack/test/template/sanitize_helper_test.rb index a840c8b4cb..e5427d9dc1 100644 --- a/actionpack/test/template/sanitize_helper_test.rb +++ b/actionpack/test/template/sanitize_helper_test.rb @@ -3,9 +3,8 @@ require 'testing_sandbox' # The exhaustive tests are in test/controller/html/sanitizer_test.rb. # This tests the that the helpers hook up correctly to the sanitizer classes. -class SanitizeHelperTest < Test::Unit::TestCase - include ActionView::Helpers::SanitizeHelper - include ActionView::Helpers::TagHelper +class SanitizeHelperTest < ActionView::TestCase + tests ActionView::Helpers::SanitizeHelper include TestingSandbox def test_strip_links diff --git a/actionpack/test/template/scriptaculous_helper_test.rb b/actionpack/test/template/scriptaculous_helper_test.rb index 91856ff980..690a7751b5 100644 --- a/actionpack/test/template/scriptaculous_helper_test.rb +++ b/actionpack/test/template/scriptaculous_helper_test.rb @@ -1,16 +1,8 @@ require 'abstract_unit' -class ScriptaculousHelperTest < Test::Unit::TestCase - include ActionView::Helpers::JavaScriptHelper - include ActionView::Helpers::PrototypeHelper - include ActionView::Helpers::ScriptaculousHelper - - include ActionView::Helpers::UrlHelper - include ActionView::Helpers::TagHelper - include ActionView::Helpers::TextHelper - include ActionView::Helpers::FormHelper - include ActionView::Helpers::CaptureHelper - +class ScriptaculousHelperTest < ActionView::TestCase + tests ActionView::Helpers::ScriptaculousHelper + def setup @controller = Class.new do def url_for(options) diff --git a/actionpack/test/template/tag_helper_test.rb b/actionpack/test/template/tag_helper_test.rb index 4b73289060..4da6116095 100644 --- a/actionpack/test/template/tag_helper_test.rb +++ b/actionpack/test/template/tag_helper_test.rb @@ -1,10 +1,7 @@ require 'abstract_unit' -class TagHelperTest < Test::Unit::TestCase - include ActionView::Helpers::TagHelper - include ActionView::Helpers::UrlHelper - include ActionView::Helpers::TextHelper - include ActionView::Helpers::CaptureHelper +class TagHelperTest < ActionView::TestCase + tests ActionView::Helpers::TagHelper def test_tag assert_equal "<br />", tag("br") diff --git a/actionpack/test/template/template_object_test.rb b/actionpack/test/template/template_object_test.rb index b3a33938cf..7adcde421f 100644 --- a/actionpack/test/template/template_object_test.rb +++ b/actionpack/test/template/template_object_test.rb @@ -82,7 +82,7 @@ class TemplateObjectTest < Test::Unit::TestCase def test_xml @view.template_format = :xml - assert_raise ActionView::ActionViewError do + assert_raise ActionView::MissingTemplate do ActionView::PartialTemplate.new(@view, @path, nil) end end diff --git a/actionpack/test/template/test_test.rb b/actionpack/test/template/test_test.rb new file mode 100644 index 0000000000..660f51b3be --- /dev/null +++ b/actionpack/test/template/test_test.rb @@ -0,0 +1,56 @@ +require 'abstract_unit' + +module PeopleHelper + def title(text) + content_tag(:h1, text) + end + + def homepage_path + people_path + end + + def homepage_url + people_url + end + + def link_to_person(person) + link_to person.name, person + end +end + +class PeopleHelperTest < ActionView::TestCase + def setup + ActionController::Routing::Routes.draw do |map| + map.people 'people', :controller => 'people', :action => 'index' + map.connect ':controller/:action/:id' + end + end + + def test_title + assert_equal "<h1>Ruby on Rails</h1>", title("Ruby on Rails") + end + + def test_homepage_path + assert_equal "/people", homepage_path + end + + def test_homepage_url + assert_equal "http://test.host/people", homepage_url + end + + uses_mocha "link_to_person" do + def test_link_to_person + person = mock(:name => "David") + expects(:mocha_mock_path).with(person).returns("/people/1") + assert_equal '<a href="/people/1">David</a>', link_to_person(person) + end + end +end + +class CrazyHelperTest < ActionView::TestCase + tests PeopleHelper + + def test_helper_class_can_be_set_manually_not_just_inferred + assert_equal PeopleHelper, self.class.helper_class + end +end diff --git a/actionpack/test/template/text_helper_test.rb b/actionpack/test/template/text_helper_test.rb index 7d92bce4bd..25ecda687f 100644 --- a/actionpack/test/template/text_helper_test.rb +++ b/actionpack/test/template/text_helper_test.rb @@ -1,9 +1,8 @@ require 'abstract_unit' require 'testing_sandbox' -class TextHelperTest < Test::Unit::TestCase - include ActionView::Helpers::TextHelper - include ActionView::Helpers::TagHelper +class TextHelperTest < ActionView::TestCase + tests ActionView::Helpers::TextHelper include TestingSandbox def setup diff --git a/actionpack/test/template/url_helper_test.rb b/actionpack/test/template/url_helper_test.rb index 9cd3b6e2f9..d45ea08a6f 100644 --- a/actionpack/test/template/url_helper_test.rb +++ b/actionpack/test/template/url_helper_test.rb @@ -2,10 +2,8 @@ require 'abstract_unit' RequestMock = Struct.new("Request", :request_uri, :protocol, :host_with_port, :env) -class UrlHelperTest < Test::Unit::TestCase - include ActionView::Helpers::AssetTagHelper - include ActionView::Helpers::UrlHelper - include ActionView::Helpers::TagHelper +class UrlHelperTest < ActionView::TestCase + tests ActionView::Helpers::UrlHelper def setup @controller = Class.new do @@ -293,7 +291,7 @@ class UrlHelperTest < Test::Unit::TestCase end end -class UrlHelperWithControllerTest < Test::Unit::TestCase +class UrlHelperWithControllerTest < ActionView::TestCase class UrlHelperController < ActionController::Base self.view_paths = [ "#{File.dirname(__FILE__)}/../fixtures/" ] @@ -310,7 +308,7 @@ class UrlHelperWithControllerTest < Test::Unit::TestCase def rescue_action(e) raise e end end - include ActionView::Helpers::UrlHelper + tests ActionView::Helpers::UrlHelper def setup @request = ActionController::TestRequest.new @@ -348,7 +346,7 @@ class UrlHelperWithControllerTest < Test::Unit::TestCase end end -class LinkToUnlessCurrentWithControllerTest < Test::Unit::TestCase +class LinkToUnlessCurrentWithControllerTest < ActionView::TestCase class TasksController < ActionController::Base self.view_paths = ["#{File.dirname(__FILE__)}/../fixtures/"] @@ -372,7 +370,7 @@ class LinkToUnlessCurrentWithControllerTest < Test::Unit::TestCase end end - include ActionView::Helpers::UrlHelper + tests ActionView::Helpers::UrlHelper def setup @request = ActionController::TestRequest.new @@ -440,7 +438,7 @@ class Session end end -class PolymorphicControllerTest < Test::Unit::TestCase +class PolymorphicControllerTest < ActionView::TestCase class WorkshopsController < ActionController::Base self.view_paths = ["#{File.dirname(__FILE__)}/../fixtures/"] @@ -479,7 +477,7 @@ class PolymorphicControllerTest < Test::Unit::TestCase def rescue_action(e) raise e end end - include ActionView::Helpers::UrlHelper + tests ActionView::Helpers::UrlHelper def setup @request = ActionController::TestRequest.new diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb index 503fb10795..b15bdb06ca 100644 --- a/activemodel/lib/active_model/validations.rb +++ b/activemodel/lib/active_model/validations.rb @@ -3,24 +3,7 @@ module ActiveModel def self.included(base) # :nodoc: base.extend(ClassMethods) base.send!(:include, ActiveSupport::Callbacks) - - %w( validate validate_on_create validate_on_update ).each do |validation_method| - base.class_eval <<-"end_eval" - def self.#{validation_method}(*methods, &block) - methods = CallbackChain.build(:#{validation_method}, *methods, &block) - self.#{validation_method}_callback_chain.replace(#{validation_method}_callback_chain | methods) - end - - def self.#{validation_method}_callback_chain - if chain = read_inheritable_attribute(:#{validation_method}) - return chain - else - write_inheritable_attribute(:#{validation_method}, CallbackChain.new) - return #{validation_method}_callback_chain - end - end - end_eval - end + base.define_callbacks :validate, :validate_on_create, :validate_on_update end module ClassMethods diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index 573c6a4f02..1d63bb2f84 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -364,8 +364,10 @@ module ActiveRecord end def current_version - Base.connection.select_values( - "SELECT version FROM #{schema_migrations_table_name}").map(&:to_i).max || 0 + version = Base.connection.select_values( + "SELECT version FROM #{schema_migrations_table_name}" + ).map(&:to_i).max rescue nil + version || 0 end def proper_table_name(name) diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb index 86cda9aa66..1d12ea8ad7 100755 --- a/activerecord/lib/active_record/validations.rb +++ b/activerecord/lib/active_record/validations.rb @@ -281,24 +281,7 @@ module ActiveRecord end base.send :include, ActiveSupport::Callbacks - - VALIDATIONS.each do |validation_method| - base.class_eval <<-"end_eval" - def self.#{validation_method}(*methods, &block) - methods = CallbackChain.build(:#{validation_method}, *methods, &block) - self.#{validation_method}_callback_chain.replace(#{validation_method}_callback_chain | methods) - end - - def self.#{validation_method}_callback_chain - if chain = read_inheritable_attribute(:#{validation_method}) - return chain - else - write_inheritable_attribute(:#{validation_method}, CallbackChain.new) - return #{validation_method}_callback_chain - end - end - end_eval - end + base.define_callbacks *VALIDATIONS end # All of the following validations are defined in the class scope of the model that you're interested in validating. @@ -404,7 +387,7 @@ module ActiveRecord # method, proc or string should return or evaluate to a true or false value. # * <tt>unless</tt> - Specifies a method, proc or string to call to determine if the validation should # not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). The - # method, proc or string should return or evaluate to a true or false value. + # method, proc or string should return or evaluate to a true or false value. def validates_confirmation_of(*attr_names) configuration = { :message => ActiveRecord::Errors.default_error_messages[:confirmation], :on => :save } configuration.update(attr_names.extract_options!) @@ -438,7 +421,7 @@ module ActiveRecord # method, proc or string should return or evaluate to a true or false value. # * <tt>unless</tt> - Specifies a method, proc or string to call to determine if the validation should # not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). The - # method, proc or string should return or evaluate to a true or false value. + # method, proc or string should return or evaluate to a true or false value. def validates_acceptance_of(*attr_names) configuration = { :message => ActiveRecord::Errors.default_error_messages[:accepted], :on => :save, :allow_nil => true, :accept => "1" } configuration.update(attr_names.extract_options!) @@ -520,7 +503,7 @@ module ActiveRecord # method, proc or string should return or evaluate to a true or false value. # * <tt>unless</tt> - Specifies a method, proc or string to call to determine if the validation should # not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). The - # method, proc or string should return or evaluate to a true or false value. + # method, proc or string should return or evaluate to a true or false value. def validates_length_of(*attrs) # Merge given options with defaults. options = { @@ -597,7 +580,7 @@ module ActiveRecord # attribute (that maps to a column). When the record is updated, the same check is made but disregarding the record itself. # # Because this check is performed outside the database there is still a chance that duplicate values - # will be inserted in two parallel transactions. To guarantee against this you should create a + # will be inserted in two parallel transactions. To guarantee against this you should create a # unique index on the field. See +add_index+ for more information. # # Configuration options: diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index 885d89b6da..c270230d67 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -813,6 +813,13 @@ if ActiveRecord::Base.connection.supports_migrations? end end + def test_migrator_db_has_no_schema_migrations_table + ActiveRecord::Base.connection.execute("DROP TABLE schema_migrations;") + assert_nothing_raised do + ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 1) + end + end + def test_migrator_verbosity ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1) assert PeopleHaveLastNames.message_count > 0 @@ -1010,7 +1017,7 @@ if ActiveRecord::Base.connection.supports_migrations? end end - + uses_mocha 'Sexy migration tests' do class SexyMigrationsTest < ActiveRecord::TestCase def test_references_column_type_adds_id diff --git a/activerecord/test/cases/validations_test.rb b/activerecord/test/cases/validations_test.rb index 97ac22eaf3..ca36ad3581 100755 --- a/activerecord/test/cases/validations_test.rb +++ b/activerecord/test/cases/validations_test.rb @@ -58,9 +58,9 @@ class ValidationsTest < ActiveRecord::TestCase fixtures :topics, :developers, 'warehouse-things' def setup - Topic.write_inheritable_attribute(:validate, nil) - Topic.write_inheritable_attribute(:validate_on_create, nil) - Topic.write_inheritable_attribute(:validate_on_update, nil) + Topic.instance_variable_set("@validate_callbacks", ActiveSupport::Callbacks::CallbackChain.new) + Topic.instance_variable_set("@validate_on_create_callbacks", ActiveSupport::Callbacks::CallbackChain.new) + Topic.instance_variable_set("@validate_on_update_callbacks", ActiveSupport::Callbacks::CallbackChain.new) end def test_single_field_validation @@ -839,16 +839,16 @@ class ValidationsTest < ActiveRecord::TestCase reply = t.replies.build('title' => 'areply', 'content' => 'whateveragain') assert t.valid? end - + def test_validates_size_of_association_using_within assert_nothing_raised { Topic.validates_size_of :replies, :within => 1..2 } t = Topic.new('title' => 'noreplies', 'content' => 'whatever') assert !t.save assert t.errors.on(:replies) - + reply = t.replies.build('title' => 'areply', 'content' => 'whateveragain') assert t.valid? - + 2.times { t.replies.build('title' => 'areply', 'content' => 'whateveragain') } assert !t.save assert t.errors.on(:replies) @@ -1351,9 +1351,9 @@ class ValidatesNumericalityTest < ActiveRecord::TestCase JUNK = ["not a number", "42 not a number", "0xdeadbeef", "00-1", "--3", "+-3", "+3-1", "-+019.0", "12.12.13.12", "123\nnot a number"] def setup - Topic.write_inheritable_attribute(:validate, nil) - Topic.write_inheritable_attribute(:validate_on_create, nil) - Topic.write_inheritable_attribute(:validate_on_update, nil) + Topic.instance_variable_set("@validate_callbacks", ActiveSupport::Callbacks::CallbackChain.new) + Topic.instance_variable_set("@validate_on_create_callbacks", ActiveSupport::Callbacks::CallbackChain.new) + Topic.instance_variable_set("@validate_on_update_callbacks", ActiveSupport::Callbacks::CallbackChain.new) end def test_default_validates_numericality_of diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 0627c89c53..cfdefed91e 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,5 +1,11 @@ *SVN* +* Time#since behaves correctly when passed a Duration. Closes #11527 [kemiller] + +* Add #getutc alias for DateTime#utc [Geoff Buesing] + +* Refactor TimeWithZone: don't send #since, #ago, #+, #-, #advance through method_missing [Geoff Buesing] + * TimeWithZone respects config.active_support.use_standard_json_time_format [Geoff Buesing] * Add config.active_support.escape_html_entities_in_json to allow disabling of html entity escaping. [rick] diff --git a/activesupport/lib/active_support/cache/mem_cache_store.rb b/activesupport/lib/active_support/cache/mem_cache_store.rb index 88e324aa3a..9b787702b2 100644 --- a/activesupport/lib/active_support/cache/mem_cache_store.rb +++ b/activesupport/lib/active_support/cache/mem_cache_store.rb @@ -15,9 +15,10 @@ module ActiveSupport def initialize(*addresses) addresses = addresses.flatten + options = addresses.extract_options! addresses = ["localhost"] if addresses.empty? @addresses = addresses - @data = MemCache.new(addresses) + @data = MemCache.new(addresses, options) end def read(key, options = nil) diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb index 329cc2fdc7..9c59b7ac76 100644 --- a/activesupport/lib/active_support/callbacks.rb +++ b/activesupport/lib/active_support/callbacks.rb @@ -96,17 +96,25 @@ module ActiveSupport end end - def find_callback(callback, &block) + def |(chain) + if chain.is_a?(CallbackChain) + chain.each { |callback| self | callback } + else + if (found_callback = find(chain)) && (index = index(chain)) + self[index] = chain + else + self << chain + end + end + self + end + + def find(callback, &block) select { |c| c == callback && (!block_given? || yield(c)) }.first end - def replace_or_append_callback(callback) - if found_callback = find_callback(callback) - index = index(found_callback) - self[index] = callback - else - self << callback - end + def delete(callback) + super(callback.is_a?(Callback) ? callback : find(callback)) end private @@ -216,8 +224,8 @@ module ActiveSupport end end - # Runs all the callbacks defined for the given options. - # + # Runs all the callbacks defined for the given options. + # # If a block is given it will be called after each callback receiving as arguments: # # * the result from the callback @@ -228,31 +236,31 @@ module ActiveSupport # Example: # class Storage # include ActiveSupport::Callbacks - # + # # define_callbacks :before_save, :after_save # end - # + # # class ConfigStorage < Storage # before_save :pass # before_save :pass # before_save :stop # before_save :pass - # + # # def pass # puts "pass" # end - # + # # def stop # puts "stop" # return false # end - # + # # def save # result = run_callbacks(:before_save) { |result, object| result == false } # puts "- save" if result # end # end - # + # # config = ConfigStorage.new # config.save # diff --git a/activesupport/lib/active_support/core_ext/date_time/calculations.rb b/activesupport/lib/active_support/core_ext/date_time/calculations.rb index 5c351c21c6..fa444f71b1 100644 --- a/activesupport/lib/active_support/core_ext/date_time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date_time/calculations.rb @@ -86,6 +86,7 @@ module ActiveSupport #:nodoc: def utc new_offset(0) end + alias_method :getutc, :utc # Returns true if offset == 0 def utc? diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb index 0bc83af709..ffbdf37789 100644 --- a/activesupport/lib/active_support/core_ext/time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/time/calculations.rb @@ -88,18 +88,21 @@ module ActiveSupport #:nodoc: end # Returns a new Time representing the time a number of seconds ago, this is basically a wrapper around the Numeric extension - # Do not use this method in combination with x.months, use months_ago instead! def ago(seconds) self.since(-seconds) end # Returns a new Time representing the time a number of seconds since the instance time, this is basically a wrapper around - # the Numeric extension. Do not use this method in combination with x.months, use months_since instead! + # the Numeric extension. def since(seconds) - initial_dst = self.dst? ? 1 : 0 f = seconds.since(self) - final_dst = f.dst? ? 1 : 0 - (seconds.abs >= 86400 && initial_dst != final_dst) ? f + (initial_dst - final_dst).hours : f + if ActiveSupport::Duration === seconds + f + else + initial_dst = self.dst? ? 1 : 0 + final_dst = f.dst? ? 1 : 0 + (seconds.abs >= 86400 && initial_dst != final_dst) ? f + (initial_dst - final_dst).hours : f + end rescue self.to_datetime.since(seconds) end diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index 1c984f07d4..f1a2498298 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -134,7 +134,8 @@ module ActiveSupport # If wrapped #time is a DateTime, use DateTime#since instead of #+ # Otherwise, just pass on to #method_missing def +(other) - time.acts_like?(:date) ? method_missing(:since, other) : method_missing(:+, other) + result = utc.acts_like?(:date) ? utc.since(other) : utc + other + result.in_time_zone(time_zone) end # If a time-like object is passed in, compare it with #utc @@ -144,10 +145,23 @@ module ActiveSupport if other.acts_like?(:time) utc - other else - time.acts_like?(:date) ? method_missing(:ago, other) : method_missing(:-, other) + result = utc.acts_like?(:date) ? utc.ago(other) : utc - other + result.in_time_zone(time_zone) end end + def since(other) + utc.since(other).in_time_zone(time_zone) + end + + def ago(other) + utc.ago(other).in_time_zone(time_zone) + end + + def advance(options) + utc.advance(options).in_time_zone(time_zone) + end + def usec time.respond_to?(:usec) ? time.usec : 0 end @@ -208,13 +222,8 @@ module ActiveSupport # Send the missing method to time instance, and wrap result in a new TimeWithZone with the existing time_zone def method_missing(sym, *args, &block) - if %w(+ - since ago advance).include?(sym.to_s) - result = utc.__send__(sym, *args, &block) - result.acts_like?(:time) ? result.in_time_zone(time_zone) : result - else - result = time.__send__(sym, *args, &block) - result.acts_like?(:time) ? self.class.new(nil, time_zone, result) : result - end + result = time.__send__(sym, *args, &block) + result.acts_like?(:time) ? self.class.new(nil, time_zone, result) : result end private diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb index a038f29f53..09b56525e0 100644 --- a/activesupport/test/caching_test.rb +++ b/activesupport/test/caching_test.rb @@ -18,6 +18,19 @@ class CacheStoreSettingTest < Test::Unit::TestCase assert_kind_of(ActiveSupport::Cache::MemCacheStore, store) assert_equal %w(localhost), store.addresses end + + def test_mem_cache_fragment_cache_store_with_multiple_servers + store = ActiveSupport::Cache.lookup_store :mem_cache_store, "localhost", '192.168.1.1' + assert_kind_of(ActiveSupport::Cache::MemCacheStore, store) + assert_equal %w(localhost 192.168.1.1), store.addresses + end + + def test_mem_cache_fragment_cache_store_with_options + store = ActiveSupport::Cache.lookup_store :mem_cache_store, "localhost", '192.168.1.1', :namespace => 'foo' + assert_kind_of(ActiveSupport::Cache::MemCacheStore, store) + assert_equal %w(localhost 192.168.1.1), store.addresses + assert_equal 'foo', store.instance_variable_get('@data').instance_variable_get('@namespace') + end def test_object_assigned_fragment_cache_store store = ActiveSupport::Cache.lookup_store ActiveSupport::Cache::FileStore.new("/path/to/cache/directory") diff --git a/activesupport/test/callbacks_test.rb b/activesupport/test/callbacks_test.rb index 3f8cb7f01a..7f71ca2262 100644 --- a/activesupport/test/callbacks_test.rb +++ b/activesupport/test/callbacks_test.rb @@ -96,6 +96,8 @@ class ConditionalCallbackTest < Test::Unit::TestCase end class CallbackTest < Test::Unit::TestCase + include ActiveSupport::Callbacks + def test_eql callback = Callback.new(:before, :save, :identifier => :lifesaver) assert callback.eql?(Callback.new(:before, :save, :identifier => :lifesaver)) @@ -115,3 +117,32 @@ class CallbackTest < Test::Unit::TestCase assert_equal({}, a.options) end end + +class CallbackChainTest < Test::Unit::TestCase + include ActiveSupport::Callbacks + + def setup + @chain = CallbackChain.build(:make, :bacon, :lettuce, :tomato) + end + + def test_build + assert_equal 3, @chain.size + assert_equal [:bacon, :lettuce, :tomato], @chain.map(&:method) + end + + def test_find + assert_equal :bacon, @chain.find(:bacon).method + end + + def test_union + assert_equal [:bacon, :lettuce, :tomato], (@chain | Callback.new(:make, :bacon)).map(&:method) + assert_equal [:bacon, :lettuce, :tomato, :turkey], (@chain | CallbackChain.build(:make, :bacon, :lettuce, :tomato, :turkey)).map(&:method) + assert_equal [:bacon, :lettuce, :tomato, :turkey, :mayo], (@chain | Callback.new(:make, :mayo)).map(&:method) + end + + def test_delete + assert_equal [:bacon, :lettuce, :tomato], @chain.map(&:method) + @chain.delete(:bacon) + assert_equal [:lettuce, :tomato], @chain.map(&:method) + end +end diff --git a/activesupport/test/core_ext/date_time_ext_test.rb b/activesupport/test/core_ext/date_time_ext_test.rb index 25a8e878f9..ed45daf403 100644 --- a/activesupport/test/core_ext/date_time_ext_test.rb +++ b/activesupport/test/core_ext/date_time_ext_test.rb @@ -240,6 +240,7 @@ class DateTimeExtCalculationsTest < Test::Unit::TestCase assert_equal DateTime.civil(2005, 2, 21, 15, 11, 12, 0), DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-5, 24)).utc assert_equal DateTime.civil(2005, 2, 21, 10, 11, 12, 0), DateTime.civil(2005, 2, 21, 10, 11, 12, 0).utc assert_equal DateTime.civil(2005, 2, 21, 9, 11, 12, 0), DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(1, 24)).utc + assert_equal DateTime.civil(2005, 2, 21, 9, 11, 12, 0), DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(1, 24)).getutc end def test_formatted_offset_with_utc diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb index d1d92964c3..e53b7193ea 100644 --- a/activesupport/test/core_ext/time_ext_test.rb +++ b/activesupport/test/core_ext/time_ext_test.rb @@ -205,6 +205,31 @@ class TimeExtCalculationsTest < Test::Unit::TestCase end end + def test_daylight_savings_time_crossings_backward_start_1day + with_env_tz 'US/Eastern' do + # dt: US: 2005 April 3rd 4:18am + assert_equal Time.local(2005,4,2,4,18,0), Time.local(2005,4,3,4,18,0).ago(1.day), 'dt-1.day=>st' + assert_equal Time.local(2005,4,1,4,18,0), Time.local(2005,4,2,4,18,0).ago(1.day), 'st-1.day=>st' + end + with_env_tz 'NZ' do + # dt: New Zealand: 2006 October 1st 4:18am + assert_equal Time.local(2006,9,30,4,18,0), Time.local(2006,10,1,4,18,0).ago(1.day), 'dt-1.day=>st' + assert_equal Time.local(2006,9,29,4,18,0), Time.local(2006,9,30,4,18,0).ago(1.day), 'st-1.day=>st' + end + end + + def test_daylight_savings_time_crossings_backward_end_1day + with_env_tz 'US/Eastern' do + # st: US: 2005 October 30th 4:03am + assert_equal Time.local(2005,10,29,4,3), Time.local(2005,10,30,4,3,0).ago(1.day), 'st-1.day=>dt' + assert_equal Time.local(2005,10,28,4,3), Time.local(2005,10,29,4,3,0).ago(1.day), 'dt-1.day=>dt' + end + with_env_tz 'NZ' do + # st: New Zealand: 2006 March 19th 4:03am + assert_equal Time.local(2006,3,18,4,3), Time.local(2006,3,19,4,3,0).ago(1.day), 'st-1.day=>dt' + assert_equal Time.local(2006,3,17,4,3), Time.local(2006,3,18,4,3,0).ago(1.day), 'dt-1.day=>dt' + end + end def test_since assert_equal Time.local(2005,2,22,10,10,11), Time.local(2005,2,22,10,10,10).since(1) assert_equal Time.local(2005,2,22,11,10,10), Time.local(2005,2,22,10,10,10).since(3600) @@ -227,6 +252,19 @@ class TimeExtCalculationsTest < Test::Unit::TestCase end end + def test_daylight_savings_time_crossings_forward_start_1day + with_env_tz 'US/Eastern' do + # st: US: 2005 April 2nd 7:27pm + assert_equal Time.local(2005,4,3,19,27,0), Time.local(2005,4,2,19,27,0).since(1.day), 'st+1.day=>dt' + assert_equal Time.local(2005,4,4,19,27,0), Time.local(2005,4,3,19,27,0).since(1.day), 'dt+1.day=>dt' + end + with_env_tz 'NZ' do + # st: New Zealand: 2006 September 30th 7:27pm + assert_equal Time.local(2006,10,1,19,27,0), Time.local(2006,9,30,19,27,0).since(1.day), 'st+1.day=>dt' + assert_equal Time.local(2006,10,2,19,27,0), Time.local(2006,10,1,19,27,0).since(1.day), 'dt+1.day=>dt' + end + end + def test_daylight_savings_time_crossings_forward_start_tomorrow with_env_tz 'US/Eastern' do # st: US: 2005 April 2nd 7:27pm @@ -240,7 +278,7 @@ class TimeExtCalculationsTest < Test::Unit::TestCase end end - def test_daylight_savings_time_crossings_forward_start_yesterday + def test_daylight_savings_time_crossings_backward_start_yesterday with_env_tz 'US/Eastern' do # st: US: 2005 April 2nd 7:27pm assert_equal Time.local(2005,4,2,19,27,0), Time.local(2005,4,3,19,27,0).yesterday, 'dt-1.day=>st' @@ -266,6 +304,19 @@ class TimeExtCalculationsTest < Test::Unit::TestCase end end + def test_daylight_savings_time_crossings_forward_end_1day + with_env_tz 'US/Eastern' do + # dt: US: 2005 October 30th 12:45am + assert_equal Time.local(2005,10,31,0,45,0), Time.local(2005,10,30,0,45,0).since(1.day), 'dt+1.day=>st' + assert_equal Time.local(2005,11, 1,0,45,0), Time.local(2005,10,31,0,45,0).since(1.day), 'st+1.day=>st' + end + with_env_tz 'NZ' do + # dt: New Zealand: 2006 March 19th 1:45am + assert_equal Time.local(2006,3,20,1,45,0), Time.local(2006,3,19,1,45,0).since(1.day), 'dt+1.day=>st' + assert_equal Time.local(2006,3,21,1,45,0), Time.local(2006,3,20,1,45,0).since(1.day), 'st+1.day=>st' + end + end + def test_daylight_savings_time_crossings_forward_end_tomorrow with_env_tz 'US/Eastern' do # dt: US: 2005 October 30th 12:45am @@ -279,7 +330,7 @@ class TimeExtCalculationsTest < Test::Unit::TestCase end end - def test_daylight_savings_time_crossings_forward_end_yesterday + def test_daylight_savings_time_crossings_backward_end_yesterday with_env_tz 'US/Eastern' do # dt: US: 2005 October 30th 12:45am assert_equal Time.local(2005,10,30,0,45,0), Time.local(2005,10,31,0,45,0).yesterday, 'st-1.day=>dt' diff --git a/cleanlogs.sh b/cleanlogs.sh index a197441085..a4e6baf0df 100755 --- a/cleanlogs.sh +++ b/cleanlogs.sh @@ -1 +1 @@ -rm activerecord/debug.log activerecord/test/debug.log actionpack/debug.log +rm activerecord/debug.log activerecord/test/debug.log actionpack/debug.log activeresource/test/debug.log diff --git a/pushgems.rb b/pushgems.rb index f90927a80c..6a1f1ffe8f 100755 --- a/pushgems.rb +++ b/pushgems.rb @@ -11,5 +11,4 @@ end else `cd #{pkg} && rm -rf pkg && rake pgem && cd ..` end -end - +end
\ No newline at end of file diff --git a/railties/CHANGELOG b/railties/CHANGELOG index 86b30244ba..a21bfc72dd 100644 --- a/railties/CHANGELOG +++ b/railties/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* Added Rails.public_path to control where HTML and assets are expected to be loaded from (defaults to Rails.root + "/public") #11581 [nicksieger] + * rake time:zones:local finds correct base utc offset for zones in the Southern Hemisphere [Geoff Buesing] * Don't require rails/gem_builder during rails initialization, it's only needed for the gems:build task. [rick] diff --git a/railties/lib/console_app.rb b/railties/lib/console_app.rb index c7673642ec..88e7962b43 100644 --- a/railties/lib/console_app.rb +++ b/railties/lib/console_app.rb @@ -24,7 +24,7 @@ end def reload! puts "Reloading..." dispatcher = ActionController::Dispatcher.new($stdout) - dispatcher.cleanup_application(true) - dispatcher.prepare_application(true) + dispatcher.cleanup_application + dispatcher.reload_application true end diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index 8a5ca6f91b..b5bf9266f5 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -38,6 +38,14 @@ module Rails def cache RAILS_CACHE end + + def public_path + @@public_path ||= File.join(self.root, "public") + end + + def public_path=(path) + @@public_path = path + end end # The Initializer is responsible for processing the Rails configuration, such @@ -127,6 +135,9 @@ module Rails load_application_initializers + # Prepare dispatcher callbacks and run 'prepare' callbacks + prepare_dispatcher + # the framework is now fully initialized after_initialize @@ -434,6 +445,12 @@ module Rails end end + def prepare_dispatcher + require 'dispatcher' unless defined?(::Dispatcher) + Dispatcher.define_dispatcher_callbacks(configuration.cache_classes) + Dispatcher.new(RAILS_DEFAULT_LOGGER).send :run_callbacks, :prepare_dispatch + end + end # The Configuration class holds all the parameters for the Initializer and diff --git a/railties/lib/rails_generator/generators/components/mailer/mailer_generator.rb b/railties/lib/rails_generator/generators/components/mailer/mailer_generator.rb index 3ff4f03972..dc1202d7c8 100644 --- a/railties/lib/rails_generator/generators/components/mailer/mailer_generator.rb +++ b/railties/lib/rails_generator/generators/components/mailer/mailer_generator.rb @@ -11,12 +11,8 @@ class MailerGenerator < Rails::Generator::NamedBase m.directory File.join('test/fixtures', file_path) # Mailer class and unit test. - m.template "mailer.rb", File.join('app/models', - class_path, - "#{file_name}.rb") - m.template "unit_test.rb", File.join('test/unit', - class_path, - "#{file_name}_test.rb") + m.template "mailer.rb", File.join('app/models', class_path, "#{file_name}.rb") + m.template "unit_test.rb", File.join('test/unit', class_path, "#{file_name}_test.rb") # View template and fixture for each action. actions.each do |action| diff --git a/railties/lib/rails_generator/generators/components/mailer/templates/mailer.rb b/railties/lib/rails_generator/generators/components/mailer/templates/mailer.rb index 127495fcbb..0c7e6bebaf 100644 --- a/railties/lib/rails_generator/generators/components/mailer/templates/mailer.rb +++ b/railties/lib/rails_generator/generators/components/mailer/templates/mailer.rb @@ -1,13 +1,17 @@ class <%= class_name %> < ActionMailer::Base + + # change to your domain name + default_url_options[:host] = 'example.com' <% for action in actions -%> def <%= action %>(sent_at = Time.now) - @subject = '<%= class_name %>#<%= action %>' - @body = {} - @recipients = '' - @from = '' - @sent_on = sent_at - @headers = {} + subject '<%= class_name %>#<%= action %>' + recipients '' + from '' + sent_on sent_at + + body :greeting => 'Hi,' end <% end -%> + end diff --git a/railties/test/console_app_test.rb b/railties/test/console_app_test.rb index 7615d95498..6cfc907b80 100644 --- a/railties/test/console_app_test.rb +++ b/railties/test/console_app_test.rb @@ -13,17 +13,20 @@ require 'console_app' Test::Unit.run = false class ConsoleAppTest < Test::Unit::TestCase - def test_reload_should_fire_preparation_callbacks - a = b = c = nil + uses_mocha 'console reload test' do + def test_reload_should_fire_preparation_callbacks + a = b = c = nil - Dispatcher.to_prepare { a = b = c = 1 } - Dispatcher.to_prepare { b = c = 2 } - Dispatcher.to_prepare { c = 3 } + Dispatcher.to_prepare { a = b = c = 1 } + Dispatcher.to_prepare { b = c = 2 } + Dispatcher.to_prepare { c = 3 } + ActionController::Routing::Routes.expects(:reload) - reload! + reload! - assert_equal 1, a - assert_equal 2, b - assert_equal 3, c + assert_equal 1, a + assert_equal 2, b + assert_equal 3, c + end end end diff --git a/railties/test/generators/generator_test_helper.rb b/railties/test/generators/generator_test_helper.rb index 4007cf16ca..190bc91d52 100644 --- a/railties/test/generators/generator_test_helper.rb +++ b/railties/test/generators/generator_test_helper.rb @@ -1,3 +1,51 @@ +require 'test/unit' +require 'fileutils' + +# Mock out what we need from AR::Base +module ActiveRecord + class Base + class << self + attr_accessor :pluralize_table_names + end + self.pluralize_table_names = true + end + + module ConnectionAdapters + class Column + attr_reader :name, :default, :type, :limit, :null, :sql_type, :precision, :scale + + def initialize(name, default, sql_type = nil) + @name = name + @default = default + @type = @sql_type = sql_type + end + + def human_name + @name.humanize + end + end + end +end + +# Mock up necessities from ActionView +module ActionView + module Helpers + module ActionRecordHelper; end + class InstanceTag; end + end +end + +# Set RAILS_ROOT appropriately fixture generation +tmp_dir = "#{File.dirname(__FILE__)}/../fixtures/tmp" + +if defined? RAILS_ROOT + RAILS_ROOT.replace tmp_dir +else + RAILS_ROOT = tmp_dir +end +FileUtils.mkdir_p RAILS_ROOT + +$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../lib" require 'initializer' # Mocks out the configuration @@ -9,35 +57,62 @@ end require 'rails_generator' +class GeneratorTestCase < Test::Unit::TestCase + include FileUtils + + def setup + ActiveRecord::Base.pluralize_table_names = true + + mkdir_p "#{RAILS_ROOT}/app/views/layouts" + mkdir_p "#{RAILS_ROOT}/config" + mkdir_p "#{RAILS_ROOT}/db" + mkdir_p "#{RAILS_ROOT}/test/fixtures" + mkdir_p "#{RAILS_ROOT}/public/stylesheets" + + File.open("#{RAILS_ROOT}/config/routes.rb", 'w') do |f| + f << "ActionController::Routing::Routes.draw do |map|\n\nend" + end + end -module GeneratorTestHelper + def teardown + rm_rf "#{RAILS_ROOT}/app" + rm_rf "#{RAILS_ROOT}/test" + rm_rf "#{RAILS_ROOT}/config" + rm_rf "#{RAILS_ROOT}/db" + rm_rf "#{RAILS_ROOT}/public" + end + + def test_truth + # don't complain, test/unit + end + # Instantiates the Generator - def build_generator(name,params) - Rails::Generator::Base.instance(name,params) + def build_generator(name, params) + Rails::Generator::Base.instance(name, params) end # Runs the create command (like the command line does) - def run_generator(name,params) + def run_generator(name, params) silence_generator do - build_generator(name,params).command(:create).invoke! + build_generator(name, params).command(:create).invoke! end end # Silences the logger temporarily and returns the output as a String def silence_generator - logger_original=Rails::Generator::Base.logger - myout=StringIO.new - Rails::Generator::Base.logger=Rails::Generator::SimpleLogger.new(myout) + logger_original = Rails::Generator::Base.logger + myout = StringIO.new + Rails::Generator::Base.logger = Rails::Generator::SimpleLogger.new(myout) yield if block_given? - Rails::Generator::Base.logger=logger_original + Rails::Generator::Base.logger = logger_original myout.string end # asserts that the given controller was generated. # It takes a name or symbol without the <tt>_controller</tt> part and an optional super class. # The contents of the class source file is passed to a block. - def assert_generated_controller_for(name,parent="ApplicationController") - assert_generated_class "app/controllers/#{name.to_s.underscore}_controller",parent do |body| + def assert_generated_controller_for(name, parent = "ApplicationController") + assert_generated_class "app/controllers/#{name.to_s.underscore}_controller", parent do |body| yield body if block_given? end end @@ -45,8 +120,8 @@ module GeneratorTestHelper # asserts that the given model was generated. # It takes a name or symbol and an optional super class. # the contents of the class source file is passed to a block. - def assert_generated_model_for(name,parent="ActiveRecord::Base") - assert_generated_class "app/models/#{name.to_s.underscore}",parent do |body| + def assert_generated_model_for(name, parent = "ActiveRecord::Base") + assert_generated_class "app/models/#{name.to_s.underscore}", parent do |body| yield body if block_given? end end @@ -63,7 +138,7 @@ module GeneratorTestHelper # asserts that the given functional test was generated. # It takes a name or symbol without the <tt>_controller_test</tt> part and an optional super class. # the contents of the class source file is passed to a block. - def assert_generated_functional_test_for(name,parent="ActionController::TestCase") + def assert_generated_functional_test_for(name, parent = "ActionController::TestCase") assert_generated_class "test/functional/#{name.to_s.underscore}_controller_test",parent do |body| yield body if block_given? end @@ -72,8 +147,8 @@ module GeneratorTestHelper # asserts that the given unit test was generated. # It takes a name or symbol without the <tt>_test</tt> part and an optional super class. # the contents of the class source file is passed to a block. - def assert_generated_unit_test_for(name,parent="ActiveSupport::TestCase") - assert_generated_class "test/unit/#{name.to_s.underscore}_test",parent do |body| + def assert_generated_unit_test_for(name, parent = "ActiveSupport::TestCase") + assert_generated_class "test/unit/#{name.to_s.underscore}_test", parent do |body| yield body if block_given? end end @@ -89,17 +164,18 @@ module GeneratorTestHelper # asserts that the given file exists def assert_file_exists(path) - assert File.exist?("#{RAILS_ROOT}/#{path}"),"The file '#{RAILS_ROOT}/#{path}' should exist" + assert File.exist?("#{RAILS_ROOT}/#{path}"), + "The file '#{RAILS_ROOT}/#{path}' should exist" end # asserts that the given class source file was generated. # It takes a path without the <tt>.rb</tt> part and an optional super class. # the contents of the class source file is passed to a block. - def assert_generated_class(path,parent=nil) - path=~/\/?(\d+_)?(\w+)$/ - class_name=$2.camelize + def assert_generated_class(path, parent=nil) + path =~ /\/?(\d+_)?(\w+)$/ + class_name = $2.camelize assert_generated_file("#{path}.rb") do |body| - assert body=~/class #{class_name}#{parent.nil? ? '':" < #{parent}"}/,"the file '#{path}.rb' should be a class" + assert_match /class #{class_name}#{parent.nil? ? '':" < #{parent}"}/, body, "the file '#{path}.rb' should be a class" yield body if block_given? end end @@ -108,10 +184,10 @@ module GeneratorTestHelper # It takes a path without the <tt>.rb</tt> part. # the contents of the class source file is passed to a block. def assert_generated_module(path) - path=~/\/?(\w+)$/ - module_name=$1.camelize + path =~ /\/?(\w+)$/ + module_name = $1.camelize assert_generated_file("#{path}.rb") do |body| - assert body=~/module #{module_name}/,"the file '#{path}.rb' should be a module" + assert_match /module #{module_name}/, body, "the file '#{path}.rb' should be a module" yield body if block_given? end end @@ -130,7 +206,8 @@ module GeneratorTestHelper # the parsed yaml tree is passed to a block. def assert_generated_yaml(path) assert_generated_file("#{path}.yml") do |body| - assert yaml=YAML.load(body) + yaml = YAML.load(body) + assert yaml, 'YAML data missing' yield yaml if block_given? end end @@ -147,23 +224,22 @@ module GeneratorTestHelper # asserts that the given views were generated. # It takes a controller name and a list of views (including extensions). # The body of each view is passed to a block - def assert_generated_views_for(name,*actions) + def assert_generated_views_for(name, *actions) actions.each do |action| - assert_generated_file("app/views/#{name.to_s.underscore}/#{action.to_s}") do |body| + assert_generated_file("app/views/#{name.to_s.underscore}/#{action}") do |body| yield body if block_given? end end end - def assert_generated_migration(name,parent="ActiveRecord::Migration") - file = - Dir.glob("#{RAILS_ROOT}/db/migrate/*_#{name.to_s.underscore}.rb").first - file = file.match(/db\/migrate\/[0-9]+_#{name.to_s.underscore}/).to_s - assert_generated_class file,parent do |body| - assert body=~/timestamps/, "should have timestamps defined" - yield body if block_given? - end + def assert_generated_migration(name, parent = "ActiveRecord::Migration") + file = Dir.glob("#{RAILS_ROOT}/db/migrate/*_#{name.to_s.underscore}.rb").first + file = file.match(/db\/migrate\/[0-9]+_\w+/).to_s + assert_generated_class file, parent do |body| + assert_match /timestamps/, body, "should have timestamps defined" + yield body if block_given? end + end # Asserts that the given migration file was not generated. # It takes the name of the migration as a parameter. @@ -175,22 +251,23 @@ module GeneratorTestHelper # asserts that the given resource was added to the routes. def assert_added_route_for(name) assert_generated_file("config/routes.rb") do |body| - assert body=~/map.resources :#{name.to_s.underscore}/,"should add route for :#{name.to_s.underscore}" + assert_match /map.resources :#{name.to_s.underscore}/, body, + "should add route for :#{name.to_s.underscore}" end end # asserts that the given methods are defined in the body. # This does assume standard rails code conventions with regards to the source code. # The body of each individual method is passed to a block. - def assert_has_method(body,*methods) + def assert_has_method(body, *methods) methods.each do |name| - assert body=~/^ def #{name.to_s}\n((\n| .*\n)*) end/,"should have method #{name.to_s}" - yield( name, $1 ) if block_given? + assert body =~ /^ def #{name}(\(.+\))?\n((\n| .*\n)*) end/, "should have method #{name}" + yield(name, $2) if block_given? end end # asserts that the given column is defined in the migration - def assert_generated_column(body,name,type) - assert body=~/t\.#{type.to_s} :#{name.to_s}/, "should have column #{name.to_s} defined" + def assert_generated_column(body, name, type) + assert_match /t\.#{type.to_s} :#{name.to_s}/, body, "should have column #{name.to_s} defined" end end diff --git a/railties/test/generators/rails_mailer_generator_test.rb b/railties/test/generators/rails_mailer_generator_test.rb new file mode 100644 index 0000000000..03170c3b61 --- /dev/null +++ b/railties/test/generators/rails_mailer_generator_test.rb @@ -0,0 +1,29 @@ +require 'generators/generator_test_helper' + +class RailsMailerGeneratorTest < GeneratorTestCase + + def test_generates_mailer + run_generator('mailer', %w(Notifier reset_password)) + + assert_generated_model_for :notifier, 'ActionMailer::Base' do |model| + assert_has_method model, :reset_password do |name, body| + assert_equal [ + "subject 'Notifier#reset_password'", + "recipients ''", + "from ''", + "sent_on sent_at", + "", + "body :greeting => 'Hi,'" + ], + body.split("\n").map{|line| line.sub(' '*4, '') } + end + + assert_match /^ default_url_options\[:host\] = 'example.com'$/m, model, + 'model should include default_url_options :host declaration' + end + + assert_generated_views_for :notifier, 'reset_password.erb' + assert_generated_unit_test_for :notifier, 'ActionMailer::TestCase' + assert_generated_file "test/fixtures/notifier/reset_password" + end +end diff --git a/railties/test/generators/rails_model_generator_test.rb b/railties/test/generators/rails_model_generator_test.rb index 86ad9c4dc8..0bfc338566 100644 --- a/railties/test/generators/rails_model_generator_test.rb +++ b/railties/test/generators/rails_model_generator_test.rb @@ -1,84 +1,6 @@ -require 'test/unit' - -# Optionally load RubyGems -begin - require 'rubygems' -rescue LoadError -end - -# Mock out what we need from AR::Base -module ActiveRecord - class Base - class << self - attr_accessor :pluralize_table_names - end - self.pluralize_table_names = true - end - - module ConnectionAdapters - class Column - attr_reader :name, :default, :type, :limit, :null, :sql_type, :precision, :scale - def initialize(name, default, sql_type=nil) - @namename - @default=default - @type=@sql_type=sql_type - end - - def human_name - @name.humanize - end - end - end -end - -# Mock up necessities from ActionView -module ActionView - module Helpers - module ActionRecordHelper; end - class InstanceTag; end - end -end - -# Set RAILS_ROOT appropriately fixture generation -tmp_dir="#{File.dirname(__FILE__)}/../fixtures/tmp" -if defined?(RAILS_ROOT) - RAILS_ROOT.replace(tmp_dir) -else - RAILS_ROOT=tmp_dir -end -Dir.mkdir(RAILS_ROOT) unless File.exist?(RAILS_ROOT) - - -$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../lib" - require 'generators/generator_test_helper' -class RailsModelGeneratorTest < Test::Unit::TestCase - include GeneratorTestHelper - - def setup - ActiveRecord::Base.pluralize_table_names = true - Dir.mkdir("#{RAILS_ROOT}/app") unless File.exist?("#{RAILS_ROOT}/app") - Dir.mkdir("#{RAILS_ROOT}/app/views") unless File.exist?("#{RAILS_ROOT}/app/views") - Dir.mkdir("#{RAILS_ROOT}/app/views/layouts") unless File.exist?("#{RAILS_ROOT}/app/views/layouts") - Dir.mkdir("#{RAILS_ROOT}/config") unless File.exist?("#{RAILS_ROOT}/config") - Dir.mkdir("#{RAILS_ROOT}/db") unless File.exist?("#{RAILS_ROOT}/db") - Dir.mkdir("#{RAILS_ROOT}/test") unless File.exist?("#{RAILS_ROOT}/test") - Dir.mkdir("#{RAILS_ROOT}/test/fixtures") unless File.exist?("#{RAILS_ROOT}/test/fixtures") - Dir.mkdir("#{RAILS_ROOT}/public") unless File.exist?("#{RAILS_ROOT}/public") - Dir.mkdir("#{RAILS_ROOT}/public/stylesheets") unless File.exist?("#{RAILS_ROOT}/public/stylesheets") - File.open("#{RAILS_ROOT}/config/routes.rb", 'w') do |f| - f<<"ActionController::Routing::Routes.draw do |map|\n\nend\n" - end - end - - def teardown - FileUtils.rm_rf "#{RAILS_ROOT}/app" - FileUtils.rm_rf "#{RAILS_ROOT}/test" - FileUtils.rm_rf "#{RAILS_ROOT}/config" - FileUtils.rm_rf "#{RAILS_ROOT}/db" - FileUtils.rm_rf "#{RAILS_ROOT}/public" - end +class RailsModelGeneratorTest < GeneratorTestCase def test_model_generates_resources run_generator('model', %w(Product name:string)) diff --git a/railties/test/generators/rails_resource_generator_test.rb b/railties/test/generators/rails_resource_generator_test.rb index 511f1059c2..45e4850ef5 100644 --- a/railties/test/generators/rails_resource_generator_test.rb +++ b/railties/test/generators/rails_resource_generator_test.rb @@ -1,82 +1,6 @@ -require 'test/unit' - -# Optionally load RubyGems -begin - require 'rubygems' -rescue LoadError -end - -# Mock out what we need from AR::Base -module ActiveRecord - class Base - class << self - attr_accessor :pluralize_table_names - end - self.pluralize_table_names = true - end - - module ConnectionAdapters - class Column - attr_reader :name, :default, :type, :limit, :null, :sql_type, :precision, :scale - def initialize(name, default, sql_type=nil) - @namename - @default=default - @type=@sql_type=sql_type - end - - def human_name - @name.humanize - end - end - end -end - -# Mock up necessities from ActionView -module ActionView - module Helpers - module ActionRecordHelper; end - class InstanceTag; end - end -end - -# Set RAILS_ROOT appropriately fixture generation -tmp_dir="#{File.dirname(__FILE__)}/../fixtures/tmp" -if defined?(RAILS_ROOT) - RAILS_ROOT.replace(tmp_dir) -else - RAILS_ROOT=tmp_dir -end -Dir.mkdir(RAILS_ROOT) unless File.exist?(RAILS_ROOT) - -$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../lib" require 'generators/generator_test_helper' -class RailsResourceGeneratorTest < Test::Unit::TestCase - include GeneratorTestHelper - - def setup - ActiveRecord::Base.pluralize_table_names = true - Dir.mkdir("#{RAILS_ROOT}/app") unless File.exist?("#{RAILS_ROOT}/app") - Dir.mkdir("#{RAILS_ROOT}/app/views") unless File.exist?("#{RAILS_ROOT}/app/views") - Dir.mkdir("#{RAILS_ROOT}/app/views/layouts") unless File.exist?("#{RAILS_ROOT}/app/views/layouts") - Dir.mkdir("#{RAILS_ROOT}/config") unless File.exist?("#{RAILS_ROOT}/config") - Dir.mkdir("#{RAILS_ROOT}/db") unless File.exist?("#{RAILS_ROOT}/db") - Dir.mkdir("#{RAILS_ROOT}/test") unless File.exist?("#{RAILS_ROOT}/test") - Dir.mkdir("#{RAILS_ROOT}/test/fixtures") unless File.exist?("#{RAILS_ROOT}/test/fixtures") - Dir.mkdir("#{RAILS_ROOT}/public") unless File.exist?("#{RAILS_ROOT}/public") - Dir.mkdir("#{RAILS_ROOT}/public/stylesheets") unless File.exist?("#{RAILS_ROOT}/public/stylesheets") - File.open("#{RAILS_ROOT}/config/routes.rb", 'w') do |f| - f<<"ActionController::Routing::Routes.draw do |map|\n\nend\n" - end - end - - def teardown - FileUtils.rm_rf "#{RAILS_ROOT}/app" - FileUtils.rm_rf "#{RAILS_ROOT}/test" - FileUtils.rm_rf "#{RAILS_ROOT}/config" - FileUtils.rm_rf "#{RAILS_ROOT}/db" - FileUtils.rm_rf "#{RAILS_ROOT}/public" - end +class RailsResourceGeneratorTest < GeneratorTestCase def test_resource_generates_resources run_generator('resource', %w(Product name:string)) diff --git a/railties/test/generators/rails_scaffold_generator_test.rb b/railties/test/generators/rails_scaffold_generator_test.rb index 34a1ad2fe5..220f9e372e 100644 --- a/railties/test/generators/rails_scaffold_generator_test.rb +++ b/railties/test/generators/rails_scaffold_generator_test.rb @@ -1,189 +1,107 @@ -require 'abstract_unit' - -# Optionally load RubyGems. -begin - require 'rubygems' -rescue LoadError -end - -# Mock out what we need from AR::Base. -module ActiveRecord - class Base - class << self - attr_accessor :pluralize_table_names - end - self.pluralize_table_names = true - end - - module ConnectionAdapters - class Column - attr_reader :name, :default, :type, :limit, :null, :sql_type, :precision, :scale - - def initialize(name, default, sql_type = nil) - @name=name - @default=default - @type=@sql_type=sql_type - end - - def human_name - @name.humanize - end - end - end -end +require 'generators/generator_test_helper' -# And what we need from ActionView -module ActionView - module Helpers - module ActiveRecordHelper; end - class InstanceTag; end +class RailsScaffoldGeneratorTest < GeneratorTestCase + + def test_scaffolded_names + g = Rails::Generator::Base.instance('scaffold', %w(ProductLine)) + assert_equal "ProductLines", g.controller_name + assert_equal "ProductLines", g.controller_class_name + assert_equal "ProductLine", g.controller_singular_name + assert_equal "product_lines", g.controller_plural_name + assert_equal "product_lines", g.controller_file_name + assert_equal "product_lines", g.controller_table_name end -end + def test_scaffold_generates_resources -# Must set before requiring generator libs. -tmp_dir="#{File.dirname(__FILE__)}/../fixtures/tmp" -if defined?(RAILS_ROOT) - RAILS_ROOT.replace(tmp_dir) -else - RAILS_ROOT=tmp_dir -end -Dir.mkdir(RAILS_ROOT) unless File.exist?(RAILS_ROOT) - -$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../lib" + run_generator('scaffold', %w(Product name:string)) -require 'generators/generator_test_helper' + assert_generated_controller_for :products do |f| -uses_mocha "Scaffold Generator Tests" do - class RailsScaffoldGeneratorTest < Test::Unit::TestCase - - include GeneratorTestHelper - - def setup - ActiveRecord::Base.pluralize_table_names = true - Dir.mkdir("#{RAILS_ROOT}/app") unless File.exist?("#{RAILS_ROOT}/app") - Dir.mkdir("#{RAILS_ROOT}/app/views") unless File.exist?("#{RAILS_ROOT}/app/views") - Dir.mkdir("#{RAILS_ROOT}/app/views/layouts") unless File.exist?("#{RAILS_ROOT}/app/views/layouts") - Dir.mkdir("#{RAILS_ROOT}/config") unless File.exist?("#{RAILS_ROOT}/config") - Dir.mkdir("#{RAILS_ROOT}/db") unless File.exist?("#{RAILS_ROOT}/db") - Dir.mkdir("#{RAILS_ROOT}/test") unless File.exist?("#{RAILS_ROOT}/test") - Dir.mkdir("#{RAILS_ROOT}/test/fixtures") unless File.exist?("#{RAILS_ROOT}/test/fixtures") - Dir.mkdir("#{RAILS_ROOT}/public") unless File.exist?("#{RAILS_ROOT}/public") - Dir.mkdir("#{RAILS_ROOT}/public/stylesheets") unless File.exist?("#{RAILS_ROOT}/public/stylesheets") - File.open("#{RAILS_ROOT}/config/routes.rb", 'w') do |f| - f<<"ActionController::Routing::Routes.draw do |map|\n\nend\n" + assert_has_method f, :index do |name, m| + assert_match /@products = Product\.find\(:all\)/, m, "#{name} should query products table" end - end - - def teardown - FileUtils.rm_rf "#{RAILS_ROOT}/app" - FileUtils.rm_rf "#{RAILS_ROOT}/test" - FileUtils.rm_rf "#{RAILS_ROOT}/config" - FileUtils.rm_rf "#{RAILS_ROOT}/db" - FileUtils.rm_rf "#{RAILS_ROOT}/public" - end - - def test_scaffolded_names - g = Rails::Generator::Base.instance('scaffold', %w(ProductLine)) - assert_equal "ProductLines", g.controller_name - assert_equal "ProductLines", g.controller_class_name - assert_equal "ProductLine", g.controller_singular_name - assert_equal "product_lines", g.controller_plural_name - assert_equal "product_lines", g.controller_file_name - assert_equal "product_lines", g.controller_table_name - end - - def test_scaffold_generates_resources - - run_generator('scaffold', %w(Product name:string)) - assert_generated_controller_for :products do |f| - - assert_has_method f, :index do |name, m| - assert_match /@products = Product\.find\(:all\)/, m, "#{name} should query products table" - end - - assert_has_method f, :show, :edit, :update, :destroy do |name, m| - assert_match /@product = Product\.find\(params\[:id\]\)/, m, "#{name.to_s} should query products table" - end - - assert_has_method f, :new do |name, m| - assert_match /@product = Product\.new/, m, "#{name.to_s} should instantiate a product" - end - - assert_has_method f, :create do |name, m| - assert_match /@product = Product\.new\(params\[:product\]\)/, m, "#{name.to_s} should instantiate a product" - assert_match /format.xml \{ render :xml => @product.errors, :status => :unprocessable_entity \}/, m, "#{name.to_s} should set status to :unprocessable_entity code for xml" - end + assert_has_method f, :show, :edit, :update, :destroy do |name, m| + assert_match /@product = Product\.find\(params\[:id\]\)/, m, "#{name.to_s} should query products table" + end + assert_has_method f, :new do |name, m| + assert_match /@product = Product\.new/, m, "#{name.to_s} should instantiate a product" end - assert_generated_model_for :product - assert_generated_functional_test_for :products - assert_generated_unit_test_for :product - assert_generated_fixtures_for :products - assert_generated_helper_for :products - assert_generated_stylesheet :scaffold - assert_generated_views_for :products, "index.html.erb", "new.html.erb", "edit.html.erb", "show.html.erb" + assert_has_method f, :create do |name, m| + assert_match /@product = Product\.new\(params\[:product\]\)/, m, "#{name.to_s} should instantiate a product" + assert_match /format.xml \{ render :xml => @product.errors, :status => :unprocessable_entity \}/, m, "#{name.to_s} should set status to :unprocessable_entity code for xml" + end - assert_generated_migration :create_products - assert_added_route_for :products end - def test_scaffold_skip_migration_skips_migration - run_generator('scaffold', %w(Product name:string --skip-migration)) - - assert_generated_model_for :product - assert_generated_functional_test_for :products - assert_generated_unit_test_for :product - assert_generated_fixtures_for :products - assert_generated_helper_for :products - assert_generated_stylesheet :scaffold - assert_generated_views_for :products, "index.html.erb","new.html.erb","edit.html.erb","show.html.erb" - assert_skipped_migration :create_products - assert_added_route_for :products - end + assert_generated_model_for :product + assert_generated_functional_test_for :products + assert_generated_unit_test_for :product + assert_generated_fixtures_for :products + assert_generated_helper_for :products + assert_generated_stylesheet :scaffold + assert_generated_views_for :products, "index.html.erb", "new.html.erb", "edit.html.erb", "show.html.erb" - def test_scaffold_generates_resources_with_attributes - run_generator('scaffold', %w(Product name:string supplier_id:integer created_at:timestamp)) + assert_generated_migration :create_products + assert_added_route_for :products + end - assert_generated_controller_for :products do |f| + def test_scaffold_skip_migration_skips_migration + run_generator('scaffold', %w(Product name:string --skip-migration)) + + assert_generated_model_for :product + assert_generated_functional_test_for :products + assert_generated_unit_test_for :product + assert_generated_fixtures_for :products + assert_generated_helper_for :products + assert_generated_stylesheet :scaffold + assert_generated_views_for :products, "index.html.erb","new.html.erb","edit.html.erb","show.html.erb" + assert_skipped_migration :create_products + assert_added_route_for :products + end - assert_has_method f, :index do |name, m| - assert_match /@products = Product\.find\(:all\)/, m, "#{name} should query products table" - end + def test_scaffold_generates_resources_with_attributes + run_generator('scaffold', %w(Product name:string supplier_id:integer created_at:timestamp)) - assert_has_method f, :show, :edit, :update, :destroy do |name, m| - assert_match /@product = Product\.find\(params\[:id\]\)/, m, "#{name.to_s} should query products table" - end + assert_generated_controller_for :products do |f| - assert_has_method f, :new do |name, m| - assert_match /@product = Product\.new/, m, "#{name.to_s} should instantiate a product" - end + assert_has_method f, :index do |name, m| + assert_match /@products = Product\.find\(:all\)/, m, "#{name} should query products table" + end - assert_has_method f, :create do |name, m| - assert_match /@product = Product\.new\(params\[:product\]\)/, m, "#{name.to_s} should instantiate a product" - assert_match /format.xml \{ render :xml => @product.errors, :status => :unprocessable_entity \}/, m, "#{name.to_s} should set status to :unprocessable_entity code for xml" - end + assert_has_method f, :show, :edit, :update, :destroy do |name, m| + assert_match /@product = Product\.find\(params\[:id\]\)/, m, "#{name.to_s} should query products table" + end + assert_has_method f, :new do |name, m| + assert_match /@product = Product\.new/, m, "#{name.to_s} should instantiate a product" end - assert_generated_model_for :product - assert_generated_functional_test_for :products - assert_generated_unit_test_for :product - assert_generated_fixtures_for :products - assert_generated_helper_for :products - assert_generated_stylesheet :scaffold - assert_generated_views_for :products, "index.html.erb", "new.html.erb", "edit.html.erb", "show.html.erb" - - assert_generated_migration :create_products do |t| - assert_generated_column t, :name, :string - assert_generated_column t, :supplier_id, :integer - assert_generated_column t, :created_at, :timestamp + assert_has_method f, :create do |name, m| + assert_match /@product = Product\.new\(params\[:product\]\)/, m, "#{name.to_s} should instantiate a product" + assert_match /format.xml \{ render :xml => @product.errors, :status => :unprocessable_entity \}/, m, "#{name.to_s} should set status to :unprocessable_entity code for xml" end - assert_added_route_for :products end + assert_generated_model_for :product + assert_generated_functional_test_for :products + assert_generated_unit_test_for :product + assert_generated_fixtures_for :products + assert_generated_helper_for :products + assert_generated_stylesheet :scaffold + assert_generated_views_for :products, "index.html.erb", "new.html.erb", "edit.html.erb", "show.html.erb" + + assert_generated_migration :create_products do |t| + assert_generated_column t, :name, :string + assert_generated_column t, :supplier_id, :integer + assert_generated_column t, :created_at, :timestamp + end + + assert_added_route_for :products end -end
\ No newline at end of file + +end |