diff options
author | Pratik Naik <pratiknaik@gmail.com> | 2009-09-21 21:14:04 +0100 |
---|---|---|
committer | Pratik Naik <pratiknaik@gmail.com> | 2009-09-21 21:14:04 +0100 |
commit | 340be9bddd8e5902e0218a0101a40a17a4afd558 (patch) | |
tree | ef4de25f3f8eb610dc2235f0762b01cb1d464efd | |
parent | b31cdb55422226cd45a2234a4b54986f1f611151 (diff) | |
parent | 1bbb9b2db05730194edfd7d2cef9f5fcb9d79e50 (diff) | |
download | rails-340be9bddd8e5902e0218a0101a40a17a4afd558.tar.gz rails-340be9bddd8e5902e0218a0101a40a17a4afd558.tar.bz2 rails-340be9bddd8e5902e0218a0101a40a17a4afd558.zip |
Merge commit 'mainstream/master'
427 files changed, 5116 insertions, 3608 deletions
diff --git a/.gitignore b/.gitignore index 43c4d7b124..f8c7d02ad6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,16 +1,20 @@ +.DS_Store debug.log doc/rdoc +activemodel/doc activeresource/doc activerecord/doc actionpack/doc actionmailer/doc activesupport/doc +activemodel/pkg activeresource/pkg activerecord/pkg actionpack/pkg activemodel/test/fixtures/fixture_database.sqlite3 actionmailer/pkg activesupport/pkg +actionpack/test/tmp activesupport/test/fixtures/isolation_test railties/pkg railties/test/500.html @@ -23,3 +27,5 @@ railties/guides/output *.rbc *.swp *.swo +actionpack/bin +*/vendor/gems @@ -3,7 +3,7 @@ require 'rake/rdoctask' env = %(PKG_BUILD="#{ENV['PKG_BUILD']}") if ENV['PKG_BUILD'] -PROJECTS = %w(activesupport actionpack actionmailer activeresource activerecord railties) +PROJECTS = %w(activesupport actionpack actionmailer activeresource activerecord activemodel railties) Dir["#{File.dirname(__FILE__)}/*/lib/*/version.rb"].each do |version_path| require version_path @@ -12,7 +12,7 @@ end desc 'Run all tests by default' task :default => :test -%w(test isolated_test rdoc pgem package release gem).each do |task_name| +%w(test isolated_test rdoc pgem package release gem gemspec).each do |task_name| desc "Run #{task_name} task for all projects" task task_name do errors = [] @@ -30,7 +30,6 @@ task :install => :gem do system("gem install railties/pkg/rails-#{ActionPack::VERSION::STRING}.gem --no-ri --no-rdoc") end - desc "Generate documentation for the Rails framework" Rake::RDocTask.new do |rdoc| rdoc.rdoc_dir = 'doc/rdoc' diff --git a/actionmailer/Rakefile b/actionmailer/Rakefile index ebcca0d246..0224bb2cf4 100644 --- a/actionmailer/Rakefile +++ b/actionmailer/Rakefile @@ -78,6 +78,11 @@ Rake::GemPackageTask.new(spec) do |p| p.need_zip = true end +task :gemspec do + File.open(File.join(File.dirname(__FILE__), "#{spec.name}.gemspec"), "w") do |file| + file.puts spec.to_ruby + end +end desc "Publish the API documentation" task :pgem => [:package] do diff --git a/actionmailer/actionmailer.gemspec b/actionmailer/actionmailer.gemspec new file mode 100644 index 0000000000..4ced9cf308 --- /dev/null +++ b/actionmailer/actionmailer.gemspec @@ -0,0 +1,33 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{actionmailer} + s.version = "3.0.pre" + + s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version= + s.authors = ["David Heinemeier Hansson"] + s.autorequire = %q{action_mailer} + s.date = %q{2009-09-01} + s.description = %q{Makes it trivial to test and deliver emails sent from a single service layer.} + s.email = %q{david@loudthinking.com} + s.files = ["Rakefile", "install.rb", "README", "CHANGELOG", "MIT-LICENSE", "lib/action_mailer", "lib/action_mailer/adv_attr_accessor.rb", "lib/action_mailer/base.rb", "lib/action_mailer/helpers.rb", "lib/action_mailer/mail_helper.rb", "lib/action_mailer/part.rb", "lib/action_mailer/part_container.rb", "lib/action_mailer/quoting.rb", "lib/action_mailer/test_case.rb", "lib/action_mailer/test_helper.rb", "lib/action_mailer/utils.rb", "lib/action_mailer/vendor", "lib/action_mailer/vendor/text-format-0.6.3", "lib/action_mailer/vendor/text-format-0.6.3/text", "lib/action_mailer/vendor/text-format-0.6.3/text/format.rb", "lib/action_mailer/vendor/text_format.rb", "lib/action_mailer/vendor/tmail-1.2.3", "lib/action_mailer/vendor/tmail-1.2.3/tmail", "lib/action_mailer/vendor/tmail-1.2.3/tmail/address.rb", "lib/action_mailer/vendor/tmail-1.2.3/tmail/attachments.rb", "lib/action_mailer/vendor/tmail-1.2.3/tmail/base64.rb", "lib/action_mailer/vendor/tmail-1.2.3/tmail/compat.rb", "lib/action_mailer/vendor/tmail-1.2.3/tmail/config.rb", "lib/action_mailer/vendor/tmail-1.2.3/tmail/core_extensions.rb", "lib/action_mailer/vendor/tmail-1.2.3/tmail/encode.rb", "lib/action_mailer/vendor/tmail-1.2.3/tmail/header.rb", "lib/action_mailer/vendor/tmail-1.2.3/tmail/index.rb", "lib/action_mailer/vendor/tmail-1.2.3/tmail/interface.rb", "lib/action_mailer/vendor/tmail-1.2.3/tmail/loader.rb", "lib/action_mailer/vendor/tmail-1.2.3/tmail/mail.rb", "lib/action_mailer/vendor/tmail-1.2.3/tmail/mailbox.rb", "lib/action_mailer/vendor/tmail-1.2.3/tmail/main.rb", "lib/action_mailer/vendor/tmail-1.2.3/tmail/mbox.rb", "lib/action_mailer/vendor/tmail-1.2.3/tmail/net.rb", "lib/action_mailer/vendor/tmail-1.2.3/tmail/obsolete.rb", "lib/action_mailer/vendor/tmail-1.2.3/tmail/parser.rb", "lib/action_mailer/vendor/tmail-1.2.3/tmail/port.rb", "lib/action_mailer/vendor/tmail-1.2.3/tmail/quoting.rb", "lib/action_mailer/vendor/tmail-1.2.3/tmail/require_arch.rb", "lib/action_mailer/vendor/tmail-1.2.3/tmail/scanner.rb", "lib/action_mailer/vendor/tmail-1.2.3/tmail/scanner_r.rb", "lib/action_mailer/vendor/tmail-1.2.3/tmail/stringio.rb", "lib/action_mailer/vendor/tmail-1.2.3/tmail/utils.rb", "lib/action_mailer/vendor/tmail-1.2.3/tmail/version.rb", "lib/action_mailer/vendor/tmail-1.2.3/tmail.rb", "lib/action_mailer/vendor/tmail.rb", "lib/action_mailer/version.rb", "lib/action_mailer.rb", "lib/actionmailer.rb", "test/abstract_unit.rb", "test/adv_attr_test.rb", "test/asset_host_test.rb", "test/delivery_method_test.rb", "test/fixtures", "test/fixtures/asset_host_mailer", "test/fixtures/asset_host_mailer/email_with_asset.html.erb", "test/fixtures/auto_layout_mailer", "test/fixtures/auto_layout_mailer/hello.html.erb", "test/fixtures/auto_layout_mailer/multipart.html.erb", "test/fixtures/auto_layout_mailer/multipart.text.erb", "test/fixtures/explicit_layout_mailer", "test/fixtures/explicit_layout_mailer/logout.html.erb", "test/fixtures/explicit_layout_mailer/signup.html.erb", "test/fixtures/first_mailer", "test/fixtures/first_mailer/share.erb", "test/fixtures/helper_mailer", "test/fixtures/helper_mailer/use_example_helper.erb", "test/fixtures/helper_mailer/use_helper.erb", "test/fixtures/helper_mailer/use_helper_method.erb", "test/fixtures/helper_mailer/use_mail_helper.erb", "test/fixtures/helpers", "test/fixtures/helpers/example_helper.rb", "test/fixtures/layouts", "test/fixtures/layouts/auto_layout_mailer.html.erb", "test/fixtures/layouts/auto_layout_mailer.text.erb", "test/fixtures/layouts/spam.html.erb", "test/fixtures/path.with.dots", "test/fixtures/path.with.dots/funky_path_mailer", "test/fixtures/path.with.dots/funky_path_mailer/multipart_with_template_path_with_dots.erb", "test/fixtures/raw_email", "test/fixtures/raw_email10", "test/fixtures/raw_email12", "test/fixtures/raw_email13", "test/fixtures/raw_email2", "test/fixtures/raw_email3", "test/fixtures/raw_email4", "test/fixtures/raw_email5", "test/fixtures/raw_email6", "test/fixtures/raw_email7", "test/fixtures/raw_email8", "test/fixtures/raw_email9", "test/fixtures/raw_email_quoted_with_0d0a", "test/fixtures/raw_email_with_invalid_characters_in_content_type", "test/fixtures/raw_email_with_nested_attachment", "test/fixtures/raw_email_with_partially_quoted_subject", "test/fixtures/second_mailer", "test/fixtures/second_mailer/share.erb", "test/fixtures/templates", "test/fixtures/templates/signed_up.erb", "test/fixtures/test_mailer", "test/fixtures/test_mailer/_subtemplate.text.erb", "test/fixtures/test_mailer/body_ivar.erb", "test/fixtures/test_mailer/custom_templating_extension.html.haml", "test/fixtures/test_mailer/custom_templating_extension.text.haml", "test/fixtures/test_mailer/implicitly_multipart_example.html.erb", "test/fixtures/test_mailer/implicitly_multipart_example.html.erb~", "test/fixtures/test_mailer/implicitly_multipart_example.ignored.erb", "test/fixtures/test_mailer/implicitly_multipart_example.rhtml.bak", "test/fixtures/test_mailer/implicitly_multipart_example.text.erb", "test/fixtures/test_mailer/implicitly_multipart_example.yaml.erb", "test/fixtures/test_mailer/included_subtemplate.text.erb", "test/fixtures/test_mailer/rxml_template.rxml", "test/fixtures/test_mailer/signed_up.html.erb", "test/fixtures/test_mailer/signed_up_with_url.erb", "test/mail_helper_test.rb", "test/mail_layout_test.rb", "test/mail_render_test.rb", "test/mail_service_test.rb", "test/quoting_test.rb", "test/test_helper_test.rb", "test/tmail_test.rb", "test/url_test.rb"] + s.homepage = %q{http://www.rubyonrails.org} + s.require_paths = ["lib"] + s.requirements = ["none"] + s.rubyforge_project = %q{actionmailer} + s.rubygems_version = %q{1.3.5} + s.summary = %q{Service layer for easy email delivery and testing.} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 3 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q<actionpack>, ["= 3.0.pre"]) + else + s.add_dependency(%q<actionpack>, ["= 3.0.pre"]) + end + else + s.add_dependency(%q<actionpack>, ["= 3.0.pre"]) + end +end diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index d020fdffc2..eb648d249a 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -256,6 +256,8 @@ module ActionMailer #:nodoc: # +implicit_parts_order+. class Base include AdvAttrAccessor, PartContainer, Quoting, Utils + extend AbstractController::RenderingController + if Object.const_defined?(:ActionController) include ActionController::UrlWriter include ActionController::Layout @@ -479,58 +481,62 @@ module ActionMailer #:nodoc: # Initialize the mailer via the given +method_name+. The body will be # rendered and a new TMail::Mail object created. def create!(method_name, *parameters) #:nodoc: - initialize_defaults(method_name) - __send__(method_name, *parameters) - - # If an explicit, textual body has not been set, we check assumptions. - unless String === @body - # First, we look to see if there are any likely templates that match, - # which include the content-type in their file name (i.e., - # "the_template_file.text.html.erb", etc.). Only do this if parts - # have not already been specified manually. - # if @parts.empty? - template_root.find_all_by_parts(@template, {}, template_path).each do |template| - @parts << Part.new( - :content_type => template.mime_type ? template.mime_type.to_s : "text/plain", - :disposition => "inline", - :charset => charset, - :body => render_template(template, @body) - ) - end - - if @parts.size > 1 - @content_type = "multipart/alternative" if @content_type !~ /^multipart/ - @parts = sort_parts(@parts, @implicit_parts_order) - end - # end - - # Then, if there were such templates, we check to see if we ought to - # also render a "normal" template (without the content type). If a - # normal template exists (or if there were no implicit parts) we render - # it. - # ==== - # TODO: Revisit this - # template_exists = @parts.empty? - # template_exists ||= template_root.find("#{mailer_name}/#{@template}") - # @body = render_message(@template, @body) if template_exists - - # Finally, if there are other message parts and a textual body exists, - # we shift it onto the front of the parts and set the body to nil (so - # that create_mail doesn't try to render it in addition to the parts). - # ==== - # TODO: Revisit this - # if !@parts.empty? && String === @body - # @parts.unshift Part.new(:charset => charset, :body => @body) - # @body = nil - # end - end + ActiveSupport::Orchestra.instrument(:create_mail, :name => method_name) do + initialize_defaults(method_name) + __send__(method_name, *parameters) + + # If an explicit, textual body has not been set, we check assumptions. + unless String === @body + # First, we look to see if there are any likely templates that match, + # which include the content-type in their file name (i.e., + # "the_template_file.text.html.erb", etc.). Only do this if parts + # have not already been specified manually. + # if @parts.empty? + template_root.find_all(@template, {}, template_path).each do |template| + @parts << Part.new( + :content_type => template.mime_type ? template.mime_type.to_s : "text/plain", + :disposition => "inline", + :charset => charset, + :body => render_template(template, @body) + ) + end + + if @parts.size > 1 + @content_type = "multipart/alternative" if @content_type !~ /^multipart/ + @parts = sort_parts(@parts, @implicit_parts_order) + end + # end + + # Then, if there were such templates, we check to see if we ought to + # also render a "normal" template (without the content type). If a + # normal template exists (or if there were no implicit parts) we render + # it. + # ==== + # TODO: Revisit this + # template_exists = @parts.empty? + # template_exists ||= template_root.find("#{mailer_name}/#{@template}") + # @body = render_message(@template, @body) if template_exists + + # Finally, if there are other message parts and a textual body exists, + # we shift it onto the front of the parts and set the body to nil (so + # that create_mail doesn't try to render it in addition to the parts). + # ==== + # TODO: Revisit this + # if !@parts.empty? && String === @body + # @parts.unshift Part.new(:charset => charset, :body => @body) + # @body = nil + # end + end + + # If this is a multipart e-mail add the mime_version if it is not + # already set. + @mime_version ||= "1.0" if !@parts.empty? - # If this is a multipart e-mail add the mime_version if it is not - # already set. - @mime_version ||= "1.0" if !@parts.empty? + # build the mail object itself + @mail = create_mail + end - # build the mail object itself - @mail = create_mail + @mail end # Delivers a TMail::Mail object. By default, it delivers the cached mail @@ -538,19 +544,21 @@ module ActionMailer #:nodoc: # no alternate has been given as the parameter, this will fail. def deliver!(mail = @mail) raise "no mail object available for delivery!" unless mail - + unless logger.nil? logger.info "Sent mail to #{Array(recipients).join(', ')}" logger.debug "\n#{mail.encoded}" end - begin - __send__("perform_delivery_#{delivery_method}", mail) if perform_deliveries - rescue Exception => e # Net::SMTP errors or sendmail pipe errors - raise e if raise_delivery_errors + ActiveSupport::Orchestra.instrument(:deliver_mail, :mail => @mail) do + begin + __send__("perform_delivery_#{delivery_method}", mail) if perform_deliveries + rescue Exception => e # Net::SMTP errors or sendmail pipe errors + raise e if raise_delivery_errors + end end - return mail + mail end private diff --git a/actionmailer/lib/actionmailer.rb b/actionmailer/lib/actionmailer.rb deleted file mode 100644 index 506416292c..0000000000 --- a/actionmailer/lib/actionmailer.rb +++ /dev/null @@ -1 +0,0 @@ -require 'action_mailer' diff --git a/actionpack/Gemfile b/actionpack/Gemfile new file mode 100644 index 0000000000..b1579b427b --- /dev/null +++ b/actionpack/Gemfile @@ -0,0 +1,14 @@ +rails_root = Pathname.new(File.dirname(__FILE__)).join("..") + +gem "rack", "~> 1.0.0" +gem "rack-test", "~> 0.4.2" +gem "activesupport", "3.0.pre", :vendored_at => rails_root.join("activesupport") +gem "activemodel", "3.0.pre", :vendored_at => rails_root.join("activemodel") + +only :test do + gem "mocha" + gem "sqlite3-ruby" + gem "RedCloth" +end + +disable_system_gems diff --git a/actionpack/Rakefile b/actionpack/Rakefile index 1181995436..cc7b4b0043 100644 --- a/actionpack/Rakefile +++ b/actionpack/Rakefile @@ -17,68 +17,48 @@ RUBY_FORGE_PROJECT = "actionpack" RUBY_FORGE_USER = "webster132" desc "Default Task" -task :default => [ :test ] +task :default => :test + +task :bundle do + puts "Checking if the bundled testing requirements are up to date..." + result = system "gem bundle" + unless result + puts "The gem bundler is not installed. Installing." + system "gem install bundler" + system "gem bundle" + end +end # Run the unit tests desc "Run all unit tests" -task :test => [:test_action_pack, :test_active_record_integration, :test_new_base] +task :test => [:test_action_pack, :test_active_record_integration] + +TESTS_GLOB = "test/{abstract,controller,dispatch,new_base,template,html-scanner}/**/*_test.rb" -test_lib_dirs = ENV["NEW"] ? ["test/new_base"] : [] -test_lib_dirs.push "test", "test/lib" -# test_lib_dirs = [ENV["NEW"] ? "test/new_base" : "test", "test/lib"] Rake::TestTask.new(:test_action_pack) do |t| - t.libs.concat test_lib_dirs + t.libs << 'test' # make sure we include the tests in alphabetical order as on some systems # this will not happen automatically and the tests (as a whole) will error - t.test_files = Dir.glob( "test/{controller,dispatch,template,html-scanner}/**/*_test.rb" ).sort + t.test_files = Dir.glob(TESTS_GLOB).sort t.verbose = true - #t.warning = true + # t.warning = true end task :isolated_test do ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')) - Dir.glob("test/{controller,dispatch,template}/**/*_test.rb").all? do |file| - system(ruby, "-Ilib:#{test_lib_dirs * ':'}", file) - end or raise "Failures" + Dir.glob(TESTS_GLOB).all? { |file| system(ruby, '-Ilib:test', file) } or raise "Failures" end desc 'ActiveRecord Integration Tests' Rake::TestTask.new(:test_active_record_integration) do |t| - t.libs.concat test_lib_dirs + t.libs << 'test' t.test_files = Dir.glob("test/activerecord/*_test.rb") t.verbose = true end -desc 'New Controller Tests' -Rake::TestTask.new(:test_new_base) do |t| - t.libs << "test/new_base" << "test/lib" - t.test_files = Dir.glob("test/{abstract_controller,new_base}/*_test.rb") - t.verbose = true -end - -desc 'Old Controller Tests on New Base' -Rake::TestTask.new(:test_new_base_on_old_tests) do |t| - t.libs << "test/new_base" << "test/lib" - - t.verbose = true - # ==== Not ported - # * filters - - t.test_files = Dir.glob( "test/{dispatch,template}/**/*_test.rb" ).sort + %w( - action_pack_assertions addresses_render assert_select - base benchmark caching capture content_type cookie dispatcher - filter_params flash helper http_basic_authentication - http_digest_authentication integration layout logging mime_responds - record_identifier redirect render render_js render_json - render_other render_xml request_forgery_protection rescue - resources routing selector send_file test url_rewriter - verification view_paths webservice - ).map { |name| "test/controller/#{name}_test.rb" } -end - # Genereate the RDoc documentation Rake::RDocTask.new { |rdoc| @@ -116,6 +96,7 @@ spec = Gem::Specification.new do |s| s.requirements << 'none' s.add_dependency('activesupport', '= 3.0.pre' + PKG_BUILD) + s.add_dependency('activemodel', '= 3.0.pre' + PKG_BUILD) s.add_dependency('rack', '~> 1.0.0') s.add_dependency('rack-test', '~> 0.4.2') @@ -134,6 +115,12 @@ Rake::GemPackageTask.new(spec) do |p| p.need_zip = true end +task :gemspec do + File.open(File.join(File.dirname(__FILE__), "#{spec.name}.gemspec"), "w") do |file| + file.puts spec.to_ruby + end +end + task :lines do lines, codelines, total_lines, total_codelines = 0, 0, 0, 0 diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec new file mode 100644 index 0000000000..b91993a12e --- /dev/null +++ b/actionpack/actionpack.gemspec @@ -0,0 +1,42 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{actionpack} + s.version = "3.0.pre" + + s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version= + s.authors = ["David Heinemeier Hansson"] + s.autorequire = %q{action_controller} + s.date = %q{2009-09-01} + s.description = %q{Eases web-request routing, handling, and response as a half-way front, half-way page controller. Implemented with specific emphasis on enabling easy unit/integration testing that doesn't require a browser.} + s.email = %q{david@loudthinking.com} + s.files = ["Rakefile", "install.rb", "README", "RUNNING_UNIT_TESTS", "CHANGELOG", "MIT-LICENSE", "lib/abstract_controller", "lib/abstract_controller/base.rb", "lib/abstract_controller/benchmarker.rb", "lib/abstract_controller/callbacks.rb", "lib/abstract_controller/exceptions.rb", "lib/abstract_controller/helpers.rb", "lib/abstract_controller/layouts.rb", "lib/abstract_controller/logger.rb", "lib/abstract_controller/rendering_controller.rb", "lib/abstract_controller.rb", "lib/action_controller", "lib/action_controller/base.rb", "lib/action_controller/caching", "lib/action_controller/caching/actions.rb", "lib/action_controller/caching/fragments.rb", "lib/action_controller/caching/pages.rb", "lib/action_controller/caching/sweeping.rb", "lib/action_controller/caching.rb", "lib/action_controller/deprecated.rb", "lib/action_controller/dispatch", "lib/action_controller/dispatch/dispatcher.rb", "lib/action_controller/dispatch/middlewares.rb", "lib/action_controller/legacy", "lib/action_controller/legacy/layout.rb", "lib/action_controller/metal", "lib/action_controller/metal/compatibility.rb", "lib/action_controller/metal/conditional_get.rb", "lib/action_controller/metal/cookies.rb", "lib/action_controller/metal/exceptions.rb", "lib/action_controller/metal/filter_parameter_logging.rb", "lib/action_controller/metal/flash.rb", "lib/action_controller/metal/helpers.rb", "lib/action_controller/metal/hide_actions.rb", "lib/action_controller/metal/http_authentication.rb", "lib/action_controller/metal/layouts.rb", "lib/action_controller/metal/mime_responds.rb", "lib/action_controller/metal/rack_convenience.rb", "lib/action_controller/metal/redirector.rb", "lib/action_controller/metal/render_options.rb", "lib/action_controller/metal/rendering_controller.rb", "lib/action_controller/metal/request_forgery_protection.rb", "lib/action_controller/metal/rescuable.rb", "lib/action_controller/metal/responder.rb", "lib/action_controller/metal/session.rb", "lib/action_controller/metal/session_management.rb", "lib/action_controller/metal/streaming.rb", "lib/action_controller/metal/testing.rb", "lib/action_controller/metal/url_for.rb", "lib/action_controller/metal/verification.rb", "lib/action_controller/metal.rb", "lib/action_controller/middleware.rb", "lib/action_controller/record_identifier.rb", "lib/action_controller/routing", "lib/action_controller/routing/builder.rb", "lib/action_controller/routing/generation", "lib/action_controller/routing/generation/polymorphic_routes.rb", "lib/action_controller/routing/generation/url_rewriter.rb", "lib/action_controller/routing/optimisations.rb", "lib/action_controller/routing/recognition_optimisation.rb", "lib/action_controller/routing/resources.rb", "lib/action_controller/routing/route.rb", "lib/action_controller/routing/route_set.rb", "lib/action_controller/routing/routing_ext.rb", "lib/action_controller/routing/segments.rb", "lib/action_controller/routing.rb", "lib/action_controller/testing", "lib/action_controller/testing/integration.rb", "lib/action_controller/testing/performance_test.rb", "lib/action_controller/testing/process.rb", "lib/action_controller/testing/test_case.rb", "lib/action_controller/translation.rb", "lib/action_controller/vendor", "lib/action_controller/vendor/html-scanner", "lib/action_controller/vendor/html-scanner/html", "lib/action_controller/vendor/html-scanner/html/document.rb", "lib/action_controller/vendor/html-scanner/html/node.rb", "lib/action_controller/vendor/html-scanner/html/sanitizer.rb", "lib/action_controller/vendor/html-scanner/html/selector.rb", "lib/action_controller/vendor/html-scanner/html/tokenizer.rb", "lib/action_controller/vendor/html-scanner/html/version.rb", "lib/action_controller/vendor/html-scanner.rb", "lib/action_controller.rb", "lib/action_dispatch", "lib/action_dispatch/http", "lib/action_dispatch/http/headers.rb", "lib/action_dispatch/http/mime_type.rb", "lib/action_dispatch/http/mime_types.rb", "lib/action_dispatch/http/request.rb", "lib/action_dispatch/http/response.rb", "lib/action_dispatch/http/status_codes.rb", "lib/action_dispatch/middleware", "lib/action_dispatch/middleware/callbacks.rb", "lib/action_dispatch/middleware/params_parser.rb", "lib/action_dispatch/middleware/rescue.rb", "lib/action_dispatch/middleware/session", "lib/action_dispatch/middleware/session/abstract_store.rb", "lib/action_dispatch/middleware/session/cookie_store.rb", "lib/action_dispatch/middleware/session/mem_cache_store.rb", "lib/action_dispatch/middleware/show_exceptions.rb", "lib/action_dispatch/middleware/stack.rb", "lib/action_dispatch/middleware/templates", "lib/action_dispatch/middleware/templates/rescues", "lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb", "lib/action_dispatch/middleware/templates/rescues/_trace.erb", "lib/action_dispatch/middleware/templates/rescues/diagnostics.erb", "lib/action_dispatch/middleware/templates/rescues/layout.erb", "lib/action_dispatch/middleware/templates/rescues/missing_template.erb", "lib/action_dispatch/middleware/templates/rescues/routing_error.erb", "lib/action_dispatch/middleware/templates/rescues/template_error.erb", "lib/action_dispatch/middleware/templates/rescues/unknown_action.erb", "lib/action_dispatch/testing", "lib/action_dispatch/testing/assertions", "lib/action_dispatch/testing/assertions/dom.rb", "lib/action_dispatch/testing/assertions/model.rb", "lib/action_dispatch/testing/assertions/response.rb", "lib/action_dispatch/testing/assertions/routing.rb", "lib/action_dispatch/testing/assertions/selector.rb", "lib/action_dispatch/testing/assertions/tag.rb", "lib/action_dispatch/testing/assertions.rb", "lib/action_dispatch/testing/test_request.rb", "lib/action_dispatch/testing/test_response.rb", "lib/action_dispatch/vendor", "lib/action_dispatch/vendor/rack-1.1.pre", "lib/action_dispatch/vendor/rack-test", "lib/action_dispatch/vendor/rack-test/rack", "lib/action_dispatch.rb", "lib/action_pack", "lib/action_pack/version.rb", "lib/action_pack.rb", "lib/action_view", "lib/action_view/base.rb", "lib/action_view/context.rb", "lib/action_view/erb", "lib/action_view/erb/util.rb", "lib/action_view/helpers", "lib/action_view/helpers/active_model_helper.rb", "lib/action_view/helpers/ajax_helper.rb", "lib/action_view/helpers/asset_tag_helper.rb", "lib/action_view/helpers/atom_feed_helper.rb", "lib/action_view/helpers/benchmark_helper.rb", "lib/action_view/helpers/cache_helper.rb", "lib/action_view/helpers/capture_helper.rb", "lib/action_view/helpers/date_helper.rb", "lib/action_view/helpers/debug_helper.rb", "lib/action_view/helpers/form_helper.rb", "lib/action_view/helpers/form_options_helper.rb", "lib/action_view/helpers/form_tag_helper.rb", "lib/action_view/helpers/javascript_helper.rb", "lib/action_view/helpers/number_helper.rb", "lib/action_view/helpers/prototype_helper.rb", "lib/action_view/helpers/record_identification_helper.rb", "lib/action_view/helpers/record_tag_helper.rb", "lib/action_view/helpers/sanitize_helper.rb", "lib/action_view/helpers/scriptaculous_helper.rb", "lib/action_view/helpers/tag_helper.rb", "lib/action_view/helpers/text_helper.rb", "lib/action_view/helpers/translation_helper.rb", "lib/action_view/helpers/url_helper.rb", "lib/action_view/helpers.rb", "lib/action_view/locale", "lib/action_view/locale/en.yml", "lib/action_view/paths.rb", "lib/action_view/render", "lib/action_view/render/partials.rb", "lib/action_view/render/rendering.rb", "lib/action_view/template", "lib/action_view/template/error.rb", "lib/action_view/template/handler.rb", "lib/action_view/template/handlers", "lib/action_view/template/handlers/builder.rb", "lib/action_view/template/handlers/erb.rb", "lib/action_view/template/handlers/rjs.rb", "lib/action_view/template/handlers.rb", "lib/action_view/template/inline.rb", "lib/action_view/template/partial.rb", "lib/action_view/template/renderable.rb", "lib/action_view/template/resolver.rb", "lib/action_view/template/template.rb", "lib/action_view/template/text.rb", "lib/action_view/test_case.rb", "lib/action_view.rb", "lib/actionpack.rb", "test/abstract_controller", "test/abstract_controller/abstract_controller_test.rb", "test/abstract_controller/callbacks_test.rb", "test/abstract_controller/helper_test.rb", "test/abstract_controller/layouts_test.rb", "test/abstract_controller/test_helper.rb", "test/abstract_controller/views", "test/abstract_controller/views/abstract_controller", "test/abstract_controller/views/abstract_controller/testing", "test/abstract_controller/views/abstract_controller/testing/me3", "test/abstract_controller/views/abstract_controller/testing/me3/formatted.html.erb", "test/abstract_controller/views/abstract_controller/testing/me3/index.erb", "test/abstract_controller/views/abstract_controller/testing/me4", "test/abstract_controller/views/abstract_controller/testing/me4/index.erb", "test/abstract_controller/views/abstract_controller/testing/me5", "test/abstract_controller/views/abstract_controller/testing/me5/index.erb", "test/abstract_controller/views/action_with_ivars.erb", "test/abstract_controller/views/helper_test.erb", "test/abstract_controller/views/index.erb", "test/abstract_controller/views/layouts", "test/abstract_controller/views/layouts/abstract_controller", "test/abstract_controller/views/layouts/abstract_controller/testing", "test/abstract_controller/views/layouts/abstract_controller/testing/me4.erb", "test/abstract_controller/views/layouts/application.erb", "test/abstract_controller/views/naked_render.erb", "test/abstract_unit.rb", "test/activerecord", "test/activerecord/active_record_store_test.rb", "test/activerecord/polymorphic_routes_test.rb", "test/activerecord/render_partial_with_record_identification_test.rb", "test/controller", "test/controller/action_pack_assertions_test.rb", "test/controller/addresses_render_test.rb", "test/controller/assert_select_test.rb", "test/controller/base_test.rb", "test/controller/benchmark_test.rb", "test/controller/caching_test.rb", "test/controller/capture_test.rb", "test/controller/content_type_test.rb", "test/controller/controller_fixtures", "test/controller/controller_fixtures/app", "test/controller/controller_fixtures/app/controllers", "test/controller/controller_fixtures/app/controllers/admin", "test/controller/controller_fixtures/app/controllers/admin/user_controller.rb", "test/controller/controller_fixtures/app/controllers/user_controller.rb", "test/controller/controller_fixtures/vendor", "test/controller/controller_fixtures/vendor/plugins", "test/controller/controller_fixtures/vendor/plugins/bad_plugin", "test/controller/controller_fixtures/vendor/plugins/bad_plugin/lib", "test/controller/controller_fixtures/vendor/plugins/bad_plugin/lib/plugin_controller.rb", "test/controller/cookie_test.rb", "test/controller/deprecation", "test/controller/deprecation/deprecated_base_methods_test.rb", "test/controller/dispatcher_test.rb", "test/controller/filter_params_test.rb", "test/controller/filters_test.rb", "test/controller/flash_test.rb", "test/controller/helper_test.rb", "test/controller/http_basic_authentication_test.rb", "test/controller/http_digest_authentication_test.rb", "test/controller/integration_test.rb", "test/controller/layout_test.rb", "test/controller/logging_test.rb", "test/controller/mime_responds_test.rb", "test/controller/record_identifier_test.rb", "test/controller/redirect_test.rb", "test/controller/render_js_test.rb", "test/controller/render_json_test.rb", "test/controller/render_other_test.rb", "test/controller/render_test.rb", "test/controller/render_xml_test.rb", "test/controller/request", "test/controller/request/test_request_test.rb", "test/controller/request_forgery_protection_test.rb", "test/controller/rescue_test.rb", "test/controller/resources_test.rb", "test/controller/routing_test.rb", "test/controller/selector_test.rb", "test/controller/send_file_test.rb", "test/controller/test_test.rb", "test/controller/translation_test.rb", "test/controller/url_rewriter_test.rb", "test/controller/verification_test.rb", "test/controller/view_paths_test.rb", "test/controller/webservice_test.rb", "test/dispatch", "test/dispatch/header_test.rb", "test/dispatch/middleware_stack_test.rb", "test/dispatch/mime_type_test.rb", "test/dispatch/rack_test.rb", "test/dispatch/request", "test/dispatch/request/json_params_parsing_test.rb", "test/dispatch/request/multipart_params_parsing_test.rb", "test/dispatch/request/query_string_parsing_test.rb", "test/dispatch/request/url_encoded_params_parsing_test.rb", "test/dispatch/request/xml_params_parsing_test.rb", "test/dispatch/request_test.rb", "test/dispatch/response_test.rb", "test/dispatch/session", "test/dispatch/session/cookie_store_test.rb", "test/dispatch/session/mem_cache_store_test.rb", "test/dispatch/session/test_session_test.rb", "test/dispatch/show_exceptions_test.rb", "test/dispatch/test_request_test.rb", "test/fixtures", "test/fixtures/_top_level_partial.html.erb", "test/fixtures/_top_level_partial_only.erb", "test/fixtures/addresses", "test/fixtures/addresses/list.erb", "test/fixtures/alternate_helpers", "test/fixtures/alternate_helpers/foo_helper.rb", "test/fixtures/bad_customers", "test/fixtures/bad_customers/_bad_customer.html.erb", "test/fixtures/companies.yml", "test/fixtures/company.rb", "test/fixtures/content_type", "test/fixtures/content_type/render_default_content_types_for_respond_to.xml.erb", "test/fixtures/content_type/render_default_for_rhtml.rhtml", "test/fixtures/content_type/render_default_for_rjs.rjs", "test/fixtures/content_type/render_default_for_rxml.rxml", "test/fixtures/customers", "test/fixtures/customers/_customer.html.erb", "test/fixtures/db_definitions", "test/fixtures/db_definitions/sqlite.sql", "test/fixtures/developer.rb", "test/fixtures/developers", "test/fixtures/developers/_developer.erb", "test/fixtures/developers.yml", "test/fixtures/developers_projects.yml", "test/fixtures/fun", "test/fixtures/fun/games", "test/fixtures/fun/games/_game.erb", "test/fixtures/fun/games/hello_world.erb", "test/fixtures/fun/serious", "test/fixtures/fun/serious/games", "test/fixtures/fun/serious/games/_game.erb", "test/fixtures/functional_caching", "test/fixtures/functional_caching/_partial.erb", "test/fixtures/functional_caching/formatted_fragment_cached.html.erb", "test/fixtures/functional_caching/formatted_fragment_cached.js.rjs", "test/fixtures/functional_caching/formatted_fragment_cached.xml.builder", "test/fixtures/functional_caching/fragment_cached.html.erb", "test/fixtures/functional_caching/html_fragment_cached_with_partial.html.erb", "test/fixtures/functional_caching/inline_fragment_cached.html.erb", "test/fixtures/functional_caching/js_fragment_cached_with_partial.js.rjs", "test/fixtures/good_customers", "test/fixtures/good_customers/_good_customer.html.erb", "test/fixtures/happy_path", "test/fixtures/happy_path/render_action", "test/fixtures/happy_path/render_action/hello_world.erb", "test/fixtures/helpers", "test/fixtures/helpers/abc_helper.rb", "test/fixtures/helpers/fun", "test/fixtures/helpers/fun/games_helper.rb", "test/fixtures/helpers/fun/pdf_helper.rb", "test/fixtures/layout_tests", "test/fixtures/layout_tests/alt", "test/fixtures/layout_tests/alt/hello.rhtml", "test/fixtures/layout_tests/alt/layouts", "test/fixtures/layout_tests/alt/layouts/alt.rhtml", "test/fixtures/layout_tests/layouts", "test/fixtures/layout_tests/layouts/controller_name_space", "test/fixtures/layout_tests/layouts/controller_name_space/nested.rhtml", "test/fixtures/layout_tests/layouts/item.rhtml", "test/fixtures/layout_tests/layouts/layout_test.rhtml", "test/fixtures/layout_tests/layouts/multiple_extensions.html.erb", "test/fixtures/layout_tests/layouts/symlinked", "test/fixtures/layout_tests/layouts/third_party_template_library.mab", "test/fixtures/layout_tests/views", "test/fixtures/layout_tests/views/goodbye.rhtml", "test/fixtures/layout_tests/views/hello.rhtml", "test/fixtures/layouts", "test/fixtures/layouts/_column.html.erb", "test/fixtures/layouts/block_with_layout.erb", "test/fixtures/layouts/builder.builder", "test/fixtures/layouts/partial_with_layout.erb", "test/fixtures/layouts/standard.html.erb", "test/fixtures/layouts/talk_from_action.erb", "test/fixtures/layouts/xhr.html.erb", "test/fixtures/layouts/yield.erb", "test/fixtures/mascot.rb", "test/fixtures/mascots", "test/fixtures/mascots/_mascot.html.erb", "test/fixtures/mascots.yml", "test/fixtures/multipart", "test/fixtures/multipart/binary_file", "test/fixtures/multipart/boundary_problem_file", "test/fixtures/multipart/bracketed_param", "test/fixtures/multipart/empty", "test/fixtures/multipart/hello.txt", "test/fixtures/multipart/large_text_file", "test/fixtures/multipart/mixed_files", "test/fixtures/multipart/mona_lisa.jpg", "test/fixtures/multipart/none", "test/fixtures/multipart/single_parameter", "test/fixtures/multipart/text_file", "test/fixtures/override", "test/fixtures/override/test", "test/fixtures/override/test/hello_world.erb", "test/fixtures/override2", "test/fixtures/override2/layouts", "test/fixtures/override2/layouts/test", "test/fixtures/override2/layouts/test/sub.erb", "test/fixtures/post_test", "test/fixtures/post_test/layouts", "test/fixtures/post_test/layouts/post.html.erb", "test/fixtures/post_test/layouts/super_post.iphone.erb", "test/fixtures/post_test/post", "test/fixtures/post_test/post/index.html.erb", "test/fixtures/post_test/post/index.iphone.erb", "test/fixtures/post_test/super_post", "test/fixtures/post_test/super_post/index.html.erb", "test/fixtures/post_test/super_post/index.iphone.erb", "test/fixtures/project.rb", "test/fixtures/projects", "test/fixtures/projects/_project.erb", "test/fixtures/projects.yml", "test/fixtures/public", "test/fixtures/public/404.html", "test/fixtures/public/500.da.html", "test/fixtures/public/500.html", "test/fixtures/public/absolute", "test/fixtures/public/absolute/test.css", "test/fixtures/public/absolute/test.js", "test/fixtures/public/elsewhere", "test/fixtures/public/elsewhere/cools.js", "test/fixtures/public/elsewhere/file.css", "test/fixtures/public/images", "test/fixtures/public/images/rails.png", "test/fixtures/public/javascripts", "test/fixtures/public/javascripts/application.js", "test/fixtures/public/javascripts/bank.js", "test/fixtures/public/javascripts/cache", "test/fixtures/public/javascripts/common.javascript", "test/fixtures/public/javascripts/controls.js", "test/fixtures/public/javascripts/dragdrop.js", "test/fixtures/public/javascripts/effects.js", "test/fixtures/public/javascripts/prototype.js", "test/fixtures/public/javascripts/robber.js", "test/fixtures/public/javascripts/subdir", "test/fixtures/public/javascripts/subdir/subdir.js", "test/fixtures/public/javascripts/version.1.0.js", "test/fixtures/public/stylesheets", "test/fixtures/public/stylesheets/bank.css", "test/fixtures/public/stylesheets/random.styles", "test/fixtures/public/stylesheets/robber.css", "test/fixtures/public/stylesheets/subdir", "test/fixtures/public/stylesheets/subdir/subdir.css", "test/fixtures/public/stylesheets/version.1.0.css", "test/fixtures/quiz", "test/fixtures/quiz/questions", "test/fixtures/quiz/questions/_question.html.erb", "test/fixtures/replies", "test/fixtures/replies/_reply.erb", "test/fixtures/replies.yml", "test/fixtures/reply.rb", "test/fixtures/respond_to", "test/fixtures/respond_to/all_types_with_layout.html.erb", "test/fixtures/respond_to/all_types_with_layout.js.rjs", "test/fixtures/respond_to/custom_constant_handling_without_block.mobile.erb", "test/fixtures/respond_to/iphone_with_html_response_type.html.erb", "test/fixtures/respond_to/iphone_with_html_response_type.iphone.erb", "test/fixtures/respond_to/layouts", "test/fixtures/respond_to/layouts/missing.html.erb", "test/fixtures/respond_to/layouts/standard.html.erb", "test/fixtures/respond_to/layouts/standard.iphone.erb", "test/fixtures/respond_to/using_defaults.html.erb", "test/fixtures/respond_to/using_defaults.js.rjs", "test/fixtures/respond_to/using_defaults.xml.builder", "test/fixtures/respond_to/using_defaults_with_type_list.html.erb", "test/fixtures/respond_to/using_defaults_with_type_list.js.rjs", "test/fixtures/respond_to/using_defaults_with_type_list.xml.builder", "test/fixtures/respond_with", "test/fixtures/respond_with/edit.html.erb", "test/fixtures/respond_with/new.html.erb", "test/fixtures/respond_with/using_defaults.html.erb", "test/fixtures/respond_with/using_defaults.js.rjs", "test/fixtures/respond_with/using_defaults_with_type_list.js.rjs", "test/fixtures/respond_with/using_defaults_with_type_list.xml.builder", "test/fixtures/respond_with/using_resource.js.rjs", "test/fixtures/scope", "test/fixtures/scope/test", "test/fixtures/scope/test/modgreet.erb", "test/fixtures/shared.html.erb", "test/fixtures/symlink_parent", "test/fixtures/symlink_parent/symlinked_layout.erb", "test/fixtures/test", "test/fixtures/test/_counter.html.erb", "test/fixtures/test/_customer.erb", "test/fixtures/test/_customer_counter.erb", "test/fixtures/test/_customer_greeting.erb", "test/fixtures/test/_customer_with_var.erb", "test/fixtures/test/_form.erb", "test/fixtures/test/_hash_greeting.erb", "test/fixtures/test/_hash_object.erb", "test/fixtures/test/_hello.builder", "test/fixtures/test/_labelling_form.erb", "test/fixtures/test/_layout_for_block_with_args.html.erb", "test/fixtures/test/_layout_for_partial.html.erb", "test/fixtures/test/_local_inspector.html.erb", "test/fixtures/test/_one.html.erb", "test/fixtures/test/_partial.erb", "test/fixtures/test/_partial.html.erb", "test/fixtures/test/_partial.js.erb", "test/fixtures/test/_partial_for_use_in_layout.html.erb", "test/fixtures/test/_partial_only.erb", "test/fixtures/test/_partial_with_only_html_version.html.erb", "test/fixtures/test/_person.erb", "test/fixtures/test/_raise.html.erb", "test/fixtures/test/_two.html.erb", "test/fixtures/test/action_talk_to_layout.erb", "test/fixtures/test/basic.html.erb", "test/fixtures/test/calling_partial_with_layout.html.erb", "test/fixtures/test/capturing.erb", "test/fixtures/test/content_for.erb", "test/fixtures/test/content_for_concatenated.erb", "test/fixtures/test/content_for_with_parameter.erb", "test/fixtures/test/delete_with_js.rjs", "test/fixtures/test/dont_pick_me", "test/fixtures/test/dot.directory", "test/fixtures/test/dot.directory/render_file_with_ivar.erb", "test/fixtures/test/enum_rjs_test.rjs", "test/fixtures/test/formatted_html_erb.html.erb", "test/fixtures/test/formatted_xml_erb.builder", "test/fixtures/test/formatted_xml_erb.html.erb", "test/fixtures/test/formatted_xml_erb.xml.erb", "test/fixtures/test/greeting.html.erb", "test/fixtures/test/greeting.js.rjs", "test/fixtures/test/greeting.xml.erb", "test/fixtures/test/hello.builder", "test/fixtures/test/hello_world.da.html.erb", "test/fixtures/test/hello_world.erb", "test/fixtures/test/hello_world.erb~", "test/fixtures/test/hello_world.pt-BR.html.erb", "test/fixtures/test/hello_world_container.builder", "test/fixtures/test/hello_world_from_rxml.builder", "test/fixtures/test/hello_world_with_layout_false.erb", "test/fixtures/test/hello_xml_world.builder", "test/fixtures/test/hyphen-ated.erb", "test/fixtures/test/implicit_content_type.atom.builder", "test/fixtures/test/list.erb", "test/fixtures/test/malformed", "test/fixtures/test/malformed/malformed.en.html.erb~", "test/fixtures/test/malformed/malformed.erb~", "test/fixtures/test/malformed/malformed.html.erb~", "test/fixtures/test/nested_layout.erb", "test/fixtures/test/non_erb_block_content_for.builder", "test/fixtures/test/potential_conflicts.erb", "test/fixtures/test/render_explicit_html_template.js.rjs", "test/fixtures/test/render_file_from_template.html.erb", "test/fixtures/test/render_file_with_ivar.erb", "test/fixtures/test/render_file_with_locals.erb", "test/fixtures/test/render_file_with_locals_and_default.erb", "test/fixtures/test/render_implicit_html_template.js.rjs", "test/fixtures/test/render_implicit_html_template_from_xhr_request.da.html.erb", "test/fixtures/test/render_implicit_html_template_from_xhr_request.html.erb", "test/fixtures/test/render_implicit_js_template_without_layout.js.erb", "test/fixtures/test/render_to_string_test.erb", "test/fixtures/test/sub_template_raise.html.erb", "test/fixtures/test/template.erb", "test/fixtures/test/update_element_with_capture.erb", "test/fixtures/test/using_layout_around_block.html.erb", "test/fixtures/test/utf8.html.erb", "test/fixtures/test/utf8_magic.html.erb", "test/fixtures/topic.rb", "test/fixtures/topics", "test/fixtures/topics/_topic.html.erb", "test/fixtures/topics.yml", "test/html-scanner", "test/html-scanner/cdata_node_test.rb", "test/html-scanner/document_test.rb", "test/html-scanner/node_test.rb", "test/html-scanner/sanitizer_test.rb", "test/html-scanner/tag_node_test.rb", "test/html-scanner/text_node_test.rb", "test/html-scanner/tokenizer_test.rb", "test/javascript", "test/javascript/ajax_test.rb", "test/lib", "test/lib/active_record_unit.rb", "test/lib/controller", "test/lib/controller/fake_controllers.rb", "test/lib/controller/fake_models.rb", "test/lib/fixture_template.rb", "test/lib/testing_sandbox.rb", "test/new_base", "test/new_base/base_test.rb", "test/new_base/content_type_test.rb", "test/new_base/etag_test.rb", "test/new_base/metal_test.rb", "test/new_base/redirect_test.rb", "test/new_base/render_action_test.rb", "test/new_base/render_file_test.rb", "test/new_base/render_implicit_action_test.rb", "test/new_base/render_layout_test.rb", "test/new_base/render_partial_test.rb", "test/new_base/render_rjs_test.rb", "test/new_base/render_template_test.rb", "test/new_base/render_test.rb", "test/new_base/render_text_test.rb", "test/new_base/render_xml_test.rb", "test/new_base/test_helper.rb", "test/old_base", "test/old_base/abstract_unit.rb", "test/runner", "test/template", "test/template/active_record_helper_i18n_test.rb", "test/template/active_record_helper_test.rb", "test/template/asset_tag_helper_test.rb", "test/template/atom_feed_helper_test.rb", "test/template/benchmark_helper_test.rb", "test/template/body_parts_test.rb", "test/template/capture_helper_test.rb", "test/template/compiled_templates_test.rb", "test/template/date_helper_i18n_test.rb", "test/template/date_helper_test.rb", "test/template/erb_util_test.rb", "test/template/form_helper_test.rb", "test/template/form_options_helper_i18n_test.rb", "test/template/form_options_helper_test.rb", "test/template/form_tag_helper_test.rb", "test/template/javascript_helper_test.rb", "test/template/number_helper_i18n_test.rb", "test/template/number_helper_test.rb", "test/template/output_buffer_test.rb", "test/template/prototype_helper_test.rb", "test/template/record_tag_helper_test.rb", "test/template/render_test.rb", "test/template/sanitize_helper_test.rb", "test/template/scriptaculous_helper_test.rb", "test/template/tag_helper_test.rb", "test/template/test_test.rb", "test/template/text_helper_test.rb", "test/template/translation_helper_test.rb", "test/template/url_helper_test.rb", "test/tmp", "test/view", "test/view/test_case_test.rb"] + s.homepage = %q{http://www.rubyonrails.org} + s.require_paths = ["lib"] + s.requirements = ["none"] + s.rubyforge_project = %q{actionpack} + s.rubygems_version = %q{1.3.5} + s.summary = %q{Web-flow and rendering framework putting the VC in MVC.} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 3 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q<activesupport>, ["= 3.0.pre"]) + s.add_runtime_dependency(%q<activemodel>, ["= 3.0.pre"]) + s.add_runtime_dependency(%q<rack>, ["~> 1.0.0"]) + s.add_runtime_dependency(%q<rack-test>, ["~> 0.4.2"]) + else + s.add_dependency(%q<activesupport>, ["= 3.0.pre"]) + s.add_dependency(%q<activemodel>, ["= 3.0.pre"]) + s.add_dependency(%q<rack>, ["~> 1.0.0"]) + s.add_dependency(%q<rack-test>, ["~> 0.4.2"]) + end + else + s.add_dependency(%q<activesupport>, ["= 3.0.pre"]) + s.add_dependency(%q<activemodel>, ["= 3.0.pre"]) + s.add_dependency(%q<rack>, ["~> 1.0.0"]) + s.add_dependency(%q<rack-test>, ["~> 0.4.2"]) + end +end diff --git a/actionpack/lib/abstract_controller.rb b/actionpack/lib/abstract_controller.rb index cdeb55b915..76c5845f5b 100644 --- a/actionpack/lib/abstract_controller.rb +++ b/actionpack/lib/abstract_controller.rb @@ -3,7 +3,6 @@ require "active_support/core_ext/module/delegation" module AbstractController autoload :Base, "abstract_controller/base" - autoload :Benchmarker, "abstract_controller/benchmarker" autoload :Callbacks, "abstract_controller/callbacks" autoload :Helpers, "abstract_controller/helpers" autoload :Layouts, "abstract_controller/layouts" diff --git a/actionpack/lib/abstract_controller/benchmarker.rb b/actionpack/lib/abstract_controller/benchmarker.rb deleted file mode 100644 index 58e9564c2f..0000000000 --- a/actionpack/lib/abstract_controller/benchmarker.rb +++ /dev/null @@ -1,38 +0,0 @@ -module AbstractController - module Benchmarker - extend ActiveSupport::Concern - - include Logger - - module ClassMethods - # Execute the passed in block, timing the duration of the block in ms. - # - # ==== Parameters - # title<#to_s>:: The title of block to benchmark - # log_level<Integer>:: A valid log level. Defaults to Logger::DEBUG - # use_silence<TrueClass, FalseClass>:: Whether or not to silence the - # logger for the duration of the block. - # - # ==== Returns - # Object:: The result of the block - def benchmark(title, log_level = ::Logger::DEBUG, use_silence = true) - if logger && logger.level >= log_level - result = nil - ms = Benchmark.ms { result = use_silence ? silence { yield } : yield } - logger.add(log_level, "#{title} (#{('%.1f' % ms)}ms)") - result - else - yield - end - end - - # Silences the logger for the duration of the block. - def silence - old_logger_level, logger.level = logger.level, ::Logger::ERROR if logger - yield - ensure - logger.level = old_logger_level if logger - end - end - end -end diff --git a/actionpack/lib/abstract_controller/callbacks.rb b/actionpack/lib/abstract_controller/callbacks.rb index ea4b59466e..379eaf6d8e 100644 --- a/actionpack/lib/abstract_controller/callbacks.rb +++ b/actionpack/lib/abstract_controller/callbacks.rb @@ -10,7 +10,7 @@ module AbstractController include ActiveSupport::NewCallbacks included do - define_callbacks :process_action, "response_body" + define_callbacks :process_action, :terminator => "response_body" end # Override AbstractController::Base's process_action to run the diff --git a/actionpack/lib/abstract_controller/layouts.rb b/actionpack/lib/abstract_controller/layouts.rb index ef66b24dd6..796ef40584 100644 --- a/actionpack/lib/abstract_controller/layouts.rb +++ b/actionpack/lib/abstract_controller/layouts.rb @@ -119,17 +119,17 @@ module AbstractController when true raise ArgumentError, "Layouts must be specified as a String, Symbol, false, or nil" when nil - self.class_eval <<-ruby_eval, __FILE__, __LINE__ + 1 + self.class_eval <<-RUBY, __FILE__, __LINE__ + 1 def _layout(details) self.class.cache_layout(details) do - if view_paths.exists?("#{_implied_layout_name}", details, "layouts") + if template_exists?("#{_implied_layout_name}", details, :_prefix => "layouts") "#{_implied_layout_name}" else super end end end - ruby_eval + RUBY end self.class_eval { private :_layout } end @@ -167,7 +167,7 @@ module AbstractController # details<Hash{Symbol => Object}>:: A list of details to restrict # the lookup to. By default, layout lookup is limited to the # formats specified for the current request. - def _layout_for_name(name, details = {:formats => formats}) + def _layout_for_name(name, details) name && _find_layout(name, details) end @@ -183,7 +183,7 @@ module AbstractController def _find_layout(name, details) # TODO: Make prefix actually part of details in ViewPath#find_by_parts prefix = details.key?(:prefix) ? details.delete(:prefix) : "layouts" - view_paths.find(name, details, prefix) + find_template(name, details, :_prefix => prefix) end # Returns the default layout for this controller and a given set of details. diff --git a/actionpack/lib/abstract_controller/logger.rb b/actionpack/lib/abstract_controller/logger.rb index 1b879b963b..f4d017b8e5 100644 --- a/actionpack/lib/abstract_controller/logger.rb +++ b/actionpack/lib/abstract_controller/logger.rb @@ -4,6 +4,26 @@ module AbstractController module Logger extend ActiveSupport::Concern + included do + cattr_accessor :logger + end + + module ClassMethods #:nodoc: + # Logs a message appending the value measured. + def log_with_time(message, time, log_level=::Logger::DEBUG) + return unless logger && logger.level >= log_level + logger.add(log_level, "#{message} (%.1fms)" % time) + end + + # Silences the logger for the duration of the block. + def silence + old_logger_level, logger.level = logger.level, ::Logger::ERROR if logge + yield + ensure + logger.level = old_logger_level if logger + end + end + # A class that allows you to defer expensive processing # until the logger actually tries to log. Otherwise, you are # forced to do the processing in advance, and send the @@ -11,43 +31,44 @@ module AbstractController # just discard the String if the log level is too low. # # TODO: Require that Rails loggers accept a block. - class DelayedLog - def initialize(&blk) - @blk = blk + class DelayedLog < ActiveSupport::BasicObject + def initialize(&block) + @str, @block = nil, block end - def to_s - @blk.call + def method_missing(*args, &block) + unless @str + @str, @block = @block.call, nil + end + @str.send(*args, &block) end - alias to_str to_s - end - - included do - cattr_accessor :logger end # Override process_action in the AbstractController::Base # to log details about the method. def process_action(action) - retval = super + event = ActiveSupport::Orchestra.instrument(:process_action, + :controller => self, :action => action) do + super + end if logger log = DelayedLog.new do "\n\nProcessing #{self.class.name}\##{action_name} " \ - "to #{request.formats} " \ - "(for #{request_origin}) [#{request.method.to_s.upcase}]" + "to #{request.formats} (for #{request_origin}) " \ + "(%.1fms) [#{request.method.to_s.upcase}]" % event.duration end logger.info(log) end - retval + event.result end private + # Returns the request origin with the IP and time. This needs to be cached, + # otherwise we would get different results for each time it calls. def request_origin - # this *needs* to be cached! - # otherwise you'd get different results if calling it more than once @request_origin ||= "#{request.remote_ip} at #{Time.now.to_s(:db)}" end end diff --git a/actionpack/lib/abstract_controller/rendering_controller.rb b/actionpack/lib/abstract_controller/rendering_controller.rb index feca1bc4b7..bbf941aa32 100644 --- a/actionpack/lib/abstract_controller/rendering_controller.rb +++ b/actionpack/lib/abstract_controller/rendering_controller.rb @@ -112,12 +112,18 @@ module AbstractController name = (options[:_template_name] || action_name).to_s options[:_template] ||= with_template_cache(name) do - view_paths.find( - name, { :formats => formats }, options[:_prefix], options[:_partial] - ) + find_template(name, { :formats => formats }, options) end end - + + def find_template(name, details, options) + view_paths.find(name, details, options[:_prefix], options[:_partial]) + end + + def template_exists?(name, details, options) + view_paths.exists?(name, details, options[:_prefix], options[:_partial]) + end + def with_template_cache(name) yield end diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 698189bd46..f5bd0a00a1 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -2,7 +2,6 @@ module ActionController class Base < Metal abstract! - include AbstractController::Benchmarker include AbstractController::Callbacks include AbstractController::Logger @@ -51,7 +50,7 @@ module ActionController def method_for_action(action_name) super || begin - if view_paths.exists?(action_name.to_s, {:formats => formats, :locales => [I18n.locale]}, controller_path) + if template_exists?(action_name.to_s, {:formats => formats}, :_prefix => controller_path) "default_render" end end diff --git a/actionpack/lib/action_controller/caching/fragments.rb b/actionpack/lib/action_controller/caching/fragments.rb index 4ef600bea0..59e24619e3 100644 --- a/actionpack/lib/action_controller/caching/fragments.rb +++ b/actionpack/lib/action_controller/caching/fragments.rb @@ -53,11 +53,11 @@ module ActionController #:nodoc: return content unless cache_configured? key = fragment_cache_key(key) - - self.class.benchmark "Cached fragment miss: #{key}" do + event = ActiveSupport::Orchestra.instrument(:write_fragment, :key => key) do cache_store.write(key, content, options) end + self.class.log_with_time("Cached fragment miss: #{key}", event.duration) content end @@ -66,10 +66,12 @@ module ActionController #:nodoc: return unless cache_configured? key = fragment_cache_key(key) - - self.class.benchmark "Cached fragment hit: #{key}" do + event = ActiveSupport::Orchestra.instrument(:read_fragment, :key => key) do cache_store.read(key, options) end + + self.class.log_with_time("Cached fragment hit: #{key}", event.duration) + event.result end # Check if a cached fragment from the location signified by <tt>key</tt> exists (see <tt>expire_fragment</tt> for acceptable formats) @@ -77,10 +79,12 @@ module ActionController #:nodoc: return unless cache_configured? key = fragment_cache_key(key) - - self.class.benchmark "Cached fragment exists?: #{key}" do + event = ActiveSupport::Orchestra.instrument(:fragment_exist?, :key => key) do cache_store.exist?(key, options) end + + self.class.log_with_time("Cached fragment exists?: #{key}", event.duration) + event.result end # Removes fragments from the cache. @@ -103,17 +107,21 @@ module ActionController #:nodoc: def expire_fragment(key, options = nil) return unless cache_configured? - key = key.is_a?(Regexp) ? key : fragment_cache_key(key) + key = fragment_cache_key(key) unless key.is_a?(Regexp) + message = nil - if key.is_a?(Regexp) - self.class.benchmark "Expired fragments matching: #{key.source}" do + event = ActiveSupport::Orchestra.instrument(:expire_fragment, :key => key) do + if key.is_a?(Regexp) + message = "Expired fragments matching: #{key.source}" cache_store.delete_matched(key, options) - end - else - self.class.benchmark "Expired fragment: #{key}" do + else + message = "Expired fragment: #{key}" cache_store.delete(key, options) end end + + self.class.log_with_time(message, event.duration) + event.result end end end diff --git a/actionpack/lib/action_controller/caching/pages.rb b/actionpack/lib/action_controller/caching/pages.rb index bd3b5a5875..4fb154470f 100644 --- a/actionpack/lib/action_controller/caching/pages.rb +++ b/actionpack/lib/action_controller/caching/pages.rb @@ -62,21 +62,29 @@ module ActionController #:nodoc: # expire_page "/lists/show" def expire_page(path) return unless perform_caching + path = page_cache_path(path) - benchmark "Expired page: #{page_cache_file(path)}" do - File.delete(page_cache_path(path)) if File.exist?(page_cache_path(path)) + event = ActiveSupport::Orchestra.instrument(:expire_page, :path => path) do + File.delete(path) if File.exist?(path) end + + log_with_time("Expired page: #{path}", event.duration) + event.result end # Manually cache the +content+ in the key determined by +path+. Example: # cache_page "I'm the cached content", "/lists/show" def cache_page(content, path) return unless perform_caching + path = page_cache_path(path) - benchmark "Cached page: #{page_cache_file(path)}" do - FileUtils.makedirs(File.dirname(page_cache_path(path))) - File.open(page_cache_path(path), "wb+") { |f| f.write(content) } + event = ActiveSupport::Orchestra.instrument(:cache_page, :path => path) do + FileUtils.makedirs(File.dirname(path)) + File.open(path, "wb+") { |f| f.write(content) } end + + log_with_time("Cached page: #{path}", event.duration) + event.result end # Caches the +actions+ using the page-caching approach that'll store the cache in a path within the page_cache_directory that @@ -149,4 +157,4 @@ module ActionController #:nodoc: end end end -end
\ No newline at end of file +end diff --git a/actionpack/lib/action_controller/dispatch/dispatcher.rb b/actionpack/lib/action_controller/dispatch/dispatcher.rb index 9ad1cadfd3..ba316b9e63 100644 --- a/actionpack/lib/action_controller/dispatch/dispatcher.rb +++ b/actionpack/lib/action_controller/dispatch/dispatcher.rb @@ -54,7 +54,7 @@ module ActionController end end - delegate :to_prepare, :prepare_dispatch, :before_dispatch, :after_dispatch, + delegate :to_prepare, :before_dispatch, :around_dispatch, :after_dispatch, :to => ActionDispatch::Callbacks def new diff --git a/actionpack/lib/action_controller/dispatch/middlewares.rb b/actionpack/lib/action_controller/dispatch/middlewares.rb index b25ed3fd3f..5641b3cb8d 100644 --- a/actionpack/lib/action_controller/dispatch/middlewares.rb +++ b/actionpack/lib/action_controller/dispatch/middlewares.rb @@ -4,15 +4,13 @@ use "Rack::Lock", :if => lambda { use "ActionDispatch::ShowExceptions", lambda { ActionController::Base.consider_all_requests_local } use "ActionDispatch::Callbacks", lambda { ActionController::Dispatcher.prepare_each_request } -use "ActionDispatch::Rescue", lambda { - controller = (::ApplicationController rescue ActionController::Base) - # TODO: Replace with controller.action(:_rescue_action) - controller.method(:rescue_action) -} + +# TODO: Redirect global exceptions somewhere? +# use "ActionDispatch::Rescue" use lambda { ActionController::Base.session_store }, lambda { ActionController::Base.session_options } use "ActionDispatch::ParamsParser" use "Rack::MethodOverride" -use "Rack::Head"
\ No newline at end of file +use "Rack::Head" diff --git a/actionpack/lib/action_controller/legacy/layout.rb b/actionpack/lib/action_controller/legacy/layout.rb index 43aea0eba2..53762158fc 100644 --- a/actionpack/lib/action_controller/legacy/layout.rb +++ b/actionpack/lib/action_controller/legacy/layout.rb @@ -191,7 +191,7 @@ module ActionController #:nodoc: def memoized_find_layout(layout, formats) #:nodoc: return layout if layout.nil? || layout.respond_to?(:render) prefix = layout.to_s =~ /layouts\// ? nil : "layouts" - view_paths.find(layout.to_s, {:formats => formats}, prefix) + find_template(layout.to_s, {:formats => formats}, :_prefix => prefix) end def find_layout(*args) @@ -200,7 +200,7 @@ module ActionController #:nodoc: end def layout_list #:nodoc: - Array(view_paths).sum([]) { |path| Dir["#{path.to_str}/layouts/**/*"] } + Array(view_paths).sum([]) { |path| Dir["#{path}/layouts/**/*"] } end memoize :layout_list diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb index 51fbba3661..e9007d3631 100644 --- a/actionpack/lib/action_controller/metal.rb +++ b/actionpack/lib/action_controller/metal.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/class/inheritable_attributes' + module ActionController # ActionController::Metal provides a way to get a valid Rack application from a controller. # @@ -79,6 +81,15 @@ module ActionController end class ActionEndpoint + @@endpoints = Hash.new {|h,k| h[k] = Hash.new {|h,k| h[k] = {} } } + + def self.for(controller, action, stack) + @@endpoints[controller][action][stack] ||= begin + endpoint = new(controller, action) + stack.build(endpoint) + end + end + def initialize(controller, action) @controller, @action = controller, action end @@ -88,6 +99,16 @@ module ActionController end end + extlib_inheritable_accessor(:middleware_stack) { ActionDispatch::MiddlewareStack.new } + + def self.use(*args) + middleware_stack.use(*args) + end + + def self.middleware + middleware_stack + end + # Return a rack endpoint for the given action. Memoize the endpoint, so # multiple calls into MyController.action will return the same object # for the same action. @@ -98,8 +119,7 @@ module ActionController # ==== Returns # Proc:: A rack application def self.action(name) - @actions ||= {} - @actions[name.to_s] ||= ActionEndpoint.new(self, name) + ActionEndpoint.for(self, name, middleware_stack) end end end diff --git a/actionpack/lib/action_controller/metal/filter_parameter_logging.rb b/actionpack/lib/action_controller/metal/filter_parameter_logging.rb index 065e62a37f..4259d9de19 100644 --- a/actionpack/lib/action_controller/metal/filter_parameter_logging.rb +++ b/actionpack/lib/action_controller/metal/filter_parameter_logging.rb @@ -49,7 +49,7 @@ module ActionController end elsif block_given? key = key.dup - value = value.dup if value + value = value.dup if value.duplicable? yield key, value filtered_parameters[key] = value else diff --git a/actionpack/lib/action_controller/metal/rescuable.rb b/actionpack/lib/action_controller/metal/rescuable.rb index 029e643d93..bbca1b2179 100644 --- a/actionpack/lib/action_controller/metal/rescuable.rb +++ b/actionpack/lib/action_controller/metal/rescuable.rb @@ -1,52 +1,13 @@ module ActionController #:nodoc: - # Actions that fail to perform as expected throw exceptions. These - # exceptions can either be rescued for the public view (with a nice - # user-friendly explanation) or for the developers view (with tons of - # debugging information). The developers view is already implemented by - # the Action Controller, but the public view should be tailored to your - # specific application. - # - # The default behavior for public exceptions is to render a static html - # file with the name of the error code thrown. If no such file exists, an - # empty response is sent with the correct status code. - # - # You can override what constitutes a local request by overriding the - # <tt>local_request?</tt> method in your own controller. Custom rescue - # behavior is achieved by overriding the <tt>rescue_action_in_public</tt> - # and <tt>rescue_action_locally</tt> methods. module Rescue extend ActiveSupport::Concern - - included do - include ActiveSupport::Rescuable - end - - module ClassMethods - # This can be removed once we can move action(:_rescue_action) into middlewares.rb - # Currently, it does controller.method(:rescue_action), which is hiding the implementation - # difference between the old and new base. - def rescue_action(env) - action(:_rescue_action).call(env) - end - end - - attr_internal :rescued_exception + include ActiveSupport::Rescuable private - def method_for_action(action_name) - return action_name if self.rescued_exception = request.env.delete("action_dispatch.rescue.exception") - super - end - - def _rescue_action - rescue_with_handler(rescued_exception) || raise(rescued_exception) - end - - def process_action(*) + def process_action(*args) super rescue Exception => exception - self.rescued_exception = exception - _rescue_action + rescue_with_handler(exception) || raise(exception) end end end diff --git a/actionpack/lib/action_controller/testing/integration.rb b/actionpack/lib/action_controller/testing/integration.rb index fb82f866fe..791f936f51 100644 --- a/actionpack/lib/action_controller/testing/integration.rb +++ b/actionpack/lib/action_controller/testing/integration.rb @@ -2,9 +2,7 @@ require 'stringio' require 'uri' require 'active_support/test_case' require 'active_support/core_ext/object/metaclass' - -require 'rack/mock_session' -require 'rack/test/cookie_jar' +require 'rack/test' module ActionController module Integration #:nodoc: @@ -251,7 +249,7 @@ module ActionController end end - opts = { + env = { :method => method, :params => parameters, @@ -261,25 +259,24 @@ module ActionController "rack.url_scheme" => https? ? "https" : "http", "REQUEST_URI" => path, - "PATH_INFO" => path, "HTTP_HOST" => host, "REMOTE_ADDR" => remote_addr, "CONTENT_TYPE" => "application/x-www-form-urlencoded", "HTTP_ACCEPT" => accept } - env = ActionDispatch::TestRequest.env_for(path, opts) - (rack_environment || {}).each do |key, value| env[key] = value end + session = Rack::Test::Session.new(@mock_session) + @controller = ActionController::Base.capture_instantiation do - @mock_session.request(URI.parse(path), env) + session.request(path, env) end @request_count += 1 - @request = ActionDispatch::Request.new(env) + @request = ActionDispatch::Request.new(session.last_request.env) @response = ActionDispatch::TestResponse.from_response(@mock_session.last_response) @html_document = nil diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb index a58b2de379..2fccf01040 100644 --- a/actionpack/lib/action_controller/testing/process.rb +++ b/actionpack/lib/action_controller/testing/process.rb @@ -84,7 +84,7 @@ module ActionController #:nodoc: # # Pass a true third parameter to ensure the uploaded file is opened in binary mode (only required for Windows): # post :change_avatar, :avatar => ActionController::TestUploadedFile.new(ActionController::TestCase.fixture_path + '/files/spongebob.png', 'image/png', :binary) - TestUploadedFile = ActionDispatch::TestRequest::Multipart::UploadedFile + TestUploadedFile = Rack::Test::UploadedFile module TestProcess def self.included(base) @@ -133,7 +133,7 @@ module ActionController #:nodoc: @request.env['REQUEST_METHOD'] = http_method parameters ||= {} - @request.assign_parameters(@controller.class.controller_path, action.to_s, parameters) + @request.assign_parameters(@controller.class.name.underscore.sub(/_controller$/, ''), action.to_s, parameters) @request.session = ActionController::TestSession.new(session) unless session.nil? @request.session["flash"] = ActionController::Flash::FlashHash.new.update(flash) if flash diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index 849f268a8c..5bcd2143a3 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -21,10 +21,6 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #++ -activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib" -$:.unshift activesupport_path if File.directory?(activesupport_path) -require 'active_support' - require 'rack' module Rack @@ -59,3 +55,7 @@ module ActionDispatch end autoload :Mime, 'action_dispatch/http/mime_type' + +activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib" +$:.unshift activesupport_path if File.directory?(activesupport_path) +require 'active_support' diff --git a/actionpack/lib/action_dispatch/middleware/callbacks.rb b/actionpack/lib/action_dispatch/middleware/callbacks.rb index 0a2b4cf5f7..2f86a382c2 100644 --- a/actionpack/lib/action_dispatch/middleware/callbacks.rb +++ b/actionpack/lib/action_dispatch/middleware/callbacks.rb @@ -1,40 +1,55 @@ module ActionDispatch class Callbacks - include ActiveSupport::Callbacks - define_callbacks :prepare, :before, :after + include ActiveSupport::NewCallbacks + + define_callbacks :call, :terminator => "result == false", :scope => :kind + define_callbacks :prepare, :scope => :name + + # Add a preparation callback. Preparation callbacks are run before every + # request in development mode, and before the first request in production mode. + # + # If a symbol with a block is given, the symbol is used as an identifier. + # That allows to_prepare to be called again with the same identifier to + # replace the existing callback. Passing an identifier is a suggested + # practice if the code adding a preparation block may be reloaded. + def self.to_prepare(*args, &block) + if args.first.is_a?(Symbol) && block_given? + define_method :"__#{args.first}", &block + set_callback(:prepare, :"__#{args.first}") + else + set_callback(:prepare, *args, &block) + end + end + + def self.before(*args, &block) + set_callback(:call, :before, *args, &block) + end + + def self.around(*args, &block) + set_callback(:call, :around, *args, &block) + end + + def self.after(*args, &block) + set_callback(:call, :after, *args, &block) + end class << self # DEPRECATED - alias_method :prepare_dispatch, :prepare alias_method :before_dispatch, :before + alias_method :around_dispatch, :around alias_method :after_dispatch, :after end - # Add a preparation callback. Preparation callbacks are run before every - # request in development mode, and before the first request in production - # mode. - # - # An optional identifier may be supplied for the callback. If provided, - # to_prepare may be called again with the same identifier to replace the - # existing callback. Passing an identifier is a suggested practice if the - # code adding a preparation block may be reloaded. - def self.to_prepare(identifier = nil, &block) - @prepare_callbacks ||= ActiveSupport::Callbacks::CallbackChain.new - callback = ActiveSupport::Callbacks::Callback.new(:prepare, block, :identifier => identifier) - @prepare_callbacks.replace_or_append!(callback) - end - def initialize(app, prepare_each_request = false) @app, @prepare_each_request = app, prepare_each_request - run_callbacks :prepare + _run_prepare_callbacks end def call(env) - run_callbacks :before - run_callbacks :prepare if @prepare_each_request - @app.call(env) - ensure - run_callbacks :after, :enumerator => :reverse_each + _run_call_callbacks do + _run_prepare_callbacks if @prepare_each_request + @app.call(env) + end end end end diff --git a/actionpack/lib/action_dispatch/middleware/rescue.rb b/actionpack/lib/action_dispatch/middleware/rescue.rb index 1456825526..aee672112c 100644 --- a/actionpack/lib/action_dispatch/middleware/rescue.rb +++ b/actionpack/lib/action_dispatch/middleware/rescue.rb @@ -1,14 +1,26 @@ module ActionDispatch class Rescue - def initialize(app, rescuer) - @app, @rescuer = app, rescuer + def initialize(app, rescuers = {}, &block) + @app, @rescuers = app, {} + rescuers.each { |exception, rescuer| rescue_from(exception, rescuer) } + instance_eval(&block) if block_given? end def call(env) @app.call(env) rescue Exception => exception - env['action_dispatch.rescue.exception'] = exception - @rescuer.call(env) + if rescuer = @rescuers[exception.class.name] + env['action_dispatch.rescue.exception'] = exception + rescuer.call(env) + else + raise exception + end end + + protected + def rescue_from(exception, rescuer) + exception = exception.class.name if exception.is_a?(Exception) + @rescuers[exception.to_s] = rescuer + end end end diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb index 9cfd6956d0..bd552b458a 100644 --- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb @@ -49,7 +49,18 @@ module ActionDispatch :expire_after => nil, :httponly => true }.freeze + + class OptionsHash < Hash + def initialize(by, env, default_options) + @session_data = env[CookieStore::ENV_SESSION_KEY] + default_options.each { |key, value| self[key] = value } + end + def [](key) + key == :id ? @session_data[:session_id] : super(key) + end + end + ENV_SESSION_KEY = "rack.session".freeze ENV_SESSION_OPTIONS_KEY = "rack.session.options".freeze HTTP_SET_COOKIE = "Set-Cookie".freeze @@ -90,8 +101,8 @@ module ActionDispatch def call(env) env[ENV_SESSION_KEY] = AbstractStore::SessionHash.new(self, env) - env[ENV_SESSION_OPTIONS_KEY] = @default_options.dup - + env[ENV_SESSION_OPTIONS_KEY] = OptionsHash.new(self, env, @default_options) + status, headers, body = @app.call(env) session_data = env[ENV_SESSION_KEY] diff --git a/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb b/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb index 1d9efc2b36..be1d5a43a2 100644 --- a/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb @@ -1,52 +1,47 @@ -require "active_support/core_ext/kernel/requires" -begin - require_library_or_gem 'memcache' +module ActionDispatch + module Session + class MemCacheStore < AbstractStore + def initialize(app, options = {}) + require 'memcache' - module ActionDispatch - module Session - class MemCacheStore < AbstractStore - def initialize(app, options = {}) - # Support old :expires option - options[:expire_after] ||= options[:expires] + # Support old :expires option + options[:expire_after] ||= options[:expires] - super + super - @default_options = { - :namespace => 'rack:session', - :memcache_server => 'localhost:11211' - }.merge(@default_options) + @default_options = { + :namespace => 'rack:session', + :memcache_server => 'localhost:11211' + }.merge(@default_options) - @pool = options[:cache] || MemCache.new(@default_options[:memcache_server], @default_options) - unless @pool.servers.any? { |s| s.alive? } - raise "#{self} unable to find server during initialization." - end - @mutex = Mutex.new - - super + @pool = options[:cache] || MemCache.new(@default_options[:memcache_server], @default_options) + unless @pool.servers.any? { |s| s.alive? } + raise "#{self} unable to find server during initialization." end + @mutex = Mutex.new - private - def get_session(env, sid) - sid ||= generate_sid - begin - session = @pool.get(sid) || {} - rescue MemCache::MemCacheError, Errno::ECONNREFUSED - session = {} - end - [sid, session] - end + super + end - def set_session(env, sid, session_data) - options = env['rack.session.options'] - expiry = options[:expire_after] || 0 - @pool.set(sid, session_data, expiry) - return true + private + def get_session(env, sid) + sid ||= generate_sid + begin + session = @pool.get(sid) || {} rescue MemCache::MemCacheError, Errno::ECONNREFUSED - return false + session = {} end - end + [sid, session] + end + + def set_session(env, sid, session_data) + options = env['rack.session.options'] + expiry = options[:expire_after] || 0 + @pool.set(sid, session_data, expiry) + return true + rescue MemCache::MemCacheError, Errno::ECONNREFUSED + return false + end end end -rescue LoadError - # MemCache wasn't available so neither can the store be end diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb index bb2d8375bd..f8f6b424ca 100644 --- a/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb @@ -15,12 +15,12 @@ show = "document.getElementById('#{name.gsub /\s/, '-'}').style.display='block';" hide = (names - [name]).collect {|hide_name| "document.getElementById('#{hide_name.gsub /\s/, '-'}').style.display='none';"} %> - <a href="#" onclick="<%= hide %><%= show %>; return false;"><%= name %></a> <%= '|' unless names.last == name %> + <a href="#" onclick="<%= hide.join %><%= show %>; return false;"><%= name %></a> <%= '|' unless names.last == name %> <% end %> <% traces.each do |name, trace| %> <div id="<%= name.gsub /\s/, '-' %>" style="display: <%= name == "Application Trace" ? 'block' : 'none' %>;"> - <pre><code><%= trace.join "\n" %></code></pre> + <pre><code><%=h trace.join "\n" %></code></pre> </div> <% end %> </div> diff --git a/actionpack/lib/action_dispatch/testing/test_request.rb b/actionpack/lib/action_dispatch/testing/test_request.rb index 8242ea4ef6..20288aa7a5 100644 --- a/actionpack/lib/action_dispatch/testing/test_request.rb +++ b/actionpack/lib/action_dispatch/testing/test_request.rb @@ -1,308 +1,13 @@ module ActionDispatch class TestRequest < Request - # Improve version of Multipart thats in rack/master - module Multipart #:nodoc: - class UploadedFile - # The filename, *not* including the path, of the "uploaded" file - attr_reader :original_filename - - # The content type of the "uploaded" file - attr_accessor :content_type - - def initialize(path, content_type = "text/plain", binary = false) - raise "#{path} file does not exist" unless ::File.exist?(path) - @content_type = content_type - @original_filename = ::File.basename(path) - @tempfile = Tempfile.new(@original_filename) - @tempfile.set_encoding(Encoding::BINARY) if @tempfile.respond_to?(:set_encoding) - @tempfile.binmode if binary - FileUtils.copy_file(path, @tempfile.path) - end - - def path - @tempfile.path - end - alias_method :local_path, :path - - def method_missing(method_name, *args, &block) #:nodoc: - @tempfile.__send__(method_name, *args, &block) - end - end - - EOL = "\r\n" - MULTIPART_BOUNDARY = "AaB03x" - - def self.parse_multipart(env) - unless env['CONTENT_TYPE'] =~ - %r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|n - nil - else - boundary = "--#{$1}" - - params = {} - buf = "" - content_length = env['CONTENT_LENGTH'].to_i - input = env['rack.input'] - input.rewind - - boundary_size = Utils.bytesize(boundary) + EOL.size - bufsize = 16384 - - content_length -= boundary_size - - read_buffer = '' - - status = input.read(boundary_size, read_buffer) - raise EOFError, "bad content body" unless status == boundary + EOL - - rx = /(?:#{EOL})?#{Regexp.quote boundary}(#{EOL}|--)/n - - loop { - head = nil - body = '' - filename = content_type = name = nil - - until head && buf =~ rx - if !head && i = buf.index(EOL+EOL) - head = buf.slice!(0, i+2) # First \r\n - buf.slice!(0, 2) # Second \r\n - - filename = head[/Content-Disposition:.* filename="?([^\";]*)"?/ni, 1] - content_type = head[/Content-Type: (.*)#{EOL}/ni, 1] - name = head[/Content-Disposition:.*\s+name="?([^\";]*)"?/ni, 1] || head[/Content-ID:\s*([^#{EOL}]*)/ni, 1] - - if content_type || filename - body = Tempfile.new("RackMultipart") - body.binmode if body.respond_to?(:binmode) - end - - next - end - - # Save the read body part. - if head && (boundary_size+4 < buf.size) - body << buf.slice!(0, buf.size - (boundary_size+4)) - end - - c = input.read(bufsize < content_length ? bufsize : content_length, read_buffer) - raise EOFError, "bad content body" if c.nil? || c.empty? - buf << c - content_length -= c.size - end - - # Save the rest. - if i = buf.index(rx) - body << buf.slice!(0, i) - buf.slice!(0, boundary_size+2) - - content_length = -1 if $1 == "--" - end - - if filename == "" - # filename is blank which means no file has been selected - data = nil - elsif filename - body.rewind - - # Take the basename of the upload's original filename. - # This handles the full Windows paths given by Internet Explorer - # (and perhaps other broken user agents) without affecting - # those which give the lone filename. - filename =~ /^(?:.*[:\\\/])?(.*)/m - filename = $1 - - data = {:filename => filename, :type => content_type, - :name => name, :tempfile => body, :head => head} - elsif !filename && content_type - body.rewind - - # Generic multipart cases, not coming from a form - data = {:type => content_type, - :name => name, :tempfile => body, :head => head} - else - data = body - end - - Utils.normalize_params(params, name, data) unless data.nil? - - break if buf.empty? || content_length == -1 - } - - input.rewind - - params - end - end - - def self.build_multipart(params, first = true) - if first - unless params.is_a?(Hash) - raise ArgumentError, "value must be a Hash" - end - - multipart = false - query = lambda { |value| - case value - when Array - value.each(&query) - when Hash - value.values.each(&query) - when UploadedFile - multipart = true - end - } - params.values.each(&query) - return nil unless multipart - end - - flattened_params = Hash.new - - params.each do |key, value| - k = first ? key.to_s : "[#{key}]" - - case value - when Array - value.map { |v| - build_multipart(v, false).each { |subkey, subvalue| - flattened_params["#{k}[]#{subkey}"] = subvalue - } - } - when Hash - build_multipart(value, false).each { |subkey, subvalue| - flattened_params[k + subkey] = subvalue - } - else - flattened_params[k] = value - end - end - - if first - flattened_params.map { |name, file| - if file.respond_to?(:original_filename) - ::File.open(file.path, "rb") do |f| - f.set_encoding(Encoding::BINARY) if f.respond_to?(:set_encoding) -<<-EOF ---#{MULTIPART_BOUNDARY}\r -Content-Disposition: form-data; name="#{name}"; filename="#{Rack::Utils.escape(file.original_filename)}"\r -Content-Type: #{file.content_type}\r -Content-Length: #{::File.stat(file.path).size}\r -\r -#{f.read}\r -EOF - end - else -<<-EOF ---#{MULTIPART_BOUNDARY}\r -Content-Disposition: form-data; name="#{name}"\r -\r -#{file}\r -EOF - end - }.join + "--#{MULTIPART_BOUNDARY}--\r" - else - flattened_params - end - end - end - - DEFAULT_ENV = { - "rack.version" => [1,0], - "rack.input" => StringIO.new, - "rack.errors" => StringIO.new, - "rack.multithread" => true, - "rack.multiprocess" => true, - "rack.run_once" => false, - } - - # Improve version of env_for thats in rack/master - def self.env_for(uri="", opts={}) #:nodoc: - uri = URI(uri) - uri.path = "/#{uri.path}" unless uri.path[0] == ?/ - - env = DEFAULT_ENV.dup - - env["REQUEST_METHOD"] = opts[:method] ? opts[:method].to_s.upcase : "GET" - env["SERVER_NAME"] = uri.host || "example.org" - env["SERVER_PORT"] = uri.port ? uri.port.to_s : "80" - env["QUERY_STRING"] = uri.query.to_s - env["PATH_INFO"] = (!uri.path || uri.path.empty?) ? "/" : uri.path - env["rack.url_scheme"] = uri.scheme || "http" - env["HTTPS"] = env["rack.url_scheme"] == "https" ? "on" : "off" - - env["SCRIPT_NAME"] = opts[:script_name] || "" - - if opts[:fatal] - env["rack.errors"] = FatalWarner.new - else - env["rack.errors"] = StringIO.new - end - - if params = opts[:params] - if env["REQUEST_METHOD"] == "GET" - params = Rack::Utils.parse_nested_query(params) if params.is_a?(String) - params.update(Rack::Utils.parse_nested_query(env["QUERY_STRING"])) - env["QUERY_STRING"] = build_nested_query(params) - elsif !opts.has_key?(:input) - opts["CONTENT_TYPE"] = "application/x-www-form-urlencoded" - if params.is_a?(Hash) - if data = Multipart.build_multipart(params) - opts[:input] = data - opts["CONTENT_LENGTH"] ||= data.length.to_s - opts["CONTENT_TYPE"] = "multipart/form-data; boundary=#{Multipart::MULTIPART_BOUNDARY}" - else - opts[:input] = build_nested_query(params) - end - else - opts[:input] = params - end - end - end - - empty_str = "" - empty_str.force_encoding("ASCII-8BIT") if empty_str.respond_to? :force_encoding - opts[:input] ||= empty_str - if String === opts[:input] - rack_input = StringIO.new(opts[:input]) - else - rack_input = opts[:input] - end - - rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding) - env['rack.input'] = rack_input - - env["CONTENT_LENGTH"] ||= env["rack.input"].length.to_s - - opts.each { |field, value| - env[field] = value if String === field - } - - env - end - - def self.build_nested_query(value, prefix = nil) - case value - when Array - value.map { |v| - build_nested_query(v, "#{prefix}[]") - }.join("&") - when Hash - value.map { |k, v| - build_nested_query(v, prefix ? "#{prefix}[#{Rack::Utils.escape(k)}]" : Rack::Utils.escape(k)) - }.join("&") - when String - raise ArgumentError, "value must be a Hash" if prefix.nil? - "#{prefix}=#{Rack::Utils.escape(value)}" - else - prefix - end - end + DEFAULT_ENV = Rack::MockRequest.env_for('/') def self.new(env = {}) super end def initialize(env = {}) - super(self.class.env_for('/').merge(env)) + super(DEFAULT_ENV.merge(env)) self.host = 'test.host' self.remote_addr = '0.0.0.0' diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index 70176a0ea4..3df4f2d6a3 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -21,11 +21,6 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #++ -activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib" -$:.unshift activesupport_path if File.directory?(activesupport_path) -require 'active_support' -require 'active_support/core_ext/class/attribute_accessors' - require File.join(File.dirname(__FILE__), "action_pack") module ActionView @@ -36,14 +31,12 @@ module ActionView autoload :Base, 'action_view/base' autoload :Context, 'action_view/context' autoload :Helpers, 'action_view/helpers' - autoload :InlineTemplate, 'action_view/template/inline' autoload :MissingTemplate, 'action_view/base' autoload :Partials, 'action_view/render/partials' autoload :Resolver, 'action_view/template/resolver' + autoload :PathResolver, 'action_view/template/resolver' autoload :PathSet, 'action_view/paths' autoload :Rendering, 'action_view/render/rendering' - autoload :Renderable, 'action_view/template/renderable' - autoload :RenderablePartial, 'action_view/template/partial' autoload :Template, 'action_view/template/template' autoload :TemplateError, 'action_view/template/error' autoload :TemplateHandler, 'action_view/template/handler' @@ -58,3 +51,8 @@ class ERB end I18n.load_path << "#{File.dirname(__FILE__)}/action_view/locale/en.yml" + +activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib" +$:.unshift activesupport_path if File.directory?(activesupport_path) +require 'active_support' +require 'active_support/core_ext/class/attribute_accessors' diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb index c71840d41f..95f00cda39 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb @@ -1,3 +1,4 @@ +require 'thread' require 'cgi' require 'action_view/helpers/url_helper' require 'action_view/helpers/tag_helper' @@ -286,7 +287,9 @@ module ActionView end javascript_src_tag(joined_javascript_name, options) else - ensure_javascript_sources!(expand_javascript_sources(sources, recursive)).collect { |source| javascript_src_tag(source, options) }.join("\n") + sources = expand_javascript_sources(sources, recursive) + ensure_javascript_sources!(sources) if cache + sources.collect { |source| javascript_src_tag(source, options) }.join("\n") end end @@ -435,7 +438,9 @@ module ActionView end stylesheet_tag(joined_stylesheet_name, options) else - ensure_stylesheet_sources!(expand_stylesheet_sources(sources, recursive)).collect { |source| stylesheet_tag(source, options) }.join("\n") + sources = expand_stylesheet_sources(sources, recursive) + ensure_stylesheet_sources!(sources) if cache + sources.collect { |source| stylesheet_tag(source, options) }.join("\n") end end diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 81029102b1..32b9c4a7dd 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -449,6 +449,15 @@ module ActionView # <% end %> # <% end %> # + # Or a collection to be used: + # + # <% form_for @person, :url => { :action => "update" } do |person_form| %> + # ... + # <% person_form.fields_for :projects, @active_projects do |project_fields| %> + # Name: <%= project_fields.text_field :name %> + # <% end %> + # <% end %> + # # When projects is already an association on Person you can use # +accepts_nested_attributes_for+ to define the writer method for you: # @@ -1037,18 +1046,21 @@ module ActionView def fields_for_with_nested_attributes(association_name, args, block) name = "#{object_name}[#{association_name}_attributes]" - association = @object.send(association_name) - explicit_object = args.first.to_model if args.first.respond_to?(:to_model) + association = args.first.to_model if args.first.respond_to?(:to_model) + + if association.respond_to?(:new_record?) + association = [association] if @object.send(association_name).is_a?(Array) + elsif !association.is_a?(Array) + association = @object.send(association_name) + end if association.is_a?(Array) - children = explicit_object ? [explicit_object] : association explicit_child_index = args.last[:child_index] if args.last.is_a?(Hash) - - children.map do |child| + association.map do |child| fields_for_nested_model("#{name}[#{explicit_child_index || nested_child_index(name)}]", child, args, block) end.join - else - fields_for_nested_model(name, explicit_object || association, args, block) + elsif association + fields_for_nested_model(name, association, args, block) end end diff --git a/actionpack/lib/action_view/helpers/tag_helper.rb b/actionpack/lib/action_view/helpers/tag_helper.rb index ff5a2134ff..7fae0f6b8d 100644 --- a/actionpack/lib/action_view/helpers/tag_helper.rb +++ b/actionpack/lib/action_view/helpers/tag_helper.rb @@ -106,7 +106,7 @@ module ActionView # escape_once("<< Accept & Checkout") # # => "<< Accept & Checkout" def escape_once(html) - html.to_s.gsub(/[\"><]|&(?!([a-zA-Z]+|(#\d+));)/) { |special| ERB::Util::HTML_ESCAPE[special] } + ActiveSupport::Multibyte.clean(html.to_s).gsub(/[\"><]|&(?!([a-zA-Z]+|(#\d+));)/) { |special| ERB::Util::HTML_ESCAPE[special] } end private diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb index b07304e361..204d4d71e1 100644 --- a/actionpack/lib/action_view/helpers/url_helper.rb +++ b/actionpack/lib/action_view/helpers/url_helper.rb @@ -1,4 +1,5 @@ require 'action_view/helpers/javascript_helper' +require 'active_support/core_ext/array/access' require 'active_support/core_ext/hash/keys' module ActionView diff --git a/actionpack/lib/action_view/template/handlers/builder.rb b/actionpack/lib/action_view/template/handlers/builder.rb index 5f381f7bf0..ba0d17b5af 100644 --- a/actionpack/lib/action_view/template/handlers/builder.rb +++ b/actionpack/lib/action_view/template/handlers/builder.rb @@ -6,7 +6,7 @@ module ActionView self.default_format = Mime::XML def compile(template) - require 'builder' + require 'active_support/vendor/builder' "xml = ::Builder::XmlMarkup.new(:indent => 2);" + "self.output_buffer = xml.target!;" + template.source + diff --git a/actionpack/lib/action_view/template/inline.rb b/actionpack/lib/action_view/template/inline.rb deleted file mode 100644 index 54efa543c8..0000000000 --- a/actionpack/lib/action_view/template/inline.rb +++ /dev/null @@ -1,19 +0,0 @@ -module ActionView #:nodoc: - class InlineTemplate #:nodoc: - include Renderable - - attr_reader :source, :extension, :method_segment - - def initialize(source, type = nil) - @source = source - @extension = type - @method_segment = "inline_#{@source.hash.abs}" - end - - private - # Always recompile inline templates - def recompile? - true - end - end -end diff --git a/actionpack/lib/action_view/template/partial.rb b/actionpack/lib/action_view/template/partial.rb deleted file mode 100644 index 30dec1dc5b..0000000000 --- a/actionpack/lib/action_view/template/partial.rb +++ /dev/null @@ -1,18 +0,0 @@ -module ActionView - # NOTE: The template that this mixin is being included into is frozen - # so you cannot set or modify any instance variables - module RenderablePartial #:nodoc: - extend ActiveSupport::Memoizable - - def variable_name - name.sub(/\A_/, '').to_sym - end - memoize :variable_name - - def counter_name - "#{variable_name}_counter".to_sym - end - memoize :counter_name - - end -end diff --git a/actionpack/lib/action_view/template/renderable.rb b/actionpack/lib/action_view/template/renderable.rb deleted file mode 100644 index 7687578165..0000000000 --- a/actionpack/lib/action_view/template/renderable.rb +++ /dev/null @@ -1,93 +0,0 @@ -# encoding: utf-8 - -module ActionView - # NOTE: The template that this mixin is being included into is frozen - # so you cannot set or modify any instance variables - module Renderable #:nodoc: - extend ActiveSupport::Memoizable - - def render(view, locals) - compile(locals) - view.send(method_name(locals), locals) {|*args| yield(*args) } - end - - def load! - names = CompiledTemplates.instance_methods.grep(/#{method_name_without_locals}/) - names.each do |name| - CompiledTemplates.class_eval do - remove_method(name) - end - end - super - end - - private - - def filename - 'compiled-template' - end - - def handler - Template.handler_class_for_extension(extension) - end - memoize :handler - - def compiled_source - handler.call(self) - end - memoize :compiled_source - - def method_name_without_locals - ['_run', extension, method_segment].compact.join('_') - end - memoize :method_name_without_locals - - def method_name(local_assigns) - if local_assigns && local_assigns.any? - method_name = method_name_without_locals.dup - method_name << "_locals_#{local_assigns.keys.map { |k| k.to_s }.sort.join('_')}" - else - method_name = method_name_without_locals - end - method_name.to_sym - end - - # Compile and evaluate the template's code (if necessary) - def compile(local_assigns) - render_symbol = method_name(local_assigns) - - if !CompiledTemplates.method_defined?(render_symbol) || recompile? - compile!(render_symbol, local_assigns) - end - end - - private - def compile!(render_symbol, local_assigns) - locals_code = local_assigns.keys.map { |key| "#{key} = local_assigns[:#{key}];" }.join - - source = <<-end_src - def #{render_symbol}(local_assigns) - old_output_buffer = output_buffer;#{locals_code};#{compiled_source} - ensure - self.output_buffer = old_output_buffer - end - end_src - - begin - ActionView::CompiledTemplates.module_eval(source, filename.to_s, 0) - rescue Exception => e # errors from template code - if logger = defined?(ActionController) && Base.logger - logger.debug "ERROR: compiling #{render_symbol} RAISED #{e}" - logger.debug "Function body: #{source}" - logger.debug "Backtrace: #{e.backtrace.join("\n")}" - end - - raise ActionView::TemplateError.new(self, {}, e) - end - end - - def recompile? - false - end - end -end diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb index 0b4c62d4d0..f5591ead09 100644 --- a/actionpack/lib/action_view/template/resolver.rb +++ b/actionpack/lib/action_view/template/resolver.rb @@ -1,9 +1,28 @@ require "pathname" +require "active_support/core_ext/class" require "action_view/template/template" module ActionView # Abstract superclass class Resolver + + class_inheritable_accessor(:registered_details) + self.registered_details = {} + + def self.register_detail(name, options = {}) + registered_details[name] = lambda do |val| + val ||= yield + val |= [nil] unless options[:allow_nil] == false + val + end + end + + register_detail(:locale) { [I18n.locale] } + register_detail(:formats) { Mime::SET.symbols } + register_detail(:handlers, :allow_nil => false) do + TemplateHandlers.extensions + end + def initialize(options = {}) @cache = options[:cache] @cached = {} @@ -11,15 +30,18 @@ module ActionView # Normalizes the arguments and passes it on to find_template def find(*args) - find_all_by_parts(*args).first + find_all(*args).first end - - def find_all_by_parts(name, details = {}, prefix = nil, partial = nil) - details[:locales] = [I18n.locale] - name = name.to_s.gsub(handler_matcher, '').split("/") - find_templates(name.pop, details, [prefix, *name].compact.join("/"), partial) + + def find_all(name, details = {}, prefix = nil, partial = nil) + details = normalize_details(details) + name, prefix = normalize_name(name, prefix) + + cached([name, details, prefix, partial]) do + find_templates(name, details, prefix, partial) + end end - + private # This is what child classes implement. No defaults are needed @@ -28,29 +50,26 @@ module ActionView def find_templates(name, details, prefix, partial) raise NotImplementedError end - - def valid_handlers - @valid_handlers ||= TemplateHandlers.extensions - end - def handler_matcher - @handler_matcher ||= begin - e = valid_handlers.join('|') - /\.(?:#{e})$/ + def normalize_details(details) + details = details.dup + # TODO: Refactor this concern out of the resolver + details.delete(:formats) if details[:formats] == [:"*/*"] + registered_details.each do |k, v| + details[k] = v.call(details[k]) end + details end - def handler_glob - @handler_glob ||= begin - e = TemplateHandlers.extensions.map{|h| ".#{h}"}.join(",") - "{#{e}}" - end - end - - def formats_glob - @formats_glob ||= begin - '{' + Mime::SET.symbols.map { |l| ".#{l}," }.join + '}' - end + # Support legacy foo.erb names even though we now ignore .erb + # as well as incorrectly putting part of the path in the template + # name instead of the prefix. + def normalize_name(name, prefix) + handlers = TemplateHandlers.extensions.join('|') + name = name.to_s.gsub(/\.(?:#{handlers})$/, '') + + parts = name.split('/') + return parts.pop, [prefix, *parts].compact.join("/") end def cached(key) @@ -60,80 +79,49 @@ module ActionView end end - class FileSystemResolver < Resolver - - def self.cached_glob - @@cached_glob ||= {} - end - - def initialize(path, options = {}) - raise ArgumentError, "path already is a Resolver class" if path.is_a?(Resolver) - super(options) - @path = Pathname.new(path).expand_path - end + class PathResolver < Resolver - # TODO: This is the currently needed API. Make this suck less - # ==== <suck> - attr_reader :path + EXTENSION_ORDER = [:locale, :formats, :handlers] def to_s - path.to_s + @path.to_s end + alias to_path to_s - def to_str - path.to_s + def find_templates(name, details, prefix, partial) + path = build_path(name, details, prefix, partial) + query(path, EXTENSION_ORDER.map { |ext| details[ext] }) end - def ==(path) - to_str == path.to_str - end + private - def eql?(path) - to_str == path.to_str + def build_path(name, details, prefix, partial) + path = "" + path << "#{prefix}/" unless prefix.empty? + path << (partial ? "_#{name}" : name) + path end - # ==== </suck> - - def find_templates(name, details, prefix, partial, root = "#{@path}/") - if glob = details_to_glob(name, details, prefix, partial, root) - cached(glob) do - Dir[glob].map do |path| - next if File.directory?(path) - source = File.read(path) - identifier = Pathname.new(path).expand_path.to_s - Template.new(source, identifier, *path_to_details(path)) - end.compact - end + def query(path, exts) + query = "#{@path}/#{path}" + exts.each do |ext| + query << '{' << ext.map {|e| e && ".#{e}" }.join(',') << '}' end - end - - private - # :api: plugin - def details_to_glob(name, details, prefix, partial, root) - self.class.cached_glob[[name, prefix, partial, details, root]] ||= begin - path = "" - path << "#{prefix}/" unless prefix.empty? - path << (partial ? "_#{name}" : name) - - extensions = "" - [:locales, :formats].each do |k| - extensions << if exts = details[k] - '{' + exts.map {|e| ".#{e},"}.join + '}' - else - k == :formats ? formats_glob : '' - end - end - - "#{root}#{path}#{extensions}#{handler_glob}" - end + Dir[query].map do |path| + next if File.directory?(path) + source = File.read(path) + identifier = Pathname.new(path).expand_path.to_s + + Template.new(source, identifier, *path_to_details(path)) + end.compact end - # TODO: fix me - # :api: plugin + # # TODO: fix me + # # :api: plugin def path_to_details(path) # [:erb, :format => :html, :locale => :en, :partial => true/false] - if m = path.match(%r'/(_)?[\w-]+(\.[\w-]+)*\.(\w+)$') + if m = path.match(%r'(?:^|/)(_)?[\w-]+(\.[\w-]+)*\.(\w+)$') partial = m[1] == '_' details = (m[2]||"").split('.').reject { |e| e.empty? } handler = Template.handler_class_for_extension(m[3]) @@ -146,13 +134,32 @@ module ActionView end end - class FileSystemResolverWithFallback < FileSystemResolver + class FileSystemResolver < PathResolver + def initialize(path, options = {}) + raise ArgumentError, "path already is a Resolver class" if path.is_a?(Resolver) + super(options) + @path = Pathname.new(path).expand_path + end + end - def find_templates(name, details, prefix, partial) - templates = super - return super(name, details, prefix, partial, '') if templates.empty? - templates + # OMG HAX + # TODO: remove hax + class FileSystemResolverWithFallback < Resolver + def initialize(path, options = {}) + super(options) + @paths = [FileSystemResolver.new(path, options), FileSystemResolver.new("", options), FileSystemResolver.new("/", options)] end + def find_templates(*args) + @paths.each do |p| + template = p.find_templates(*args) + return template unless template.empty? + end + [] + end + + def to_s + @paths.first.to_s + end end end
\ No newline at end of file diff --git a/actionpack/lib/action_view/template/template.rb b/actionpack/lib/action_view/template/template.rb index 7d6964e3e3..80c1bab7d5 100644 --- a/actionpack/lib/action_view/template/template.rb +++ b/actionpack/lib/action_view/template/template.rb @@ -27,8 +27,10 @@ module ActionView end def render(view, locals, &block) - method_name = compile(locals, view) - view.send(method_name, locals, &block) + ActiveSupport::Orchestra.instrument(:render_template, :identifier => identifier) do + method_name = compile(locals, view) + view.send(method_name, locals, &block) + end.result rescue Exception => e if e.is_a?(TemplateError) e.sub_template_of(self) diff --git a/actionpack/lib/actionpack.rb b/actionpack/lib/actionpack.rb deleted file mode 100644 index 2fe2832f81..0000000000 --- a/actionpack/lib/actionpack.rb +++ /dev/null @@ -1 +0,0 @@ -require 'action_pack' diff --git a/actionpack/test/abstract_controller/abstract_controller_test.rb b/actionpack/test/abstract/abstract_controller_test.rb index 7991436703..524381509d 100644 --- a/actionpack/test/abstract_controller/abstract_controller_test.rb +++ b/actionpack/test/abstract/abstract_controller_test.rb @@ -1,4 +1,4 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper") +require 'abstract_unit' module AbstractController module Testing @@ -148,10 +148,10 @@ module AbstractController private def self.layout(formats) begin - view_paths.find(name.underscore, {:formats => formats}, "layouts") + find_template(name.underscore, {:formats => formats}, :_prefix => "layouts") rescue ActionView::MissingTemplate begin - view_paths.find("application", {:formats => formats}, "layouts") + find_template("application", {:formats => formats}, :_prefix => "layouts") rescue ActionView::MissingTemplate end end diff --git a/actionpack/test/abstract_controller/callbacks_test.rb b/actionpack/test/abstract/callbacks_test.rb index 8f62adce8c..0ce1dc506b 100644 --- a/actionpack/test/abstract_controller/callbacks_test.rb +++ b/actionpack/test/abstract/callbacks_test.rb @@ -1,4 +1,4 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper") +require 'abstract_unit' module AbstractController module Testing @@ -235,4 +235,4 @@ module AbstractController end end -end
\ No newline at end of file +end diff --git a/actionpack/test/abstract_controller/helper_test.rb b/actionpack/test/abstract/helper_test.rb index 34a10cecc9..5a363c9aa5 100644 --- a/actionpack/test/abstract_controller/helper_test.rb +++ b/actionpack/test/abstract/helper_test.rb @@ -1,4 +1,4 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper") +require 'abstract_unit' module AbstractController module Testing diff --git a/actionpack/test/abstract_controller/layouts_test.rb b/actionpack/test/abstract/layouts_test.rb index 995aac7fad..453d31826e 100644 --- a/actionpack/test/abstract_controller/layouts_test.rb +++ b/actionpack/test/abstract/layouts_test.rb @@ -1,4 +1,4 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper") +require 'abstract_unit' require 'active_support/core_ext/class/removal' module AbstractControllerTests diff --git a/actionpack/test/abstract_controller/views/abstract_controller/testing/me3/formatted.html.erb b/actionpack/test/abstract/views/abstract_controller/testing/me3/formatted.html.erb index 785bf69191..785bf69191 100644 --- a/actionpack/test/abstract_controller/views/abstract_controller/testing/me3/formatted.html.erb +++ b/actionpack/test/abstract/views/abstract_controller/testing/me3/formatted.html.erb diff --git a/actionpack/test/abstract_controller/views/abstract_controller/testing/me3/index.erb b/actionpack/test/abstract/views/abstract_controller/testing/me3/index.erb index f079ad8204..f079ad8204 100644 --- a/actionpack/test/abstract_controller/views/abstract_controller/testing/me3/index.erb +++ b/actionpack/test/abstract/views/abstract_controller/testing/me3/index.erb diff --git a/actionpack/test/abstract_controller/views/abstract_controller/testing/me4/index.erb b/actionpack/test/abstract/views/abstract_controller/testing/me4/index.erb index 89dce12bdc..89dce12bdc 100644 --- a/actionpack/test/abstract_controller/views/abstract_controller/testing/me4/index.erb +++ b/actionpack/test/abstract/views/abstract_controller/testing/me4/index.erb diff --git a/actionpack/test/abstract_controller/views/abstract_controller/testing/me5/index.erb b/actionpack/test/abstract/views/abstract_controller/testing/me5/index.erb index 84d0b7417e..84d0b7417e 100644 --- a/actionpack/test/abstract_controller/views/abstract_controller/testing/me5/index.erb +++ b/actionpack/test/abstract/views/abstract_controller/testing/me5/index.erb diff --git a/actionpack/test/abstract_controller/views/action_with_ivars.erb b/actionpack/test/abstract/views/action_with_ivars.erb index 8d8ae22fd7..8d8ae22fd7 100644 --- a/actionpack/test/abstract_controller/views/action_with_ivars.erb +++ b/actionpack/test/abstract/views/action_with_ivars.erb diff --git a/actionpack/test/abstract_controller/views/helper_test.erb b/actionpack/test/abstract/views/helper_test.erb index 8ae45cc195..8ae45cc195 100644 --- a/actionpack/test/abstract_controller/views/helper_test.erb +++ b/actionpack/test/abstract/views/helper_test.erb diff --git a/actionpack/test/abstract_controller/views/index.erb b/actionpack/test/abstract/views/index.erb index cc1a8b8c85..cc1a8b8c85 100644 --- a/actionpack/test/abstract_controller/views/index.erb +++ b/actionpack/test/abstract/views/index.erb diff --git a/actionpack/test/abstract_controller/views/layouts/abstract_controller/testing/me4.erb b/actionpack/test/abstract/views/layouts/abstract_controller/testing/me4.erb index 172dd56569..172dd56569 100644 --- a/actionpack/test/abstract_controller/views/layouts/abstract_controller/testing/me4.erb +++ b/actionpack/test/abstract/views/layouts/abstract_controller/testing/me4.erb diff --git a/actionpack/test/abstract_controller/views/layouts/application.erb b/actionpack/test/abstract/views/layouts/application.erb index 27317140ad..27317140ad 100644 --- a/actionpack/test/abstract_controller/views/layouts/application.erb +++ b/actionpack/test/abstract/views/layouts/application.erb diff --git a/actionpack/test/abstract_controller/views/naked_render.erb b/actionpack/test/abstract/views/naked_render.erb index 1b3d03878b..1b3d03878b 100644 --- a/actionpack/test/abstract_controller/views/naked_render.erb +++ b/actionpack/test/abstract/views/naked_render.erb diff --git a/actionpack/test/abstract_controller/test_helper.rb b/actionpack/test/abstract_controller/test_helper.rb deleted file mode 100644 index ba4302d914..0000000000 --- a/actionpack/test/abstract_controller/test_helper.rb +++ /dev/null @@ -1,21 +0,0 @@ -$:.unshift(File.dirname(__FILE__) + '/../../lib') -$:.unshift(File.dirname(__FILE__) + '/../../../activesupport/lib') -$:.unshift(File.dirname(__FILE__) + '/../lib') - -require 'rubygems' -require 'test/unit' -require 'active_support' -require 'active_support/test_case' -require 'abstract_controller' -require 'action_view' -require 'action_view/base' -require 'action_dispatch' -require 'fixture_template' - -begin - require 'ruby-debug' - Debugger.settings[:autoeval] = true - Debugger.start -rescue LoadError - # Debugging disabled. `gem install ruby-debug` to enable. -end diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index 07ba37c51c..b9293ffb9f 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -1,29 +1,36 @@ $:.unshift(File.dirname(__FILE__) + '/../lib') $:.unshift(File.dirname(__FILE__) + '/../../activesupport/lib') $:.unshift(File.dirname(__FILE__) + '/../../activemodel/lib') -$:.unshift(File.dirname(__FILE__) + '/lib') +$:.unshift(File.dirname(__FILE__) + '/lib') $:.unshift(File.dirname(__FILE__) + '/fixtures/helpers') $:.unshift(File.dirname(__FILE__) + '/fixtures/alternate_helpers') -ENV['TMPDIR'] = File.join(File.dirname(__FILE__), 'tmp') +bundler = File.join(File.dirname(__FILE__), '..', 'vendor', 'gems', 'environment') +require bundler if File.exist?("#{bundler}.rb") -ENV['new_base'] = "true" -$stderr.puts "Running old tests on new_base" +begin + %w( rack rack/test sqlite3 ).each { |lib| require lib } +rescue LoadError => e + abort e.message +end + +ENV['TMPDIR'] = File.join(File.dirname(__FILE__), 'tmp') require 'test/unit' require 'active_support' - require 'active_support/test_case' +require 'abstract_controller' require 'action_controller' +require 'action_view' +require 'action_view/base' +require 'action_dispatch' +require 'active_model' require 'fixture_template' require 'action_controller/testing/process' -require 'action_view/test_case' require 'action_controller/testing/integration' +require 'action_view/test_case' require 'active_support/dependencies' -require 'active_model' - -$tags[:new_base] = true begin require 'ruby-debug' @@ -33,6 +40,8 @@ rescue LoadError # Debugging disabled. `gem install ruby-debug` to enable. end +require 'pp' # require 'pp' early to prevent hidden_methods from not picking up the pretty-print methods until too late + ActiveSupport::Dependencies.hook! # Show backtraces for deprecated behavior for quicker cleanup. @@ -55,6 +64,61 @@ module ActionView end end +# Temporary base class +class Rack::TestCase < ActionController::IntegrationTest + setup do + ActionController::Base.session_options[:key] = "abc" + ActionController::Base.session_options[:secret] = ("*" * 30) + end + + def app + @app ||= ActionController::Dispatcher.new + end + + def self.testing(klass = nil) + if klass + @testing = "/#{klass.name.underscore}".sub!(/_controller$/, '') + else + @testing + end + end + + def get(thing, *args) + if thing.is_a?(Symbol) + super("#{self.class.testing}/#{thing}", *args) + else + super + end + end + + def assert_body(body) + assert_equal body, Array.wrap(response.body).join + end + + def assert_status(code) + assert_equal code, response.status + end + + def assert_response(body, status = 200, headers = {}) + assert_body body + assert_status status + headers.each do |header, value| + assert_header header, value + end + end + + def assert_content_type(type) + assert_equal type, response.headers["Content-Type"] + end + + def assert_header(name, value) + assert_equal value, response.headers[name] + end +end + +class ::ApplicationController < ActionController::Base +end + module ActionController Base.session = { :key => '_testing_session', @@ -131,3 +195,11 @@ module ActionController end end end + +class SimpleRouteCase < Rack::TestCase + setup do + ActionController::Routing::Routes.draw do |map| + map.connect ':controller/:action/:id' + end + end +end diff --git a/actionpack/test/lib/active_record_unit.rb b/actionpack/test/active_record_unit.rb index 1ba308e9d7..9e0c66055d 100644 --- a/actionpack/test/lib/active_record_unit.rb +++ b/actionpack/test/active_record_unit.rb @@ -16,7 +16,7 @@ if defined?(ActiveRecord) && defined?(Fixtures) else $stderr.print 'Attempting to load Active Record... ' begin - PATH_TO_AR = "#{File.dirname(__FILE__)}/../../../activerecord/lib" + PATH_TO_AR = "#{File.dirname(__FILE__)}/../../activerecord/lib" raise LoadError, "#{PATH_TO_AR} doesn't exist" unless File.directory?(PATH_TO_AR) $LOAD_PATH.unshift PATH_TO_AR require 'active_record' @@ -72,13 +72,13 @@ class ActiveRecordTestConnector # Load actionpack sqlite tables def load_schema - File.read(File.dirname(__FILE__) + "/../fixtures/db_definitions/sqlite.sql").split(';').each do |sql| + File.read(File.dirname(__FILE__) + "/fixtures/db_definitions/sqlite.sql").split(';').each do |sql| ActiveRecord::Base.connection.execute(sql) unless sql.blank? end end def require_fixture_models - Dir.glob(File.dirname(__FILE__) + "/../fixtures/*.rb").each {|f| require f} + Dir.glob(File.dirname(__FILE__) + "/fixtures/*.rb").each {|f| require f} end end end diff --git a/actionpack/test/activerecord/active_record_store_test.rb b/actionpack/test/activerecord/active_record_store_test.rb index a46ce7a0aa..19d9c955a5 100644 --- a/actionpack/test/activerecord/active_record_store_test.rb +++ b/actionpack/test/activerecord/active_record_store_test.rb @@ -176,6 +176,7 @@ class ActiveRecordStoreTest < ActionController::IntegrationTest c.connect "/:action" end end + reset_app! yield end end diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb index 453812c128..901cb940ea 100644 --- a/actionpack/test/controller/action_pack_assertions_test.rb +++ b/actionpack/test/controller/action_pack_assertions_test.rb @@ -1,5 +1,6 @@ require 'abstract_unit' require 'action_controller/vendor/html-scanner' +require 'controller/fake_controllers' # a controller class to facilitate the tests class ActionPackAssertionsController < ActionController::Base diff --git a/actionpack/test/controller/addresses_render_test.rb b/actionpack/test/controller/addresses_render_test.rb index 2d2a2745b0..c1cd22113d 100644 --- a/actionpack/test/controller/addresses_render_test.rb +++ b/actionpack/test/controller/addresses_render_test.rb @@ -1,5 +1,6 @@ require 'abstract_unit' require 'logger' +require 'controller/fake_controllers' class Address def Address.count(conditions = nil, join = nil) @@ -15,13 +16,8 @@ class Address end end -class AddressesTestController < ActionController::Base - def self.controller_name; "addresses"; end - def self.controller_path; "addresses"; end -end - class AddressesTest < ActionController::TestCase - tests AddressesTestController + tests AddressesController def setup super diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb index 82c790bc19..bd17df73c7 100644 --- a/actionpack/test/controller/caching_test.rb +++ b/actionpack/test/controller/caching_test.rb @@ -441,8 +441,8 @@ class ActionCacheTest < ActionController::TestCase def test_correct_content_type_is_returned_for_cache_hit # run it twice to cache it the first time - get :index, :id => 'content-type.xml' - get :index, :id => 'content-type.xml' + get :index, :id => 'content-type', :format => 'xml' + get :index, :id => 'content-type', :format => 'xml' assert_equal 'application/xml', @response.content_type end @@ -625,15 +625,20 @@ class FragmentCachingTest < ActionController::TestCase def test_fragment_for_logging fragment_computed = false - @controller.class.expects(:benchmark).with('Cached fragment exists?: views/expensive') - @controller.class.expects(:benchmark).with('Cached fragment miss: views/expensive') - @controller.class.expects(:benchmark).with('Cached fragment hit: views/expensive').never + listener = [] + ActiveSupport::Orchestra.register listener buffer = 'generated till now -> ' @controller.fragment_for(buffer, 'expensive') { fragment_computed = true } + assert_equal 2, listener.size + assert_equal :fragment_exist?, listener[0].name + assert_equal :write_fragment, listener[1].name + assert fragment_computed assert_equal 'generated till now -> ', buffer + ensure + ActiveSupport::Orchestra.unregister listener end end diff --git a/actionpack/test/controller/content_type_test.rb b/actionpack/test/controller/content_type_test.rb index c249788c67..e5ffe20ecc 100644 --- a/actionpack/test/controller/content_type_test.rb +++ b/actionpack/test/controller/content_type_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' -class ContentTypeController < ActionController::Base +class OldContentTypeController < ActionController::Base # :ported: def render_content_type_from_body response.content_type = Mime::RSS @@ -56,7 +56,7 @@ class ContentTypeController < ActionController::Base end class ContentTypeTest < ActionController::TestCase - tests ContentTypeController + tests OldContentTypeController def setup super @@ -73,11 +73,11 @@ class ContentTypeTest < ActionController::TestCase end def test_render_changed_charset_default - ContentTypeController.default_charset = "utf-16" + OldContentTypeController.default_charset = "utf-16" get :render_defaults assert_equal "utf-16", @response.charset assert_equal Mime::HTML, @response.content_type - ContentTypeController.default_charset = "utf-8" + OldContentTypeController.default_charset = "utf-8" end # :ported: @@ -109,12 +109,12 @@ class ContentTypeTest < ActionController::TestCase end def test_nil_default_for_rhtml - ContentTypeController.default_charset = nil + OldContentTypeController.default_charset = nil get :render_default_for_rhtml assert_equal Mime::HTML, @response.content_type assert_nil @response.charset, @response.headers.inspect ensure - ContentTypeController.default_charset = "utf-8" + OldContentTypeController.default_charset = "utf-8" end def test_default_for_rhtml @@ -143,8 +143,7 @@ class ContentTypeTest < ActionController::TestCase end class AcceptBasedContentTypeTest < ActionController::TestCase - - tests ContentTypeController + tests OldContentTypeController def setup super diff --git a/actionpack/test/controller/dispatcher_test.rb b/actionpack/test/controller/dispatcher_test.rb index 9fae1fcf63..150fc83cde 100644 --- a/actionpack/test/controller/dispatcher_test.rb +++ b/actionpack/test/controller/dispatcher_test.rb @@ -3,13 +3,16 @@ require 'abstract_unit' class DispatcherTest < Test::Unit::TestCase Dispatcher = ActionController::Dispatcher + class Foo + cattr_accessor :a, :b + end + def setup ENV['REQUEST_METHOD'] = 'GET' # Clear callbacks as they are redefined by Dispatcher#define_dispatcher_callbacks - ActionDispatch::Callbacks.instance_variable_set("@prepare_callbacks", ActiveSupport::Callbacks::CallbackChain.new) - ActionDispatch::Callbacks.instance_variable_set("@before_callbacks", ActiveSupport::Callbacks::CallbackChain.new) - ActionDispatch::Callbacks.instance_variable_set("@after_callbacks", ActiveSupport::Callbacks::CallbackChain.new) + ActionDispatch::Callbacks.reset_callbacks(:prepare) + ActionDispatch::Callbacks.reset_callbacks(:call) @old_router, Dispatcher.router = Dispatcher.router, mock() Dispatcher.router.stubs(:call).returns([200, {}, 'response']) @@ -68,13 +71,12 @@ class DispatcherTest < Test::Unit::TestCase end def test_to_prepare_with_identifier_replaces - a = b = nil - Dispatcher.to_prepare(:unique_id) { |*args| a = b = 1 } - Dispatcher.to_prepare(:unique_id) { |*args| a = 2 } + Dispatcher.to_prepare(:unique_id) { |*args| Foo.a, Foo.b = 1, 1 } + Dispatcher.to_prepare(:unique_id) { |*args| Foo.a = 2 } dispatch - assert_equal 2, a - assert_equal nil, b + assert_equal 2, Foo.a + assert_equal nil, Foo.b end private diff --git a/actionpack/test/controller/filter_params_test.rb b/actionpack/test/controller/filter_params_test.rb index f7864745eb..19232c6bc9 100644 --- a/actionpack/test/controller/filter_params_test.rb +++ b/actionpack/test/controller/filter_params_test.rb @@ -35,6 +35,7 @@ class FilterParamTest < ActionController::TestCase test_hashes = [[{},{},[]], [{'foo'=>nil},{'foo'=>nil},[]], [{'foo'=>'bar'},{'foo'=>'bar'},[]], + [{'foo'=>1},{'foo'=>1},[]], [{'foo'=>'bar'},{'foo'=>'bar'},%w'food'], [{'foo'=>'bar'},{'foo'=>'[FILTERED]'},%w'foo'], [{'foo'=>'bar', 'bar'=>'foo'},{'foo'=>'[FILTERED]', 'bar'=>'foo'},%w'foo baz'], diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb index 197ba0c69c..9f56bbfd46 100644 --- a/actionpack/test/controller/integration_test.rb +++ b/actionpack/test/controller/integration_test.rb @@ -371,12 +371,13 @@ class IntegrationProcessTest < ActionController::IntegrationTest c.connect "/:action" end end + reset! yield end end end -class MetalTest < ActionController::IntegrationTest +class MetalIntegrationTest < ActionController::IntegrationTest class Poller def self.call(env) if env["PATH_INFO"] =~ /^\/success/ diff --git a/actionpack/test/controller/render_js_test.rb b/actionpack/test/controller/render_js_test.rb index bc850de733..491c98a0fd 100644 --- a/actionpack/test/controller/render_js_test.rb +++ b/actionpack/test/controller/render_js_test.rb @@ -2,23 +2,27 @@ require 'abstract_unit' require 'controller/fake_models' require 'pathname' -class TestController < ActionController::Base - protect_from_forgery +class RenderJSTest < ActionController::TestCase + class TestController < ActionController::Base + protect_from_forgery - def render_vanilla_js_hello - render :js => "alert('hello')" - end - - def greeting - # let's just rely on the template + def self.controller_path + 'test' + end + + def render_vanilla_js_hello + render :js => "alert('hello')" + end + + def greeting + # let's just rely on the template + end + + def show_partial + render :partial => 'partial' + end end - - def show_partial - render :partial => 'partial' - end -end -class RenderTest < ActionController::TestCase tests TestController def test_render_vanilla_js @@ -26,14 +30,14 @@ class RenderTest < ActionController::TestCase assert_equal "alert('hello')", @response.body assert_equal "text/javascript", @response.content_type end - + def test_render_with_default_from_accept_header xhr :get, :greeting assert_equal "$(\"body\").visualEffect(\"highlight\");", @response.body end - + def test_should_render_js_partial xhr :get, :show_partial, :format => 'js' assert_equal 'partial js', @response.body end -end
\ No newline at end of file +end diff --git a/actionpack/test/controller/render_json_test.rb b/actionpack/test/controller/render_json_test.rb index 233b2dfd89..3938fc7061 100644 --- a/actionpack/test/controller/render_json_test.rb +++ b/actionpack/test/controller/render_json_test.rb @@ -2,35 +2,39 @@ require 'abstract_unit' require 'controller/fake_models' require 'pathname' -class TestController < ActionController::Base - protect_from_forgery - - def render_json_nil - render :json => nil - end +class RenderJsonTest < ActionController::TestCase + class TestController < ActionController::Base + protect_from_forgery - def render_json_hello_world - render :json => ActiveSupport::JSON.encode(:hello => 'world') - end + def self.controller_path + 'test' + end - def render_json_hello_world_with_callback - render :json => ActiveSupport::JSON.encode(:hello => 'world'), :callback => 'alert' - end + def render_json_nil + render :json => nil + end - def render_json_with_custom_content_type - render :json => ActiveSupport::JSON.encode(:hello => 'world'), :content_type => 'text/javascript' - end + def render_json_hello_world + render :json => ActiveSupport::JSON.encode(:hello => 'world') + end - def render_symbol_json - render :json => ActiveSupport::JSON.encode(:hello => 'world') - end + def render_json_hello_world_with_callback + render :json => ActiveSupport::JSON.encode(:hello => 'world'), :callback => 'alert' + end - def render_json_with_render_to_string - render :json => {:hello => render_to_string(:partial => 'partial')} - end -end + def render_json_with_custom_content_type + render :json => ActiveSupport::JSON.encode(:hello => 'world'), :content_type => 'text/javascript' + end + + def render_symbol_json + render :json => ActiveSupport::JSON.encode(:hello => 'world') + end + + def render_json_with_render_to_string + render :json => {:hello => render_to_string(:partial => 'partial')} + end + end -class RenderTest < ActionController::TestCase tests TestController def setup @@ -40,8 +44,8 @@ class RenderTest < ActionController::TestCase @controller.logger = Logger.new(nil) @request.host = "www.nextangle.com" - end - + end + def test_render_json_nil get :render_json_nil assert_equal 'null', @response.body @@ -76,5 +80,5 @@ class RenderTest < ActionController::TestCase get :render_json_with_render_to_string assert_equal '{"hello":"partial html"}', @response.body assert_equal 'application/json', @response.content_type - end -end
\ No newline at end of file + end +end diff --git a/actionpack/test/controller/render_other_test.rb b/actionpack/test/controller/render_other_test.rb index 05645e47fa..51c3c55545 100644 --- a/actionpack/test/controller/render_other_test.rb +++ b/actionpack/test/controller/render_other_test.rb @@ -2,139 +2,144 @@ require 'abstract_unit' require 'controller/fake_models' require 'pathname' -class TestController < ActionController::Base - protect_from_forgery - layout :determine_layout +class RenderOtherTest < ActionController::TestCase + class TestController < ActionController::Base + protect_from_forgery - module RenderTestHelper - def rjs_helper_method_from_module - page.visual_effect :highlight + def self.controller_path + 'test' end - end - helper RenderTestHelper - helper do - def rjs_helper_method(value) - page.visual_effect :highlight, value + layout :determine_layout + + module RenderTestHelper + def rjs_helper_method_from_module + page.visual_effect :highlight + end end - end - def enum_rjs_test - render :update do |page| - page.select('.product').each do |value| - page.rjs_helper_method_from_module - page.rjs_helper_method(value) - page.sortable(value, :url => { :action => "order" }) - page.draggable(value) + helper RenderTestHelper + helper do + def rjs_helper_method(value) + page.visual_effect :highlight, value end end - end - - def render_explicit_html_template - end - - def render_custom_code_rjs - render :update, :status => 404 do |page| - page.replace :foo, :partial => 'partial' + + def enum_rjs_test + render :update do |page| + page.select('.product').each do |value| + page.rjs_helper_method_from_module + page.rjs_helper_method(value) + page.sortable(value, :url => { :action => "order" }) + page.draggable(value) + end + end end - end - - def render_implicit_html_template - end - - def render_js_with_explicit_template - @project_id = 4 - render :template => 'test/delete_with_js' - end - def render_js_with_explicit_action_template - @project_id = 4 - render :action => 'delete_with_js' - end - - def delete_with_js - @project_id = 4 - end - - def update_page - render :update do |page| - page.replace_html 'balance', '$37,000,000.00' - page.visual_effect :highlight, 'balance' + def render_explicit_html_template + end + + def render_custom_code_rjs + render :update, :status => 404 do |page| + page.replace :foo, :partial => 'partial' + end end - end - def update_page_with_instance_variables - @money = '$37,000,000.00' - @div_id = 'balance' - render :update do |page| - page.replace_html @div_id, @money - page.visual_effect :highlight, @div_id + def render_implicit_html_template end - end - def update_page_with_view_method - render :update do |page| - page.replace_html 'person', pluralize(2, 'person') + def render_js_with_explicit_template + @project_id = 4 + render :template => 'test/delete_with_js' end - end - - def partial_as_rjs - render :update do |page| - page.replace :foo, :partial => 'partial' + + def render_js_with_explicit_action_template + @project_id = 4 + render :action => 'delete_with_js' end - end - def respond_to_partial_as_rjs - respond_to do |format| - format.js do - render :update do |page| - page.replace :foo, :partial => 'partial' - end + def delete_with_js + @project_id = 4 + end + + def update_page + render :update do |page| + page.replace_html 'balance', '$37,000,000.00' + page.visual_effect :highlight, 'balance' end end - end - - def render_alternate_default - # For this test, the method "default_render" is overridden: - @alternate_default_render = lambda do + + def update_page_with_instance_variables + @money = '$37,000,000.00' + @div_id = 'balance' + render :update do |page| + page.replace_html @div_id, @money + page.visual_effect :highlight, @div_id + end + end + + def update_page_with_view_method + render :update do |page| + page.replace_html 'person', pluralize(2, 'person') + end + end + + def partial_as_rjs render :update do |page| page.replace :foo, :partial => 'partial' end end - end - -private - def default_render - if @alternate_default_render - @alternate_default_render.call - else - super + + def respond_to_partial_as_rjs + respond_to do |format| + format.js do + render :update do |page| + page.replace :foo, :partial => 'partial' + end + end + end end - end - def determine_layout - case action_name - when "hello_world", "layout_test", "rendering_without_layout", - "rendering_nothing_on_layout", "render_text_hello_world", - "render_text_hello_world_with_layout", - "hello_world_with_layout_false", - "partial_only", "partial_only_with_layout", - "accessing_params_in_template", - "accessing_params_in_template_with_layout", - "render_with_explicit_template", - "render_with_explicit_string_template", - "update_page", "update_page_with_instance_variables" - - "layouts/standard" - when "action_talk_to_layout", "layout_overriding_layout" - "layouts/talk_from_action" - when "render_implicit_html_template_from_xhr_request" - (request.xhr? ? 'layouts/xhr' : 'layouts/standard') - end - end -end + def render_alternate_default + # For this test, the method "default_render" is overridden: + @alternate_default_render = lambda do + render :update do |page| + page.replace :foo, :partial => 'partial' + end + end + end + + private + def default_render + if @alternate_default_render + @alternate_default_render.call + else + super + end + end + + def determine_layout + case action_name + when "hello_world", "layout_test", "rendering_without_layout", + "rendering_nothing_on_layout", "render_text_hello_world", + "render_text_hello_world_with_layout", + "hello_world_with_layout_false", + "partial_only", "partial_only_with_layout", + "accessing_params_in_template", + "accessing_params_in_template_with_layout", + "render_with_explicit_template", + "render_with_explicit_string_template", + "update_page", "update_page_with_instance_variables" + + "layouts/standard" + when "action_talk_to_layout", "layout_overriding_layout" + "layouts/talk_from_action" + when "render_implicit_html_template_from_xhr_request" + (request.xhr? ? 'layouts/xhr' : 'layouts/standard') + end + end + end -class RenderTest < ActionController::TestCase tests TestController def setup @@ -144,8 +149,8 @@ class RenderTest < ActionController::TestCase @controller.logger = Logger.new(nil) @request.host = "www.nextangle.com" - end - + end + def test_enum_rjs_test ActiveSupport::SecureRandom.stubs(:base64).returns("asdf") get :enum_rjs_test @@ -153,13 +158,13 @@ class RenderTest < ActionController::TestCase $$(".product").each(function(value, index) { new Effect.Highlight(element,{}); new Effect.Highlight(value,{}); - Sortable.create(value, {onUpdate:function(){new Ajax.Request('/test/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(value) + '&authenticity_token=' + encodeURIComponent('asdf')})}}); + Sortable.create(value, {onUpdate:function(){new Ajax.Request('/render_other_test/test/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(value) + '&authenticity_token=' + encodeURIComponent('asdf')})}}); new Draggable(value, {}); }); }.gsub(/^ /, '').strip assert_equal body, @response.body end - + def test_explicitly_rendering_an_html_template_with_implicit_html_template_renders_should_be_possible_from_an_rjs_template [:js, "js"].each do |format| assert_nothing_raised do @@ -167,14 +172,14 @@ class RenderTest < ActionController::TestCase assert_equal %(document.write("Hello world\\n");), @response.body end end - end - + end + def test_render_custom_code_rjs get :render_custom_code_rjs assert_response 404 assert_equal %(Element.replace("foo", "partial html");), @response.body end - + def test_render_in_an_rjs_template_should_pick_html_templates_when_available [:js, "js"].each do |format| assert_nothing_raised do @@ -183,7 +188,7 @@ class RenderTest < ActionController::TestCase end end end - + def test_render_rjs_template_explicitly get :render_js_with_explicit_template assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body @@ -193,12 +198,12 @@ class RenderTest < ActionController::TestCase get :render_js_with_explicit_action_template assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body end - + def test_render_rjs_with_default get :delete_with_js assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body end - + def test_update_page get :update_page assert_template nil @@ -219,8 +224,8 @@ class RenderTest < ActionController::TestCase assert_template nil assert_equal 'text/javascript; charset=utf-8', @response.headers["Content-Type"] assert_match /2 people/, @response.body - end - + end + def test_should_render_html_formatted_partial_with_rjs xhr :get, :partial_as_rjs assert_equal %(Element.replace("foo", "partial html");), @response.body @@ -230,9 +235,9 @@ class RenderTest < ActionController::TestCase xhr :get, :respond_to_partial_as_rjs assert_equal %(Element.replace("foo", "partial html");), @response.body end - + def test_should_render_with_alternate_default_render xhr :get, :render_alternate_default assert_equal %(Element.replace("foo", "partial html");), @response.body - end -end
\ No newline at end of file + end +end diff --git a/actionpack/test/controller/render_xml_test.rb b/actionpack/test/controller/render_xml_test.rb index e96e8a4d57..68a52c3e8c 100644 --- a/actionpack/test/controller/render_xml_test.rb +++ b/actionpack/test/controller/render_xml_test.rb @@ -2,37 +2,41 @@ require 'abstract_unit' require 'controller/fake_models' require 'pathname' -class TestController < ActionController::Base - protect_from_forgery +class RenderXmlTest < ActionController::TestCase + class TestController < ActionController::Base + protect_from_forgery - def render_with_location - render :xml => "<hello/>", :location => "http://example.com", :status => 201 - end + def self.controller_path + 'test' + end - def render_with_object_location - customer = Customer.new("Some guy", 1) - render :xml => "<customer/>", :location => customer, :status => :created - end + def render_with_location + render :xml => "<hello/>", :location => "http://example.com", :status => 201 + end - def render_with_to_xml - to_xmlable = Class.new do - def to_xml - "<i-am-xml/>" - end - end.new + def render_with_object_location + customer = Customer.new("Some guy", 1) + render :xml => "<customer/>", :location => customer, :status => :created + end - render :xml => to_xmlable - end - - def formatted_xml_erb + def render_with_to_xml + to_xmlable = Class.new do + def to_xml + "<i-am-xml/>" + end + end.new + + render :xml => to_xmlable + end + + def formatted_xml_erb + end + + def render_xml_with_custom_content_type + render :xml => "<blah/>", :content_type => "application/atomsvc+xml" + end end - - def render_xml_with_custom_content_type - render :xml => "<blah/>", :content_type => "application/atomsvc+xml" - end -end -class RenderTest < ActionController::TestCase tests TestController def setup @@ -42,8 +46,8 @@ class RenderTest < ActionController::TestCase @controller.logger = Logger.new(nil) @request.host = "www.nextangle.com" - end - + end + def test_rendering_with_location_should_set_header get :render_with_location assert_equal "http://example.com", @response.headers["Location"] @@ -53,7 +57,7 @@ class RenderTest < ActionController::TestCase get :render_with_to_xml assert_equal "<i-am-xml/>", @response.body end - + def test_rendering_with_object_location_should_set_header_with_url_for with_routing do |set| set.draw do |map| @@ -65,19 +69,19 @@ class RenderTest < ActionController::TestCase assert_equal "http://www.nextangle.com/customers/1", @response.headers["Location"] end end - + def test_should_render_formatted_xml_erb_template get :formatted_xml_erb, :format => :xml assert_equal '<test>passed formatted xml erb</test>', @response.body end - + def test_should_render_xml_but_keep_custom_content_type get :render_xml_with_custom_content_type assert_equal "application/atomsvc+xml", @response.content_type end - + def test_should_use_implicit_content_type get :implicit_content_type, :format => 'atom' assert_equal Mime::ATOM, @response.content_type - end + end end diff --git a/actionpack/test/controller/rescue_test.rb b/actionpack/test/controller/rescue_test.rb index 490a4ff3b3..09eddfe4a7 100644 --- a/actionpack/test/controller/rescue_test.rb +++ b/actionpack/test/controller/rescue_test.rb @@ -227,12 +227,6 @@ class ControllerInheritanceRescueControllerTest < ActionController::TestCase end end -class ApplicationController < ActionController::Base - rescue_from ActionController::RoutingError do - render :text => 'no way' - end -end - class RescueControllerTest < ActionController::TestCase def test_rescue_handler get :not_authorized @@ -332,23 +326,20 @@ class RescueTest < ActionController::IntegrationTest end test 'rescue routing exceptions' do - assert_equal 1, ApplicationController.rescue_handlers.length - - begin - with_test_routing do - get '/no_way' - assert_equal 'no way', response.body - end - ensure - ActionController::Base.rescue_handlers.clear + app = ActionDispatch::Rescue.new(ActionController::Routing::Routes) do + rescue_from ActionController::RoutingError, lambda { |env| [200, {"Content-Type" => "text/html"}, "Gotcha!"] } end + @integration_session = open_session(app) + + get '/b00m' + assert_equal "Gotcha!", response.body end test 'unrescued exception' do - with_test_routing do - get '/b00m' - assert_match(/Action Controller: Exception caught/, response.body) - end + app = ActionDispatch::Rescue.new(ActionController::Routing::Routes) + @integration_session = open_session(app) + + assert_raise(ActionController::RoutingError) { get '/b00m' } end private @@ -359,6 +350,7 @@ class RescueTest < ActionController::IntegrationTest map.connect 'invalid', :controller => "rescue_test/test", :action => 'invalid' map.connect 'b00m', :controller => "rescue_test/test", :action => 'b00m' end + reset! yield end end diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb index 0b639e363d..5b47de19ae 100644 --- a/actionpack/test/controller/resources_test.rb +++ b/actionpack/test/controller/resources_test.rb @@ -135,7 +135,7 @@ class ResourcesTest < ActionController::TestCase def test_with_custom_conditions with_restful_routing :messages, :conditions => { :subdomain => 'app' } do - assert_equal 'app', ActionController::Routing::Routes.named_routes.routes[:messages].conditions[:subdomain] + assert ActionController::Routing::Routes.recognize_path("/messages", :method => :get, :subdomain => 'app') end end @@ -1130,7 +1130,8 @@ class ResourcesTest < ActionController::TestCase map.resource :product end - assert_equal :get, set.named_routes.routes[:product].conditions[:method] + assert_routing '/product', :controller => 'products', :action => 'show' + assert set.recognize_path("/product", :method => :get) end end diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index d20684296f..1aabf71cad 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -232,14 +232,18 @@ class LegacyRouteSetTests < Test::Unit::TestCase end def test_basic_named_route - rs.add_named_route :home, '', :controller => 'content', :action => 'list' + rs.draw do |map| + map.home '', :controller => 'content', :action => 'list' + end x = setup_for_named_route assert_equal("http://test.host/", x.send(:home_url)) end def test_basic_named_route_with_relative_url_root - rs.add_named_route :home, '', :controller => 'content', :action => 'list' + rs.draw do |map| + map.home '', :controller => 'content', :action => 'list' + end x = setup_for_named_route ActionController::Base.relative_url_root = "/foo" assert_equal("http://test.host/foo/", @@ -249,14 +253,18 @@ class LegacyRouteSetTests < Test::Unit::TestCase end def test_named_route_with_option - rs.add_named_route :page, 'page/:title', :controller => 'content', :action => 'show_page' + rs.draw do |map| + map.page 'page/:title', :controller => 'content', :action => 'show_page' + end x = setup_for_named_route assert_equal("http://test.host/page/new%20stuff", x.send(:page_url, :title => 'new stuff')) end def test_named_route_with_default - rs.add_named_route :page, 'page/:title', :controller => 'content', :action => 'show_page', :title => 'AboutPage' + rs.draw do |map| + map.page 'page/:title', :controller => 'content', :action => 'show_page', :title => 'AboutPage' + end x = setup_for_named_route assert_equal("http://test.host/page/AboutRails", x.send(:page_url, :title => "AboutRails")) @@ -264,36 +272,46 @@ class LegacyRouteSetTests < Test::Unit::TestCase end def test_named_route_with_name_prefix - rs.add_named_route :page, 'page', :controller => 'content', :action => 'show_page', :name_prefix => 'my_' + rs.draw do |map| + map.page 'page', :controller => 'content', :action => 'show_page', :name_prefix => 'my_' + end x = setup_for_named_route assert_equal("http://test.host/page", x.send(:my_page_url)) end def test_named_route_with_path_prefix - rs.add_named_route :page, 'page', :controller => 'content', :action => 'show_page', :path_prefix => 'my' + rs.draw do |map| + map.page 'page', :controller => 'content', :action => 'show_page', :path_prefix => 'my' + end x = setup_for_named_route assert_equal("http://test.host/my/page", x.send(:page_url)) end def test_named_route_with_blank_path_prefix - rs.add_named_route :page, 'page', :controller => 'content', :action => 'show_page', :path_prefix => '' + rs.draw do |map| + map.page 'page', :controller => 'content', :action => 'show_page', :path_prefix => '' + end x = setup_for_named_route assert_equal("http://test.host/page", x.send(:page_url)) end def test_named_route_with_nested_controller - rs.add_named_route :users, 'admin/user', :controller => 'admin/user', :action => 'index' + rs.draw do |map| + map.users 'admin/user', :controller => 'admin/user', :action => 'index' + end x = setup_for_named_route assert_equal("http://test.host/admin/user", x.send(:users_url)) end def test_optimised_named_route_call_never_uses_url_for - rs.add_named_route :users, 'admin/user', :controller => '/admin/user', :action => 'index' - rs.add_named_route :user, 'admin/user/:id', :controller=>'/admin/user', :action=>'show' + rs.draw do |map| + map.users 'admin/user', :controller => '/admin/user', :action => 'index' + map.user 'admin/user/:id', :controller=>'/admin/user', :action=>'show' + end x = setup_for_named_route x.expects(:url_for).never x.send(:users_url) @@ -303,7 +321,9 @@ class LegacyRouteSetTests < Test::Unit::TestCase end def test_optimised_named_route_with_host - rs.add_named_route :pages, 'pages', :controller => 'content', :action => 'show_page', :host => 'foo.com' + rs.draw do |map| + map.pages 'pages', :controller => 'content', :action => 'show_page', :host => 'foo.com' + end x = setup_for_named_route x.expects(:url_for).with(:host => 'foo.com', :only_path => false, :controller => 'content', :action => 'show_page', :use_route => :pages).once x.send(:pages_url) @@ -378,7 +398,9 @@ class LegacyRouteSetTests < Test::Unit::TestCase end def test_paths_slashes_unescaped_with_ordered_parameters - rs.add_named_route :path, '/file/*path', :controller => 'content' + rs.draw do |map| + map.path '/file/*path', :controller => 'content' + end # No / to %2F in URI, only for query params. x = setup_for_named_route @@ -1781,23 +1803,23 @@ class RouteSetTest < ActiveSupport::TestCase end def test_default_route_recognition - expected = {:controller => 'accounts', :action => 'show', :id => '10'} - assert_equal expected, default_route_set.recognize_path('/accounts/show/10') - assert_equal expected, default_route_set.recognize_path('/accounts/show/10/') + expected = {:controller => 'pages', :action => 'show', :id => '10'} + assert_equal expected, default_route_set.recognize_path('/pages/show/10') + assert_equal expected, default_route_set.recognize_path('/pages/show/10/') expected[:id] = 'jamis' - assert_equal expected, default_route_set.recognize_path('/accounts/show/jamis/') + assert_equal expected, default_route_set.recognize_path('/pages/show/jamis/') expected.delete :id - assert_equal expected, default_route_set.recognize_path('/accounts/show') - assert_equal expected, default_route_set.recognize_path('/accounts/show/') + assert_equal expected, default_route_set.recognize_path('/pages/show') + assert_equal expected, default_route_set.recognize_path('/pages/show/') expected[:action] = 'index' - assert_equal expected, default_route_set.recognize_path('/accounts/') - assert_equal expected, default_route_set.recognize_path('/accounts') + assert_equal expected, default_route_set.recognize_path('/pages/') + assert_equal expected, default_route_set.recognize_path('/pages') assert_raise(ActionController::RoutingError) { default_route_set.recognize_path('/') } - assert_raise(ActionController::RoutingError) { default_route_set.recognize_path('/accounts/how/goood/it/is/to/be/free') } + assert_raise(ActionController::RoutingError) { default_route_set.recognize_path('/pages/how/goood/it/is/to/be/free') } end def test_default_route_should_omit_default_action @@ -1813,15 +1835,15 @@ class RouteSetTest < ActiveSupport::TestCase end def test_default_route_should_uri_escape_pluses - expected = { :controller => 'accounts', :action => 'show', :id => 'hello world' } - assert_equal expected, default_route_set.recognize_path('/accounts/show/hello world') - assert_equal expected, default_route_set.recognize_path('/accounts/show/hello%20world') - assert_equal '/accounts/show/hello%20world', default_route_set.generate(expected, expected) + expected = { :controller => 'pages', :action => 'show', :id => 'hello world' } + assert_equal expected, default_route_set.recognize_path('/pages/show/hello world') + assert_equal expected, default_route_set.recognize_path('/pages/show/hello%20world') + assert_equal '/pages/show/hello%20world', default_route_set.generate(expected, expected) expected[:id] = 'hello+world' - assert_equal expected, default_route_set.recognize_path('/accounts/show/hello+world') - assert_equal expected, default_route_set.recognize_path('/accounts/show/hello%2Bworld') - assert_equal '/accounts/show/hello+world', default_route_set.generate(expected, expected) + assert_equal expected, default_route_set.recognize_path('/pages/show/hello+world') + assert_equal expected, default_route_set.recognize_path('/pages/show/hello%2Bworld') + assert_equal '/pages/show/hello+world', default_route_set.generate(expected, expected) end def test_parameter_shell diff --git a/actionpack/test/controller/url_rewriter_test.rb b/actionpack/test/controller/url_rewriter_test.rb index 9b8d07222b..4c4bf9ade4 100644 --- a/actionpack/test/controller/url_rewriter_test.rb +++ b/actionpack/test/controller/url_rewriter_test.rb @@ -1,4 +1,5 @@ require 'abstract_unit' +require 'controller/fake_controllers' ActionController::UrlRewriter diff --git a/actionpack/test/controller/view_paths_test.rb b/actionpack/test/controller/view_paths_test.rb index c732d1c910..05d2c8407c 100644 --- a/actionpack/test/controller/view_paths_test.rb +++ b/actionpack/test/controller/view_paths_test.rb @@ -43,7 +43,7 @@ class ViewLoadPathsTest < ActionController::TestCase end def expand(array) - array.map {|x| File.expand_path(x)} + array.map {|x| File.expand_path(x.to_s)} end def assert_paths(*paths) diff --git a/actionpack/test/dispatch/session/cookie_store_test.rb b/actionpack/test/dispatch/session/cookie_store_test.rb index 0723a76d2b..d695be0be4 100644 --- a/actionpack/test/dispatch/session/cookie_store_test.rb +++ b/actionpack/test/dispatch/session/cookie_store_test.rb @@ -30,7 +30,7 @@ class CookieStoreTest < ActionController::IntegrationTest end def get_session_id - render :text => "foo: #{session[:foo].inspect}; id: #{request.session_options[:id]}" + render :text => "id: #{request.session_options[:id]}" end def call_reset_session @@ -119,7 +119,7 @@ class CookieStoreTest < ActionController::IntegrationTest get '/get_session_id' assert_response :success - assert_equal "foo: \"bar\"; id: #{session_id}", response.body + assert_equal "id: #{session_id}", response.body end end diff --git a/actionpack/test/dispatch/show_exceptions_test.rb b/actionpack/test/dispatch/show_exceptions_test.rb index ce1973853e..d4800e4edb 100644 --- a/actionpack/test/dispatch/show_exceptions_test.rb +++ b/actionpack/test/dispatch/show_exceptions_test.rb @@ -70,8 +70,7 @@ class ShowExceptionsTest < ActionController::IntegrationTest test "localize public rescue message" do # Change locale - old_locale = I18n.locale - I18n.locale = :da + old_locale, I18n.locale = I18n.locale, :da begin @integration_session = open_session(ProductionApp) diff --git a/actionpack/test/dispatch/test_request_test.rb b/actionpack/test/dispatch/test_request_test.rb index 5da02b2ea6..b8e340e055 100644 --- a/actionpack/test/dispatch/test_request_test.rb +++ b/actionpack/test/dispatch/test_request_test.rb @@ -5,7 +5,7 @@ class TestRequestTest < ActiveSupport::TestCase env = ActionDispatch::TestRequest.new.env assert_equal "GET", env.delete("REQUEST_METHOD") - assert_equal "off", env.delete("HTTPS") + assert_equal nil, env.delete("HTTPS") assert_equal "http", env.delete("rack.url_scheme") assert_equal "example.org", env.delete("SERVER_NAME") assert_equal "80", env.delete("SERVER_PORT") @@ -18,7 +18,7 @@ class TestRequestTest < ActiveSupport::TestCase assert_equal "0.0.0.0", env.delete("REMOTE_ADDR") assert_equal "Rails Testing", env.delete("HTTP_USER_AGENT") - assert_equal [1, 0], env.delete("rack.version") + assert_equal [0, 1], env.delete("rack.version") assert_equal "", env.delete("rack.input").string assert_kind_of StringIO, env.delete("rack.errors") assert_equal true, env.delete("rack.multithread") diff --git a/actionpack/test/fixtures/content_type/render_default_content_types_for_respond_to.xml.erb b/actionpack/test/fixtures/old_content_type/render_default_content_types_for_respond_to.xml.erb index 25dc746886..25dc746886 100644 --- a/actionpack/test/fixtures/content_type/render_default_content_types_for_respond_to.xml.erb +++ b/actionpack/test/fixtures/old_content_type/render_default_content_types_for_respond_to.xml.erb diff --git a/actionpack/test/fixtures/content_type/render_default_for_rhtml.rhtml b/actionpack/test/fixtures/old_content_type/render_default_for_rhtml.rhtml index c7926d48bb..c7926d48bb 100644 --- a/actionpack/test/fixtures/content_type/render_default_for_rhtml.rhtml +++ b/actionpack/test/fixtures/old_content_type/render_default_for_rhtml.rhtml diff --git a/actionpack/test/fixtures/content_type/render_default_for_rjs.rjs b/actionpack/test/fixtures/old_content_type/render_default_for_rjs.rjs index 8d614d04ad..8d614d04ad 100644 --- a/actionpack/test/fixtures/content_type/render_default_for_rjs.rjs +++ b/actionpack/test/fixtures/old_content_type/render_default_for_rjs.rjs diff --git a/actionpack/test/fixtures/content_type/render_default_for_rxml.rxml b/actionpack/test/fixtures/old_content_type/render_default_for_rxml.rxml index 598d62e2fc..598d62e2fc 100644 --- a/actionpack/test/fixtures/content_type/render_default_for_rxml.rxml +++ b/actionpack/test/fixtures/old_content_type/render_default_for_rxml.rxml diff --git a/actionpack/test/lib/controller/fake_controllers.rb b/actionpack/test/lib/controller/fake_controllers.rb index 6e02e2d21b..5dcca2e148 100644 --- a/actionpack/test/lib/controller/fake_controllers.rb +++ b/actionpack/test/lib/controller/fake_controllers.rb @@ -9,7 +9,15 @@ module Admin class UserController < ActionController::Base; end class NewsFeedController < ActionController::Base; end end - +class ElsewhereController < ActionController::Base; end +class AddressesController < ActionController::Base; end +class SessionsController < ActionController::Base; end +class FooController < ActionController::Base; end +class CController < ActionController::Base; end +class HiController < ActionController::Base; end +class BraveController < ActionController::Base; end +class ImageController < ActionController::Base; end +class WeblogController < ActionController::Base; end # For speed test class SpeedController < ActionController::Base; end @@ -24,7 +32,6 @@ class UsersController < SpeedController; end class SettingsController < SpeedController; end class ChannelsController < SpeedController; end class ChannelVideosController < SpeedController; end -class SessionsController < SpeedController; end class LostPasswordsController < SpeedController; end class PagesController < SpeedController; end diff --git a/actionpack/test/lib/fixture_template.rb b/actionpack/test/lib/fixture_template.rb index 8da92180d1..6b9e7c5270 100644 --- a/actionpack/test/lib/fixture_template.rb +++ b/actionpack/test/lib/fixture_template.rb @@ -1,67 +1,24 @@ module ActionView #:nodoc: - class FixtureResolver < Resolver + class FixtureResolver < PathResolver def initialize(hash = {}, options = {}) super(options) @hash = hash end - def find_templates(name, details, prefix, partial) - if regexp = details_to_regexp(name, details, prefix, partial) - cached(regexp) do - templates = [] - @hash.select { |k,v| k =~ regexp }.each do |path, source| - templates << Template.new(source, path, *path_to_details(path)) - end - templates.sort_by {|t| -t.details.values.compact.size } - end - end - end - private - def formats_regexp - @formats_regexp ||= begin - formats = Mime::SET.symbols - '(?:' + formats.map { |l| "\\.#{Regexp.escape(l.to_s)}" }.join('|') + ')?' + def query(path, exts) + query = Regexp.escape(path) + exts.each do |ext| + query << '(?:' << ext.map {|e| e && Regexp.escape(".#{e}") }.join('|') << ')' end - end - - def handler_regexp - e = TemplateHandlers.extensions.map{|h| "\\.#{Regexp.escape(h.to_s)}"}.join("|") - "(?:#{e})" - end - def details_to_regexp(name, details, prefix, partial) - path = "" - path << "#{prefix}/" unless prefix.empty? - path << (partial ? "_#{name}" : name) - - extensions = "" - [:locales, :formats].each do |k| - extensions << if exts = details[k] - '(?:' + exts.map {|e| "\\.#{Regexp.escape(e.to_s)}"}.join('|') + ')?' - else - k == :formats ? formats_regexp : '' - end + templates = [] + @hash.select { |k,v| k =~ /^#{query}$/ }.each do |path, source| + templates << Template.new(source, path, *path_to_details(path)) end - - %r'^#{Regexp.escape(path)}#{extensions}#{handler_regexp}$' + templates.sort_by {|t| -t.details.values.compact.size } end - # TODO: fix me - # :api: plugin - def path_to_details(path) - # [:erb, :format => :html, :locale => :en, :partial => true/false] - if m = path.match(%r'(_)?[\w-]+((?:\.[\w-]+)*)\.(\w+)$') - partial = m[1] == '_' - details = (m[2]||"").split('.').reject { |e| e.empty? } - handler = Template.handler_class_for_extension(m[3]) - - format = Mime[details.last] && details.pop.to_sym - locale = details.last && details.pop.to_sym - - return handler, :format => format, :locale => locale, :partial => partial - end - end end end
\ No newline at end of file diff --git a/actionpack/test/new_base/base_test.rb b/actionpack/test/new_base/base_test.rb index 1b2e917ced..effde324bc 100644 --- a/actionpack/test/new_base/base_test.rb +++ b/actionpack/test/new_base/base_test.rb @@ -1,4 +1,4 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper") +require 'abstract_unit' # Tests the controller dispatching happy path module Dispatching @@ -65,4 +65,4 @@ module Dispatching assert_equal 'contained_empty', Submodule::ContainedEmptyController.controller_name end end -end
\ No newline at end of file +end diff --git a/actionpack/test/new_base/content_negotiation_test.rb b/actionpack/test/new_base/content_negotiation_test.rb new file mode 100644 index 0000000000..c43cb677f8 --- /dev/null +++ b/actionpack/test/new_base/content_negotiation_test.rb @@ -0,0 +1,18 @@ +require 'abstract_unit' + +module ContentNegotiation + + # This has no layout and it works + class BasicController < ActionController::Base + self.view_paths = [ActionView::FixtureResolver.new( + "content_negotiation/basic/hello.html.erb" => "Hello world <%= request.formats %>!" + )] + end + + class TestContentNegotiation < SimpleRouteCase + test "A */* Accept header will return HTML" do + get "/content_negotiation/basic/hello", {}, "HTTP_ACCEPT" => "*/*" + assert_body "Hello world */*!" + end + end +end diff --git a/actionpack/test/new_base/content_type_test.rb b/actionpack/test/new_base/content_type_test.rb index ceee508224..898d0bb9f3 100644 --- a/actionpack/test/new_base/content_type_test.rb +++ b/actionpack/test/new_base/content_type_test.rb @@ -1,4 +1,4 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper") +require 'abstract_unit' module ContentType class BaseController < ActionController::Base diff --git a/actionpack/test/new_base/etag_test.rb b/actionpack/test/new_base/etag_test.rb index 3a69e7dac4..d5b7942ab6 100644 --- a/actionpack/test/new_base/etag_test.rb +++ b/actionpack/test/new_base/etag_test.rb @@ -1,4 +1,4 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper") +require 'abstract_unit' module Etags class BasicController < ActionController::Base @@ -43,4 +43,4 @@ module Etags %("#{Digest::MD5.hexdigest(text)}") end end -end
\ No newline at end of file +end diff --git a/actionpack/test/new_base/metal_test.rb b/actionpack/test/new_base/metal_test.rb index 2b7720863a..e1d46b906e 100644 --- a/actionpack/test/new_base/metal_test.rb +++ b/actionpack/test/new_base/metal_test.rb @@ -1,4 +1,4 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper") +require 'abstract_unit' module MetalTest class MetalMiddleware < ActionController::Middleware @@ -41,4 +41,3 @@ module MetalTest end end end - diff --git a/actionpack/test/new_base/middleware_test.rb b/actionpack/test/new_base/middleware_test.rb new file mode 100644 index 0000000000..ada0215b1a --- /dev/null +++ b/actionpack/test/new_base/middleware_test.rb @@ -0,0 +1,77 @@ +require 'abstract_unit' + +module MiddlewareTest + class MyMiddleware + def initialize(app) + @app = app + end + + def call(env) + result = @app.call(env) + result[1]["Middleware-Test"] = "Success" + result[1]["Middleware-Order"] = "First" + result + end + end + + class ExclaimerMiddleware + def initialize(app) + @app = app + end + + def call(env) + result = @app.call(env) + result[1]["Middleware-Order"] << "!" + result + end + end + + class MyController < ActionController::Metal + use MyMiddleware + + middleware.insert_before MyMiddleware, ExclaimerMiddleware + + def index + self.response_body = "Hello World" + end + end + + class InheritedController < MyController + end + + module MiddlewareTests + extend ActiveSupport::Testing::Declarative + + test "middleware that is 'use'd is called as part of the Rack application" do + result = @app.call(env_for("/")) + assert_equal "Hello World", result[2] + assert_equal "Success", result[1]["Middleware-Test"] + end + + test "the middleware stack is exposed as 'middleware' in the controller" do + result = @app.call(env_for("/")) + assert_equal "First!", result[1]["Middleware-Order"] + end + end + + class TestMiddleware < ActiveSupport::TestCase + include MiddlewareTests + + def setup + @app = MyController.action(:index) + end + + def env_for(url) + Rack::MockRequest.env_for(url) + end + end + + class TestInheritedMiddleware < TestMiddleware + def setup + @app = InheritedController.action(:index) + end + + test "middleware inherits" do + end + end +end diff --git a/actionpack/test/new_base/redirect_test.rb b/actionpack/test/new_base/redirect_test.rb deleted file mode 100644 index e591ebd05f..0000000000 --- a/actionpack/test/new_base/redirect_test.rb +++ /dev/null @@ -1 +0,0 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
\ No newline at end of file diff --git a/actionpack/test/new_base/render_action_test.rb b/actionpack/test/new_base/render_action_test.rb index dfa7cc2141..d5896c1ebd 100644 --- a/actionpack/test/new_base/render_action_test.rb +++ b/actionpack/test/new_base/render_action_test.rb @@ -1,4 +1,4 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper") +require 'abstract_unit' module RenderAction # This has no layout and it works @@ -317,4 +317,4 @@ module RenderActionWithBothLayouts assert_status 200 end end -end
\ No newline at end of file +end diff --git a/actionpack/test/new_base/render_file_test.rb b/actionpack/test/new_base/render_file_test.rb index 769949be0c..c4098855e6 100644 --- a/actionpack/test/new_base/render_file_test.rb +++ b/actionpack/test/new_base/render_file_test.rb @@ -1,9 +1,9 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper") +require 'abstract_unit' module RenderFile class BasicController < ActionController::Base - self.view_paths = "." + self.view_paths = File.dirname(__FILE__) def index render :file => File.join(File.dirname(__FILE__), *%w[.. fixtures test hello_world]) @@ -107,4 +107,4 @@ module RenderFile end end -end
\ No newline at end of file +end diff --git a/actionpack/test/new_base/render_implicit_action_test.rb b/actionpack/test/new_base/render_implicit_action_test.rb index fd96e1955f..2b78fa7d4f 100644 --- a/actionpack/test/new_base/render_implicit_action_test.rb +++ b/actionpack/test/new_base/render_implicit_action_test.rb @@ -1,4 +1,4 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper") +require 'abstract_unit' module RenderImplicitAction class SimpleController < ::ApplicationController @@ -25,4 +25,4 @@ module RenderImplicitAction assert_status 200 end end -end
\ No newline at end of file +end diff --git a/actionpack/test/new_base/render_layout_test.rb b/actionpack/test/new_base/render_layout_test.rb index 933eef58e7..f840a47ecf 100644 --- a/actionpack/test/new_base/render_layout_test.rb +++ b/actionpack/test/new_base/render_layout_test.rb @@ -1,4 +1,4 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper") +require 'abstract_unit' module ControllerLayouts class ImplicitController < ::ApplicationController @@ -98,4 +98,4 @@ module ControllerLayouts end end end -end
\ No newline at end of file +end diff --git a/actionpack/test/new_base/render_partial_test.rb b/actionpack/test/new_base/render_partial_test.rb index bbb98a0c01..7c2c20e1c7 100644 --- a/actionpack/test/new_base/render_partial_test.rb +++ b/actionpack/test/new_base/render_partial_test.rb @@ -1,4 +1,4 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper") +require 'abstract_unit' module RenderPartial @@ -24,4 +24,4 @@ module RenderPartial end end -end
\ No newline at end of file +end diff --git a/actionpack/test/new_base/render_rjs_test.rb b/actionpack/test/new_base/render_rjs_test.rb index 3d3e516905..7b76c54ab9 100644 --- a/actionpack/test/new_base/render_rjs_test.rb +++ b/actionpack/test/new_base/render_rjs_test.rb @@ -1,9 +1,7 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper") +require 'abstract_unit' module RenderRjs - class BasicController < ActionController::Base - self.view_paths = [ActionView::FixtureResolver.new( "render_rjs/basic/index.js.rjs" => "page[:customer].replace_html render(:partial => 'customer')", "render_rjs/basic/index_html.js.rjs" => "page[:customer].replace_html :partial => 'customer'", @@ -26,6 +24,14 @@ module RenderRjs class TestBasic < SimpleRouteCase testing BasicController + def setup + @old_locale = I18n.locale + end + + def teardown + I18n.locale = @old_locale + end + test "rendering a partial in an RJS template should pick the JS template over the HTML one" do get :index, "format" => "js" assert_response("$(\"customer\").update(\"JS Partial\");") @@ -40,6 +46,5 @@ module RenderRjs get :index_locale, "format" => "js" assert_response("$(\"customer\").update(\"Danish HTML Partial\");") end - end -end
\ No newline at end of file +end diff --git a/actionpack/test/new_base/render_template_test.rb b/actionpack/test/new_base/render_template_test.rb index 967cbd07b0..3b24c2d75a 100644 --- a/actionpack/test/new_base/render_template_test.rb +++ b/actionpack/test/new_base/render_template_test.rb @@ -1,4 +1,4 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper") +require 'abstract_unit' module RenderTemplate class WithoutLayoutController < ActionController::Base @@ -167,4 +167,4 @@ module RenderTemplate end end end -end
\ No newline at end of file +end diff --git a/actionpack/test/new_base/render_test.rb b/actionpack/test/new_base/render_test.rb index 5783b4766a..804be79d17 100644 --- a/actionpack/test/new_base/render_test.rb +++ b/actionpack/test/new_base/render_test.rb @@ -1,4 +1,4 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper") +require 'abstract_unit' module Render class BlankRenderController < ActionController::Base @@ -82,4 +82,4 @@ module Render assert_body "Controller Name: blank_render" end end -end
\ No newline at end of file +end diff --git a/actionpack/test/new_base/render_text_test.rb b/actionpack/test/new_base/render_text_test.rb index 84f77432c9..f5839ee16f 100644 --- a/actionpack/test/new_base/render_text_test.rb +++ b/actionpack/test/new_base/render_text_test.rb @@ -1,4 +1,4 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper") +require 'abstract_unit' module RenderText class SimpleController < ActionController::Base @@ -134,4 +134,4 @@ module RenderText assert_status 200 end end -end
\ No newline at end of file +end diff --git a/actionpack/test/new_base/render_xml_test.rb b/actionpack/test/new_base/render_xml_test.rb index a3890ddfb2..d044738a78 100644 --- a/actionpack/test/new_base/render_xml_test.rb +++ b/actionpack/test/new_base/render_xml_test.rb @@ -1,4 +1,4 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper") +require 'abstract_unit' module RenderXml @@ -8,4 +8,4 @@ module RenderXml "render_xml/basic/with_render_erb" => "Hello world!" )] end -end
\ No newline at end of file +end diff --git a/actionpack/test/new_base/test_helper.rb b/actionpack/test/new_base/test_helper.rb deleted file mode 100644 index b7ccd3db8d..0000000000 --- a/actionpack/test/new_base/test_helper.rb +++ /dev/null @@ -1,110 +0,0 @@ -$:.unshift(File.dirname(__FILE__) + '/../../lib') -$:.unshift(File.dirname(__FILE__) + '/../../../activesupport/lib') -$:.unshift(File.dirname(__FILE__) + '/../lib') - -require 'test/unit' -require 'active_support' -require 'active_support/test_case' -require 'action_view' -require 'fixture_template' - -begin - require 'ruby-debug' - Debugger.settings[:autoeval] = true - Debugger.start -rescue LoadError - # Debugging disabled. `gem install ruby-debug` to enable. -end - -require 'action_controller' -require 'pp' # require 'pp' early to prevent hidden_methods from not picking up the pretty-print methods until too late - -require 'action_controller/testing/process' -require 'action_controller/testing/integration' - -module Rails - def self.env - x = Object.new - def x.test?() true end - x - end -end - -# Temporary base class -class Rack::TestCase < ActionController::IntegrationTest - setup do - ActionController::Base.session_options[:key] = "abc" - ActionController::Base.session_options[:secret] = ("*" * 30) - end - - def app - @app ||= ActionController::Dispatcher.new - end - - def self.testing(klass = nil) - if klass - @testing = "/#{klass.name.underscore}".sub!(/_controller$/, '') - else - @testing - end - end - - def get(thing, *args) - if thing.is_a?(Symbol) - super("#{self.class.testing}/#{thing}", *args) - else - super - end - end - - def assert_body(body) - assert_equal body, Array.wrap(response.body).join - end - - def assert_status(code) - assert_equal code, response.status - end - - def assert_response(body, status = 200, headers = {}) - assert_body body - assert_status status - headers.each do |header, value| - assert_header header, value - end - end - - def assert_content_type(type) - assert_equal type, response.headers["Content-Type"] - end - - def assert_header(name, value) - assert_equal value, response.headers[name] - end -end - -class ::ApplicationController < ActionController::Base -end - -module ActionController - class << Routing - def possible_controllers - @@possible_controllers ||= [] - end - end - - class Base - def self.inherited(klass) - name = klass.name.underscore.sub(/_controller$/, '') - ActionController::Routing.possible_controllers << name unless name.blank? - super - end - end -end - -class SimpleRouteCase < Rack::TestCase - setup do - ActionController::Routing::Routes.draw do |map| - map.connect ':controller/:action/:id' - end - end -end diff --git a/actionpack/test/old_base/abstract_unit.rb b/actionpack/test/old_base/abstract_unit.rb deleted file mode 100644 index 3301041a41..0000000000 --- a/actionpack/test/old_base/abstract_unit.rb +++ /dev/null @@ -1,43 +0,0 @@ -if ENV['new_base'] - puts *caller - raise 'new_base/abstract_unit already loaded' -end -$:.unshift(File.dirname(__FILE__) + '/../lib') -$:.unshift(File.dirname(__FILE__) + '/../../activesupport/lib') -$:.unshift(File.dirname(__FILE__) + '/fixtures/helpers') -$:.unshift(File.dirname(__FILE__) + '/fixtures/alternate_helpers') - -require 'rubygems' -require 'yaml' -require 'stringio' -require 'test/unit' - -begin - require 'ruby-debug' - Debugger.settings[:autoeval] = true - Debugger.start -rescue LoadError - # Debugging disabled. `gem install ruby-debug` to enable. -end - -require 'action_controller' -require 'action_controller/testing/process' -require 'action_view/test_case' - -$tags[:old_base] = true - -# Show backtraces for deprecated behavior for quicker cleanup. -ActiveSupport::Deprecation.debug = true - -ActionController::Base.logger = nil -ActionController::Routing::Routes.reload rescue nil - -ActionController::Base.session_store = nil - -# Register danish language for testing -I18n.backend.store_translations 'da', {} -I18n.backend.store_translations 'pt-BR', {} -ORIGINAL_LOCALES = I18n.available_locales.map {|locale| locale.to_s }.sort - -FIXTURE_LOAD_PATH = File.join(File.dirname(__FILE__), 'fixtures') -ActionController::Base.view_paths = FIXTURE_LOAD_PATH diff --git a/actionpack/test/runner b/actionpack/test/runner deleted file mode 100755 index c2bbe63c75..0000000000 --- a/actionpack/test/runner +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env ruby - - -ARGV.each do |arg| - Dir["#{Dir.pwd}/#{arg}/**/*_test.rb"].each do |file| - require file - end -end
\ No newline at end of file diff --git a/actionpack/test/template/asset_tag_helper_test.rb b/actionpack/test/template/asset_tag_helper_test.rb index 28f9d48671..83fc6a282c 100644 --- a/actionpack/test/template/asset_tag_helper_test.rb +++ b/actionpack/test/template/asset_tag_helper_test.rb @@ -213,11 +213,11 @@ class AssetTagHelperTest < ActionView::TestCase end def test_javascript_include_tag_with_missing_source - assert_raise(Errno::ENOENT) { + assert_nothing_raised { javascript_include_tag('missing_security_guard') } - assert_raise(Errno::ENOENT) { + assert_nothing_raised { javascript_include_tag(:defaults, 'missing_security_guard') } @@ -276,7 +276,7 @@ class AssetTagHelperTest < ActionView::TestCase end def test_stylesheet_link_tag_with_missing_source - assert_raise(Errno::ENOENT) { + assert_nothing_raised { stylesheet_link_tag('missing_security_guard') } @@ -639,6 +639,40 @@ class AssetTagHelperTest < ActionView::TestCase assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'money.js')) end + def test_caching_javascript_include_tag_when_caching_on_and_missing_javascript_file + ENV["RAILS_ASSET_ID"] = "" + ActionController::Base.perform_caching = true + + assert_raise(Errno::ENOENT) { + javascript_include_tag('bank', 'robber', 'missing_security_guard', :cache => true) + } + + assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'all.js')) + + assert_raise(Errno::ENOENT) { + javascript_include_tag('bank', 'robber', 'missing_security_guard', :cache => "money") + } + + assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'money.js')) + end + + def test_caching_javascript_include_tag_when_caching_off_and_missing_javascript_file + ENV["RAILS_ASSET_ID"] = "" + ActionController::Base.perform_caching = false + + assert_raise(Errno::ENOENT) { + javascript_include_tag('bank', 'robber', 'missing_security_guard', :cache => true) + } + + assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'all.js')) + + assert_raise(Errno::ENOENT) { + javascript_include_tag('bank', 'robber', 'missing_security_guard', :cache => "money") + } + + assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'money.js')) + end + def test_caching_stylesheet_link_tag_when_caching_on ENV["RAILS_ASSET_ID"] = "" ActionController::Base.asset_host = 'http://a0.example.com' @@ -709,7 +743,6 @@ class AssetTagHelperTest < ActionView::TestCase def test_caching_stylesheet_link_tag_when_caching_on_and_missing_css_file ENV["RAILS_ASSET_ID"] = "" - ActionController::Base.asset_host = 'http://a0.example.com' ActionController::Base.perform_caching = true assert_raise(Errno::ENOENT) { @@ -729,6 +762,27 @@ class AssetTagHelperTest < ActionView::TestCase FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'money.css')) end + def test_caching_stylesheet_link_tag_when_caching_off_and_missing_css_file + ENV["RAILS_ASSET_ID"] = "" + ActionController::Base.perform_caching = false + + assert_raise(Errno::ENOENT) { + stylesheet_link_tag('bank', 'robber', 'missing_security_guard', :cache => true) + } + + assert ! File.exist?(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css')) + + assert_raise(Errno::ENOENT) { + stylesheet_link_tag('bank', 'robber', 'missing_security_guard', :cache => "money") + } + + assert ! File.exist?(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'money.css')) + + ensure + FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css')) + FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'money.css')) + end + def test_caching_stylesheet_link_tag_when_caching_on_with_proc_asset_host ENV["RAILS_ASSET_ID"] = "" ActionController::Base.asset_host = Proc.new { |source| "http://a#{source.length}.example.com" } diff --git a/actionpack/test/template/compiled_templates_test.rb b/actionpack/test/template/compiled_templates_test.rb index 7734e6da73..632988bb2e 100644 --- a/actionpack/test/template/compiled_templates_test.rb +++ b/actionpack/test/template/compiled_templates_test.rb @@ -14,6 +14,9 @@ class CompiledTemplatesTest < Test::Unit::TestCase assert_equal "two", render(:file => "test/render_file_with_locals_and_default.erb", :locals => { :secret => "two" }) end + # This is broken in 1.8.6 (not supported in Rails 3.0) because the cache uses a Hash + # key. Since Ruby 1.8.6 implements Hash#hash using the hash's object_id, it will never + # successfully get a cache hit here. def test_template_changes_are_not_reflected_with_cached_templates assert_equal "Hello world!", render(:file => "test/hello_world.erb") modify_template "test/hello_world.erb", "Goodbye world!" do diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb index 8fd018f86d..be15b06372 100644 --- a/actionpack/test/template/form_helper_test.rb +++ b/actionpack/test/template/form_helper_test.rb @@ -784,6 +784,42 @@ class FormHelperTest < ActionView::TestCase assert_dom_equal expected, output_buffer end + def test_nested_fields_for_with_an_empty_supplied_attributes_collection + form_for(:post, @post) do |f| + concat f.text_field(:title) + f.fields_for(:comments, []) do |cf| + concat cf.text_field(:name) + end + end + + expected = '<form action="http://www.example.com" method="post">' + + '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + + '</form>' + + assert_dom_equal expected, output_buffer + end + + def test_nested_fields_for_with_existing_records_on_a_supplied_nested_attributes_collection + @post.comments = Array.new(2) { |id| Comment.new(id + 1) } + + form_for(:post, @post) do |f| + concat f.text_field(:title) + f.fields_for(:comments, @post.comments) do |cf| + concat cf.text_field(:name) + end + end + + expected = '<form action="http://www.example.com" method="post">' + + '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + + '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' + + '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' + + '<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />' + + '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' + + '</form>' + + assert_dom_equal expected, output_buffer + end + def test_nested_fields_for_on_a_nested_attributes_collection_association_yields_only_builder @post.comments = [Comment.new(321), Comment.new] yielded_comments = [] diff --git a/actionpack/test/template/form_options_helper_test.rb b/actionpack/test/template/form_options_helper_test.rb index aa40e46aa8..f3cdab05bf 100644 --- a/actionpack/test/template/form_options_helper_test.rb +++ b/actionpack/test/template/form_options_helper_test.rb @@ -1,5 +1,5 @@ require 'abstract_unit' -require 'tzinfo' +require 'active_support/vendor/tzinfo' TZInfo::Timezone.cattr_reader :loaded_zones diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb index c86d5215cd..3c192906ae 100644 --- a/actionpack/test/template/render_test.rb +++ b/actionpack/test/template/render_test.rb @@ -33,18 +33,14 @@ module RenderTestCases end def test_render_file_with_localization - begin - old_locale = I18n.locale - I18n.locale = :da - assert_equal "Hey verden", @view.render(:file => "test/hello_world") - ensure - I18n.locale = old_locale - end + old_locale, I18n.locale = I18n.locale, :da + assert_equal "Hey verden", @view.render(:file => "test/hello_world") + ensure + I18n.locale = old_locale end def test_render_file_with_dashed_locale - old_locale = I18n.locale - I18n.locale = :"pt-BR" + old_locale, I18n.locale = I18n.locale, :"pt-BR" assert_equal "Ola mundo", @view.render(:file => "test/hello_world") ensure I18n.locale = old_locale diff --git a/actionpack/test/template/url_helper_test.rb b/actionpack/test/template/url_helper_test.rb index 0e24fbd24d..447d520ef1 100644 --- a/actionpack/test/template/url_helper_test.rb +++ b/actionpack/test/template/url_helper_test.rb @@ -1,5 +1,6 @@ # encoding: utf-8 require 'abstract_unit' +require 'controller/fake_controllers' RequestMock = Struct.new("Request", :request_uri, :protocol, :host_with_port, :env) @@ -367,25 +368,25 @@ class UrlHelperTest < ActionView::TestCase end end -class UrlHelperWithControllerTest < ActionView::TestCase - class UrlHelperController < ActionController::Base - def self.controller_path; 'url_helper_with_controller' end - - def show_url_for - render :inline => "<%= url_for :controller => 'url_helper_with_controller', :action => 'show_url_for' %>" - end +class UrlHelperController < ActionController::Base + def self.controller_path; 'url_helper_with_controller' end - def show_named_route - render :inline => "<%= show_named_route_#{params[:kind]} %>" - end + def show_url_for + render :inline => "<%= url_for :controller => 'url_helper_with_controller', :action => 'show_url_for' %>" + end - def nil_url_for - render :inline => '<%= url_for(nil) %>' - end + def show_named_route + render :inline => "<%= show_named_route_#{params[:kind]} %>" + end - def rescue_action(e) raise e end + def nil_url_for + render :inline => '<%= url_for(nil) %>' end + def rescue_action(e) raise e end +end + +class UrlHelperWithControllerTest < ActionView::TestCase tests ActionView::Helpers::UrlHelper def setup @@ -416,7 +417,7 @@ class UrlHelperWithControllerTest < ActionView::TestCase def test_url_for_nil_returns_current_path get :nil_url_for - assert_equal '/url_helper_with_controller/nil_url_for', @response.body + assert_equal '/url_helper/nil_url_for', @response.body end def test_named_route_should_show_host_and_path_using_controller_default_url_options @@ -436,35 +437,33 @@ class UrlHelperWithControllerTest < ActionView::TestCase def with_url_helper_routing with_routing do |set| set.draw do |map| - map.show_named_route 'url_helper_with_controller/show_named_route', :controller => 'url_helper_with_controller', :action => 'show_named_route' + map.show_named_route 'url_helper_with_controller/show_named_route', :controller => 'url_helper', :action => 'show_named_route' end yield end end end -class LinkToUnlessCurrentWithControllerTest < ActionView::TestCase - class TasksController < ActionController::Base - def self.controller_path; 'tasks' end - - def index - render_default - end +class TasksController < ActionController::Base + def index + render_default + end - def show - render_default - end + def show + render_default + end - def rescue_action(e) raise e end + def rescue_action(e) raise e end - protected - def render_default - render :inline => - "<%= link_to_unless_current(\"tasks\", tasks_path) %>\n" + - "<%= link_to_unless_current(\"tasks\", tasks_url) %>" - end - end + protected + def render_default + render :inline => + "<%= link_to_unless_current(\"tasks\", tasks_path) %>\n" + + "<%= link_to_unless_current(\"tasks\", tasks_url) %>" + end +end +class LinkToUnlessCurrentWithControllerTest < ActionView::TestCase tests ActionView::Helpers::UrlHelper def setup @@ -537,41 +536,37 @@ class Session end end -class PolymorphicControllerTest < ActionView::TestCase - class WorkshopsController < ActionController::Base - def self.controller_path; 'workshops' end - - def index - @workshop = Workshop.new(1, true) - render :inline => "<%= url_for(@workshop) %>\n<%= link_to('Workshop', @workshop) %>" - end - - def show - @workshop = Workshop.new(params[:id], false) - render :inline => "<%= url_for(@workshop) %>\n<%= link_to('Workshop', @workshop) %>" - end - - def rescue_action(e) raise e end +class WorkshopsController < ActionController::Base + def index + @workshop = Workshop.new(1, true) + render :inline => "<%= url_for(@workshop) %>\n<%= link_to('Workshop', @workshop) %>" end - class SessionsController < ActionController::Base - def self.controller_path; 'sessions' end + def show + @workshop = Workshop.new(params[:id], false) + render :inline => "<%= url_for(@workshop) %>\n<%= link_to('Workshop', @workshop) %>" + end - def index - @workshop = Workshop.new(params[:workshop_id], false) - @session = Session.new(1, true) - render :inline => "<%= url_for([@workshop, @session]) %>\n<%= link_to('Session', [@workshop, @session]) %>" - end + def rescue_action(e) raise e end +end - def show - @workshop = Workshop.new(params[:workshop_id], false) - @session = Session.new(params[:id], false) - render :inline => "<%= url_for([@workshop, @session]) %>\n<%= link_to('Session', [@workshop, @session]) %>" - end +class SessionsController < ActionController::Base + def index + @workshop = Workshop.new(params[:workshop_id], false) + @session = Session.new(1, true) + render :inline => "<%= url_for([@workshop, @session]) %>\n<%= link_to('Session', [@workshop, @session]) %>" + end - def rescue_action(e) raise e end + def show + @workshop = Workshop.new(params[:workshop_id], false) + @session = Session.new(params[:id], false) + render :inline => "<%= url_for([@workshop, @session]) %>\n<%= link_to('Session', [@workshop, @session]) %>" end + def rescue_action(e) raise e end +end + +class PolymorphicControllerTest < ActionView::TestCase tests ActionView::Helpers::UrlHelper def setup diff --git a/activemodel/MIT-LICENSE b/activemodel/MIT-LICENSE new file mode 100644 index 0000000000..e7accc5ea1 --- /dev/null +++ b/activemodel/MIT-LICENSE @@ -0,0 +1,21 @@ +Copyright (c) 2004-2009 David Heinemeier Hansson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/activemodel/Rakefile b/activemodel/Rakefile index ae2fbdb002..4a64c90dd9 100755 --- a/activemodel/Rakefile +++ b/activemodel/Rakefile @@ -1,7 +1,13 @@ -#!/usr/bin/env ruby -require 'rake' +require File.join(File.dirname(__FILE__), 'lib', 'active_model', 'version') + +PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : '' +PKG_NAME = 'activemodel' +PKG_VERSION = ActiveModel::VERSION::STRING + PKG_BUILD +PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}" +RELEASE_NAME = "REL #{PKG_VERSION}" + + require 'rake/testtask' -require 'rake/rdoctask' task :default => :test @@ -9,14 +15,19 @@ Rake::TestTask.new do |t| t.libs << "test" t.test_files = Dir.glob("test/cases/**/*_test.rb").sort t.verbose = true + t.warning = true end + task :isolated_test do ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')) Dir.glob("test/**/*_test.rb").all? do |file| - system(ruby, '-Ilib:test', file) + system(ruby, '-w', '-Ilib:test', file) end or raise "Failures" end + +require 'rake/rdoctask' + # Generate the RDoc documentation Rake::RDocTask.new do |rdoc| rdoc.rdoc_dir = 'doc' @@ -27,3 +38,39 @@ Rake::RDocTask.new do |rdoc| rdoc.rdoc_files.include('README', 'CHANGES') rdoc.rdoc_files.include('lib/**/*.rb') end + + +require 'rake/packagetask' +require 'rake/gempackagetask' + +spec = Gem::Specification.new do |s| + s.platform = Gem::Platform::RUBY + s.name = PKG_NAME + s.version = PKG_VERSION + s.summary = "A toolkit for building other modeling frameworks like ActiveRecord" + s.description = %q{Extracts common modeling concerns from ActiveRecord to share between similar frameworks like ActiveResource.} + + s.author = "David Heinemeier Hansson" + s.email = "david@loudthinking.com" + s.rubyforge_project = "activemodel" + s.homepage = "http://www.rubyonrails.org" + + s.has_rdoc = true + + s.add_dependency('activesupport', '= 3.0.pre' + PKG_BUILD) + + s.require_path = 'lib' + s.files = Dir["CHANGELOG", "MIT-LICENSE", "README", "Rakefile", "lib/**/*", "test/**/*"] +end + +Rake::GemPackageTask.new(spec) do |p| + p.gem_spec = spec + p.need_tar = true + p.need_zip = true +end + +task :gemspec do + File.open(File.join(File.dirname(__FILE__), "#{spec.name}.gemspec"), "w") do |file| + file.puts spec.to_ruby + end +end
\ No newline at end of file diff --git a/activemodel/activemodel.gemspec b/activemodel/activemodel.gemspec new file mode 100644 index 0000000000..e96718e6fd --- /dev/null +++ b/activemodel/activemodel.gemspec @@ -0,0 +1,31 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{activemodel} + s.version = "3.0.pre" + + s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version= + s.authors = ["David Heinemeier Hansson"] + s.date = %q{2009-09-01} + s.description = %q{Extracts common modeling concerns from ActiveRecord to share between similar frameworks like ActiveResource.} + s.email = %q{david@loudthinking.com} + s.files = ["CHANGELOG", "MIT-LICENSE", "README", "Rakefile", "lib/active_model", "lib/active_model/attribute_methods.rb", "lib/active_model/conversion.rb", "lib/active_model/deprecated_error_methods.rb", "lib/active_model/dirty.rb", "lib/active_model/errors.rb", "lib/active_model/lint.rb", "lib/active_model/locale", "lib/active_model/locale/en.yml", "lib/active_model/naming.rb", "lib/active_model/observing.rb", "lib/active_model/serialization.rb", "lib/active_model/serializers", "lib/active_model/serializers/json.rb", "lib/active_model/serializers/xml.rb", "lib/active_model/state_machine", "lib/active_model/state_machine/event.rb", "lib/active_model/state_machine/machine.rb", "lib/active_model/state_machine/state.rb", "lib/active_model/state_machine/state_transition.rb", "lib/active_model/state_machine.rb", "lib/active_model/test_case.rb", "lib/active_model/validations", "lib/active_model/validations/acceptance.rb", "lib/active_model/validations/confirmation.rb", "lib/active_model/validations/exclusion.rb", "lib/active_model/validations/format.rb", "lib/active_model/validations/inclusion.rb", "lib/active_model/validations/length.rb", "lib/active_model/validations/numericality.rb", "lib/active_model/validations/presence.rb", "lib/active_model/validations/with.rb", "lib/active_model/validations.rb", "lib/active_model/validations_repair_helper.rb", "lib/active_model/version.rb", "lib/active_model.rb", "lib/activemodel.rb", "test/cases", "test/cases/helper.rb", "test/cases/lint_test.rb", "test/cases/naming_test.rb", "test/cases/observing_test.rb", "test/cases/serializeration", "test/cases/serializeration/json_serialization_test.rb", "test/cases/serializeration/xml_serialization_test.rb", "test/cases/state_machine", "test/cases/state_machine/event_test.rb", "test/cases/state_machine/machine_test.rb", "test/cases/state_machine/state_test.rb", "test/cases/state_machine/state_transition_test.rb", "test/cases/state_machine_test.rb", "test/cases/tests_database.rb", "test/cases/validations", "test/cases/validations/acceptance_validation_test.rb", "test/cases/validations/conditional_validation_test.rb", "test/cases/validations/confirmation_validation_test.rb", "test/cases/validations/exclusion_validation_test.rb", "test/cases/validations/format_validation_test.rb", "test/cases/validations/i18n_generate_message_validation_test.rb", "test/cases/validations/i18n_validation_test.rb", "test/cases/validations/inclusion_validation_test.rb", "test/cases/validations/length_validation_test.rb", "test/cases/validations/numericality_validation_test.rb", "test/cases/validations/presence_validation_test.rb", "test/cases/validations/with_validation_test.rb", "test/cases/validations_test.rb", "test/config.rb", "test/fixtures", "test/fixtures/topics.yml", "test/models", "test/models/contact.rb", "test/models/custom_reader.rb", "test/models/developer.rb", "test/models/person.rb", "test/models/reply.rb", "test/models/topic.rb", "test/schema.rb"] + s.homepage = %q{http://www.rubyonrails.org} + s.require_paths = ["lib"] + s.rubyforge_project = %q{activemodel} + s.rubygems_version = %q{1.3.5} + s.summary = %q{A toolkit for building other modeling frameworks like ActiveRecord} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 3 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q<activesupport>, ["= 3.0.pre"]) + else + s.add_dependency(%q<activesupport>, ["= 3.0.pre"]) + end + else + s.add_dependency(%q<activesupport>, ["= 3.0.pre"]) + end +end diff --git a/activemodel/examples/validations.rb b/activemodel/examples/validations.rb index 3f8311ff96..b039897ea5 100644 --- a/activemodel/examples/validations.rb +++ b/activemodel/examples/validations.rb @@ -1,4 +1,4 @@ -require 'activemodel' +require 'active_model' class Person include ActiveModel::Conversion diff --git a/activemodel/lib/active_model.rb b/activemodel/lib/active_model.rb index 5bb931be7f..67f529262d 100644 --- a/activemodel/lib/active_model.rb +++ b/activemodel/lib/active_model.rb @@ -41,6 +41,7 @@ module ActiveModel autoload :TestCase, 'active_model/test_case' autoload :Validations, 'active_model/validations' autoload :ValidationsRepairHelper, 'active_model/validations_repair_helper' + autoload :VERSION, 'active_model/version' module Serializers autoload :JSON, 'active_model/serializers/json' diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb index 1091ad3095..aa35a2726e 100644 --- a/activemodel/lib/active_model/attribute_methods.rb +++ b/activemodel/lib/active_model/attribute_methods.rb @@ -181,7 +181,7 @@ module ActiveModel end def attribute_methods_generated? - @attribute_methods_generated ? true : false + @attribute_methods_generated ||= nil end protected diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index 1a3d120761..7a48960f89 100644 --- a/activemodel/lib/active_model/errors.rb +++ b/activemodel/lib/active_model/errors.rb @@ -1,7 +1,8 @@ require 'active_support/core_ext/string/inflections' +require 'active_support/ordered_hash' module ActiveModel - class Errors < Hash + class Errors < ActiveSupport::OrderedHash include DeprecatedErrorMethods def initialize(base) diff --git a/activemodel/lib/active_model/lint.rb b/activemodel/lib/active_model/lint.rb index 46af8ca9de..478f887043 100644 --- a/activemodel/lib/active_model/lint.rb +++ b/activemodel/lib/active_model/lint.rb @@ -2,7 +2,7 @@ require "test/unit" require "test/unit/ui/console/testrunner" # You can test whether an object is compliant with the ActiveModel API by -# calling ActiveModel::Compliance.test(object). It will emit a Test::Unit +# calling ActiveModel::Lint.test(object). It will emit a Test::Unit # output that tells you whether your object is fully compliant, or if not, # which aspects of the API are not implemented. # @@ -13,7 +13,6 @@ require "test/unit/ui/console/testrunner" # # Objects you pass in are expected to return a compliant object from a # call to to_model. It is perfectly fine for to_model to return self. - module ActiveModel module Lint def self.test(object, verbosity = 2, output = STDOUT) @@ -59,7 +58,7 @@ module ActiveModel end def test_destroyed? - assert @object.respond_to?(:new_record?), "The model should respond to destroyed?" + assert @object.respond_to?(:destroyed?), "The model should respond to destroyed?" assert_boolean "destroyed?", @object.destroyed? end @@ -93,4 +92,4 @@ module ActiveModel include Errors end end -end
\ No newline at end of file +end diff --git a/activemodel/lib/active_model/observing.rb b/activemodel/lib/active_model/observing.rb index 3b230c43b9..d9d1ab8967 100644 --- a/activemodel/lib/active_model/observing.rb +++ b/activemodel/lib/active_model/observing.rb @@ -40,23 +40,6 @@ module ActiveModel observers.each { |o| instantiate_observer(o) } end - # Wraps methods with before and after notifications. - # - # wrap_with_notifications :create, :save, :update, :destroy - def wrap_with_notifications(*methods) - methods.each do |method| - class_eval(<<-EOS, __FILE__, __LINE__ + 1) - def #{method}_with_notifications(*args, &block) - notify_observers(:before_#{method}) - result = #{method}_without_notifications(*args, &block) - notify_observers(:after_#{method}) - result - end - EOS - alias_method_chain(method, :notifications) - end - end - protected def instantiate_observer(observer) #:nodoc: # string/symbol diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb index 7d49e60790..edeb508a08 100644 --- a/activemodel/lib/active_model/validations.rb +++ b/activemodel/lib/active_model/validations.rb @@ -6,10 +6,10 @@ require 'active_support/callbacks' module ActiveModel module Validations extend ActiveSupport::Concern - include ActiveSupport::Callbacks + include ActiveSupport::NewCallbacks included do - define_callbacks :validate + define_callbacks :validate, :scope => :name end module ClassMethods @@ -64,7 +64,7 @@ module ActiveModel attrs = attrs.flatten # Declare the validation. - send(validation_method(options[:on]), options) do |record| + validate options do |record| attrs.each do |attr| value = record.send(:read_attribute_for_validation, attr) next if (value.nil? && options[:allow_nil]) || (value.blank? && options[:allow_blank]) @@ -73,10 +73,14 @@ module ActiveModel end end - private - def validation_method(on) - :validate + def validate(*args, &block) + options = args.last + if options.is_a?(Hash) && options.key?(:on) + options[:if] = Array(options[:if]) + options[:if] << "@_on_validate == :#{options[:on]}" end + set_callback(:validate, *args, &block) + end end # Returns the Errors object that holds all information about attribute error messages. @@ -87,7 +91,7 @@ module ActiveModel # Runs all the specified validations and returns true if no errors were added otherwise false. def valid? errors.clear - run_callbacks(:validate) + _run_validate_callbacks errors.empty? end diff --git a/activemodel/lib/active_model/validations/presence.rb b/activemodel/lib/active_model/validations/presence.rb index 72d6b1c6f0..3ff677c137 100644 --- a/activemodel/lib/active_model/validations/presence.rb +++ b/activemodel/lib/active_model/validations/presence.rb @@ -32,7 +32,7 @@ module ActiveModel # can't use validates_each here, because it cannot cope with nonexistent attributes, # while errors.add_on_empty can - send(validation_method(configuration[:on]), configuration) do |record| + validate configuration do |record| record.errors.add_on_blank(attr_names, configuration[:message]) end end diff --git a/activemodel/lib/active_model/validations/with.rb b/activemodel/lib/active_model/validations/with.rb index 851cdfebf0..edc2133ddc 100644 --- a/activemodel/lib/active_model/validations/with.rb +++ b/activemodel/lib/active_model/validations/with.rb @@ -51,7 +51,7 @@ module ActiveModel def validates_with(*args) configuration = args.extract_options! - send(validation_method(configuration[:on]), configuration) do |record| + validate configuration do |record| args.each do |klass| klass.new(record, configuration.except(:on, :if, :unless)).validate end diff --git a/activemodel/lib/active_model/validations_repair_helper.rb b/activemodel/lib/active_model/validations_repair_helper.rb index 432e411308..40741e6dbe 100644 --- a/activemodel/lib/active_model/validations_repair_helper.rb +++ b/activemodel/lib/active_model/validations_repair_helper.rb @@ -2,43 +2,34 @@ module ActiveModel module ValidationsRepairHelper extend ActiveSupport::Concern - module Toolbox - def self.record_validations(*model_classes) - model_classes.inject({}) do |repair, klass| - repair[klass] ||= {} - [:validate, :validate_on_create, :validate_on_update].each do |callback| - the_callback = klass.instance_variable_get("@#{callback.to_s}_callbacks") - repair[klass][callback] = (the_callback.nil? ? nil : the_callback.dup) - end - repair - end - end - - def self.reset_validations(recorded) - recorded.each do |klass, repairs| - [:validate, :validate_on_create, :validate_on_update].each do |callback| - klass.instance_variable_set("@#{callback.to_s}_callbacks", repairs[callback]) - end - end - end - end - module ClassMethods def repair_validations(*model_classes) setup do - @validation_repairs = Toolbox.record_validations(*model_classes) + @_stored_callbacks = {} + model_classes.each do |k| + @_stored_callbacks[k] = k._validate_callbacks.dup + end end teardown do - Toolbox.reset_validations(@validation_repairs) + model_classes.each do |k| + k._validate_callbacks = @_stored_callbacks[k] + k.__update_callbacks(:validate) + end end end end def repair_validations(*model_classes, &block) - validation_repairs = Toolbox.record_validations(*model_classes) + @__stored_callbacks = {} + model_classes.each do |k| + @__stored_callbacks[k] = k._validate_callbacks.dup + end return block.call ensure - Toolbox.reset_validations(validation_repairs) + model_classes.each do |k| + k._validate_callbacks = @__stored_callbacks[k] + k.__update_callbacks(:validate) + end end end end diff --git a/activemodel/lib/active_model/version.rb b/activemodel/lib/active_model/version.rb new file mode 100644 index 0000000000..0c233b7b4f --- /dev/null +++ b/activemodel/lib/active_model/version.rb @@ -0,0 +1,9 @@ +module ActiveModel + module VERSION #:nodoc: + MAJOR = 3 + MINOR = 0 + TINY = "pre" + + STRING = [MAJOR, MINOR, TINY].join('.') + end +end diff --git a/activemodel/lib/activemodel.rb b/activemodel/lib/activemodel.rb deleted file mode 100644 index da3133103b..0000000000 --- a/activemodel/lib/activemodel.rb +++ /dev/null @@ -1 +0,0 @@ -require 'active_model' diff --git a/activemodel/test/cases/observing_test.rb b/activemodel/test/cases/observing_test.rb index fbf93c19ef..e23bda0528 100644 --- a/activemodel/test/cases/observing_test.rb +++ b/activemodel/test/cases/observing_test.rb @@ -78,6 +78,7 @@ class ObserverTest < ActiveModel::TestCase def teardown FooObserver.instance_eval do + undef_method :observed_classes alias_method :observed_classes, :original_observed_classes end end diff --git a/activemodel/test/cases/serializeration/json_serialization_test.rb b/activemodel/test/cases/serializeration/json_serialization_test.rb index 6227aedc39..81df52fcb9 100644 --- a/activemodel/test/cases/serializeration/json_serialization_test.rb +++ b/activemodel/test/cases/serializeration/json_serialization_test.rb @@ -1,12 +1,14 @@ require 'cases/helper' require 'models/contact' +require 'active_support/core_ext/object/instance_variables' class Contact + extend ActiveModel::Naming include ActiveModel::Serializers::JSON def attributes instance_values - end + end unless method_defined?(:attributes) end class JsonSerializationTest < ActiveModel::TestCase diff --git a/activemodel/test/cases/serializeration/xml_serialization_test.rb b/activemodel/test/cases/serializeration/xml_serialization_test.rb index 428e5a6bd1..6340aad531 100644 --- a/activemodel/test/cases/serializeration/xml_serialization_test.rb +++ b/activemodel/test/cases/serializeration/xml_serialization_test.rb @@ -1,12 +1,14 @@ require 'cases/helper' require 'models/contact' +require 'active_support/core_ext/object/instance_variables' class Contact + extend ActiveModel::Naming include ActiveModel::Serializers::Xml def attributes instance_values - end + end unless method_defined?(:attributes) end module Admin diff --git a/activemodel/test/cases/validations/i18n_generate_message_validation_test.rb b/activemodel/test/cases/validations/i18n_generate_message_validation_test.rb index 37bba5e95e..07e4341289 100644 --- a/activemodel/test/cases/validations/i18n_generate_message_validation_test.rb +++ b/activemodel/test/cases/validations/i18n_generate_message_validation_test.rb @@ -5,7 +5,7 @@ require 'models/person' class I18nGenerateMessageValidationTest < Test::Unit::TestCase def setup - reset_callbacks Person + Person.reset_callbacks(:validate) @person = Person.new @old_load_path, @old_backend = I18n.load_path, I18n.backend @@ -45,12 +45,6 @@ class I18nGenerateMessageValidationTest < Test::Unit::TestCase I18n.backend = @old_backend end - def reset_callbacks(*models) - models.each do |model| - model.instance_variable_set("@validate_callbacks", ActiveSupport::Callbacks::CallbackChain.new) - end - end - # validates_inclusion_of: generate_message(attr_name, :inclusion, :default => configuration[:message], :value => value) def test_generate_message_inclusion_with_default_message assert_equal 'is not included in the list', @person.errors.generate_message(:title, :inclusion, :default => nil, :value => 'title') diff --git a/activemodel/test/cases/validations/i18n_validation_test.rb b/activemodel/test/cases/validations/i18n_validation_test.rb index cc68d847a2..fc4f1926b0 100644 --- a/activemodel/test/cases/validations/i18n_validation_test.rb +++ b/activemodel/test/cases/validations/i18n_validation_test.rb @@ -7,8 +7,7 @@ class I18nValidationTest < ActiveModel::TestCase include ActiveModel::TestsDatabase def setup - reset_callbacks Person - + Person.reset_callbacks(:validate) @person = Person.new @old_load_path, @old_backend = I18n.load_path, I18n.backend @@ -18,17 +17,11 @@ class I18nValidationTest < ActiveModel::TestCase end def teardown - reset_callbacks Person + Person.reset_callbacks(:validate) I18n.load_path.replace @old_load_path I18n.backend = @old_backend end - def reset_callbacks(*models) - models.each do |model| - model.instance_variable_set("@validate_callbacks", ActiveSupport::Callbacks::CallbackChain.new) - end - end - def test_percent_s_interpolation_syntax_in_error_messages_was_deprecated assert_not_deprecated do default = "%s interpolation syntax was deprecated" @@ -107,32 +100,6 @@ class I18nValidationTest < ActiveModel::TestCase @person.valid? end - def test_validates_length_of_within_generates_message_with_title_too_short - Person.validates_length_of :title, :within => 3..5 - @person.errors.expects(:generate_message).with(:title, :too_short, {:count => 3, :default => nil}) - @person.valid? - end - - def test_validates_length_of_within_generates_message_with_title_too_short_and_custom_default_message - Person.validates_length_of :title, :within => 3..5, :too_short => 'custom' - @person.errors.expects(:generate_message).with(:title, :too_short, {:count => 3, :default => 'custom'}) - @person.valid? - end - - def test_validates_length_of_within_generates_message_with_title_too_long - Person.validates_length_of :title, :within => 3..5 - @person.title = 'this title is too long' - @person.errors.expects(:generate_message).with(:title, :too_long, {:count => 5, :default => nil}) - @person.valid? - end - - def test_validates_length_of_within_generates_message_with_title_too_long_and_custom_default_message - Person.validates_length_of :title, :within => 3..5, :too_long => 'custom' - @person.title = 'this title is too long' - @person.errors.expects(:generate_message).with(:title, :too_long, {:count => 5, :default => 'custom'}) - @person.valid? - end - # validates_length_of :within w/ mocha def test_validates_length_of_within_generates_message_with_title_too_short @@ -280,7 +247,7 @@ class I18nValidationTest < ActiveModel::TestCase @person.valid? end - def test_validates_numericality_of_odd_generates_message_with_custom_default_message + def test_validates_numericality_of_less_than_odd_generates_message_with_custom_default_message Person.validates_numericality_of :title, :only_integer => true, :less_than => 0, :message => 'custom' @person.title = 1 @person.errors.expects(:generate_message).with(:title, :less_than, {:value => 1, :count => 0, :default => 'custom'}) @@ -384,24 +351,6 @@ class I18nValidationTest < ActiveModel::TestCase assert_equal ['global message'], @person.errors[:title] end - def test_validates_length_of_is_finds_custom_model_key_translation - I18n.backend.store_translations 'en', :activemodel => {:errors => {:models => {:person => {:attributes => {:title => {:wrong_length => 'custom message'}}}}}} - I18n.backend.store_translations 'en', :activemodel => {:errors => {:messages => {:wrong_length => 'global message'}}} - - Person.validates_length_of :title, :is => 5 - @person.valid? - assert_equal ['custom message'], @person.errors[:title] - end - - def test_validates_length_of_is_finds_global_default_translation - I18n.backend.store_translations 'en', :activemodel => {:errors => {:messages => {:wrong_length => 'global message'}}} - - Person.validates_length_of :title, :is => 5 - @person.valid? - assert_equal ['global message'], @person.errors[:title] - end - - # validates_format_of w/o mocha def test_validates_format_of_finds_custom_model_key_translation @@ -576,4 +525,4 @@ class I18nValidationTest < ActiveModel::TestCase assert_equal ["I am a custom error"], @person.errors[:title] end -end
\ No newline at end of file +end diff --git a/activemodel/test/cases/validations/presence_validation_test.rb b/activemodel/test/cases/validations/presence_validation_test.rb index bb6fb91774..90b0951a77 100644 --- a/activemodel/test/cases/validations/presence_validation_test.rb +++ b/activemodel/test/cases/validations/presence_validation_test.rb @@ -5,6 +5,7 @@ require 'cases/tests_database' require 'models/topic' require 'models/developer' require 'models/person' +require 'models/custom_reader' class PresenceValidationTest < ActiveModel::TestCase include ActiveModel::TestsDatabase diff --git a/activemodel/test/cases/validations/with_validation_test.rb b/activemodel/test/cases/validations/with_validation_test.rb index f55fdc5864..c290b49a28 100644 --- a/activemodel/test/cases/validations/with_validation_test.rb +++ b/activemodel/test/cases/validations/with_validation_test.rb @@ -1,9 +1,11 @@ # encoding: utf-8 require 'cases/helper' +require 'cases/tests_database' require 'models/topic' class ValidatesWithTest < ActiveRecord::TestCase + include ActiveModel::TestsDatabase include ActiveModel::ValidationsRepairHelper repair_validations(Topic) diff --git a/activemodel/test/cases/validations_test.rb b/activemodel/test/cases/validations_test.rb index 0b340e68bf..78565177d8 100644 --- a/activemodel/test/cases/validations_test.rb +++ b/activemodel/test/cases/validations_test.rb @@ -121,8 +121,8 @@ class ValidationsTest < ActiveModel::TestCase end def test_invalid_validator - Topic.validate 3 - assert_raise(ArgumentError) { t = Topic.create } + Topic.validate :i_dont_exist + assert_raise(NameError) { t = Topic.create } end def test_errors_to_xml @@ -141,6 +141,22 @@ class ValidationsTest < ActiveModel::TestCase t = Topic.new("title" => "") assert !t.valid? assert_equal "can't be blank", t.errors["title"].first + Topic.validates_presence_of :title, :author_name + Topic.validate {|topic| topic.errors.add('author_email_address', 'will never be valid')} + Topic.validates_length_of :title, :content, :minimum => 2 + + t = Topic.new :title => '' + assert !t.valid? + + assert_equal :title, key = t.errors.keys.first + assert_equal "can't be blank", t.errors[key].first + assert_equal 'is too short (minimum is 2 characters)', t.errors[key].second + assert_equal :author_name, key = t.errors.keys.second + assert_equal "can't be blank", t.errors[key].first + assert_equal :author_email_address, key = t.errors.keys.third + assert_equal 'will never be valid', t.errors[key].first + assert_equal :content, key = t.errors.keys.fourth + assert_equal 'is too short (minimum is 2 characters)', t.errors[key].first end def test_invalid_should_be_the_opposite_of_valid @@ -189,4 +205,4 @@ class ValidationsTest < ActiveModel::TestCase all_errors = t.errors.to_a assert_deprecated { assert_equal all_errors, t.errors.each_full{|err| err} } end -end
\ No newline at end of file +end diff --git a/activemodel/test/models/reply.rb b/activemodel/test/models/reply.rb index acfd801674..e86692677f 100644 --- a/activemodel/test/models/reply.rb +++ b/activemodel/test/models/reply.rb @@ -2,11 +2,11 @@ require 'models/topic' class Reply < Topic validate :errors_on_empty_content - validate_on_create :title_is_wrong_create + validate :title_is_wrong_create, :on => :create validate :check_empty_title - validate_on_create :check_content_mismatch - validate_on_update :check_wrong_update + validate :check_content_mismatch, :on => :create + validate :check_wrong_update, :on => :update attr_accessible :title, :author_name, :author_email_address, :written_on, :content, :last_read diff --git a/activerecord/Rakefile b/activerecord/Rakefile index a9e4a92e37..aa2c998d07 100644 --- a/activerecord/Rakefile +++ b/activerecord/Rakefile @@ -208,6 +208,7 @@ spec = Gem::Specification.new do |s| end s.add_dependency('activesupport', '= 3.0.pre' + PKG_BUILD) + s.add_dependency('activemodel', '= 3.0.pre' + PKG_BUILD) s.files.delete FIXTURES_ROOT + "/fixture_database.sqlite" s.files.delete FIXTURES_ROOT + "/fixture_database_2.sqlite" @@ -232,6 +233,12 @@ Rake::GemPackageTask.new(spec) do |p| p.need_zip = true end +task :gemspec do + File.open(File.join(File.dirname(__FILE__), "#{spec.name}.gemspec"), "w") do |file| + file.puts spec.to_ruby + end +end + task :lines do lines, codelines, total_lines, total_codelines = 0, 0, 0, 0 diff --git a/activerecord/activerecord.gemspec b/activerecord/activerecord.gemspec new file mode 100644 index 0000000000..af61f18fe8 --- /dev/null +++ b/activerecord/activerecord.gemspec @@ -0,0 +1,37 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{activerecord} + s.version = "3.0.pre" + + s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version= + s.authors = ["David Heinemeier Hansson"] + s.autorequire = %q{active_record} + s.date = %q{2009-09-01} + s.description = %q{Implements the ActiveRecord pattern (Fowler, PoEAA) for ORM. It ties database tables and classes together for business objects, like Customer or Subscription, that can find, save, and destroy themselves without resorting to manual SQL.} + s.email = %q{david@loudthinking.com} + s.extra_rdoc_files = ["README"] + s.files = ["Rakefile", "install.rb", "README", "RUNNING_UNIT_TESTS", "CHANGELOG", "lib/active_record", "lib/active_record/aggregations.rb", "lib/active_record/association_preload.rb", "lib/active_record/associations", "lib/active_record/associations/association_collection.rb", "lib/active_record/associations/association_proxy.rb", "lib/active_record/associations/belongs_to_association.rb", "lib/active_record/associations/belongs_to_polymorphic_association.rb", "lib/active_record/associations/has_and_belongs_to_many_association.rb", "lib/active_record/associations/has_many_association.rb", "lib/active_record/associations/has_many_through_association.rb", "lib/active_record/associations/has_one_association.rb", "lib/active_record/associations/has_one_through_association.rb", "lib/active_record/associations/through_association_scope.rb", "lib/active_record/associations.rb", "lib/active_record/attribute_methods", "lib/active_record/attribute_methods/before_type_cast.rb", "lib/active_record/attribute_methods/dirty.rb", "lib/active_record/attribute_methods/primary_key.rb", "lib/active_record/attribute_methods/query.rb", "lib/active_record/attribute_methods/read.rb", "lib/active_record/attribute_methods/time_zone_conversion.rb", "lib/active_record/attribute_methods/write.rb", "lib/active_record/attribute_methods.rb", "lib/active_record/autosave_association.rb", "lib/active_record/base.rb", "lib/active_record/batches.rb", "lib/active_record/calculations.rb", "lib/active_record/callbacks.rb", "lib/active_record/connection_adapters", "lib/active_record/connection_adapters/abstract", "lib/active_record/connection_adapters/abstract/connection_pool.rb", "lib/active_record/connection_adapters/abstract/connection_specification.rb", "lib/active_record/connection_adapters/abstract/database_statements.rb", "lib/active_record/connection_adapters/abstract/query_cache.rb", "lib/active_record/connection_adapters/abstract/quoting.rb", "lib/active_record/connection_adapters/abstract/schema_definitions.rb", "lib/active_record/connection_adapters/abstract/schema_statements.rb", "lib/active_record/connection_adapters/abstract_adapter.rb", "lib/active_record/connection_adapters/mysql_adapter.rb", "lib/active_record/connection_adapters/postgresql_adapter.rb", "lib/active_record/connection_adapters/sqlite3_adapter.rb", "lib/active_record/connection_adapters/sqlite_adapter.rb", "lib/active_record/dynamic_finder_match.rb", "lib/active_record/dynamic_scope_match.rb", "lib/active_record/fixtures.rb", "lib/active_record/locale", "lib/active_record/locale/en.yml", "lib/active_record/locking", "lib/active_record/locking/optimistic.rb", "lib/active_record/locking/pessimistic.rb", "lib/active_record/migration.rb", "lib/active_record/named_scope.rb", "lib/active_record/nested_attributes.rb", "lib/active_record/observer.rb", "lib/active_record/query_cache.rb", "lib/active_record/reflection.rb", "lib/active_record/schema.rb", "lib/active_record/schema_dumper.rb", "lib/active_record/serialization.rb", "lib/active_record/serializers", "lib/active_record/serializers/xml_serializer.rb", "lib/active_record/session_store.rb", "lib/active_record/state_machine.rb", "lib/active_record/test_case.rb", "lib/active_record/timestamp.rb", "lib/active_record/transactions.rb", "lib/active_record/validations", "lib/active_record/validations/associated.rb", "lib/active_record/validations/uniqueness.rb", "lib/active_record/validations.rb", "lib/active_record/validator.rb", "lib/active_record/version.rb", "lib/active_record.rb", "lib/activerecord.rb", "test/assets", "test/assets/example.log", "test/assets/flowers.jpg", "test/cases", "test/cases/active_schema_test_mysql.rb", "test/cases/active_schema_test_postgresql.rb", "test/cases/adapter_test.rb", "test/cases/aggregations_test.rb", "test/cases/ar_schema_test.rb", "test/cases/associations", "test/cases/associations/belongs_to_associations_test.rb", "test/cases/associations/callbacks_test.rb", "test/cases/associations/cascaded_eager_loading_test.rb", "test/cases/associations/eager_load_includes_full_sti_class_test.rb", "test/cases/associations/eager_load_nested_include_test.rb", "test/cases/associations/eager_singularization_test.rb", "test/cases/associations/eager_test.rb", "test/cases/associations/extension_test.rb", "test/cases/associations/habtm_join_table_test.rb", "test/cases/associations/has_and_belongs_to_many_associations_test.rb", "test/cases/associations/has_many_associations_test.rb", "test/cases/associations/has_many_through_associations_test.rb", "test/cases/associations/has_one_associations_test.rb", "test/cases/associations/has_one_through_associations_test.rb", "test/cases/associations/inner_join_association_test.rb", "test/cases/associations/inverse_associations_test.rb", "test/cases/associations/join_model_test.rb", "test/cases/associations_test.rb", "test/cases/attribute_methods_test.rb", "test/cases/autosave_association_test.rb", "test/cases/base_test.rb", "test/cases/batches_test.rb", "test/cases/binary_test.rb", "test/cases/calculations_test.rb", "test/cases/callbacks_observers_test.rb", "test/cases/callbacks_test.rb", "test/cases/class_inheritable_attributes_test.rb", "test/cases/column_alias_test.rb", "test/cases/column_definition_test.rb", "test/cases/connection_pool_test.rb", "test/cases/connection_test_firebird.rb", "test/cases/connection_test_mysql.rb", "test/cases/copy_table_test_sqlite.rb", "test/cases/database_statements_test.rb", "test/cases/datatype_test_postgresql.rb", "test/cases/date_time_test.rb", "test/cases/default_test_firebird.rb", "test/cases/defaults_test.rb", "test/cases/deprecated_finder_test.rb", "test/cases/dirty_test.rb", "test/cases/finder_respond_to_test.rb", "test/cases/finder_test.rb", "test/cases/fixtures_test.rb", "test/cases/helper.rb", "test/cases/i18n_test.rb", "test/cases/inheritance_test.rb", "test/cases/invalid_date_test.rb", "test/cases/json_serialization_test.rb", "test/cases/lifecycle_test.rb", "test/cases/locking_test.rb", "test/cases/method_scoping_test.rb", "test/cases/migration_test.rb", "test/cases/migration_test_firebird.rb", "test/cases/mixin_test.rb", "test/cases/modules_test.rb", "test/cases/multiple_db_test.rb", "test/cases/named_scope_test.rb", "test/cases/nested_attributes_test.rb", "test/cases/pk_test.rb", "test/cases/pooled_connections_test.rb", "test/cases/query_cache_test.rb", "test/cases/readonly_test.rb", "test/cases/reflection_test.rb", "test/cases/reload_models_test.rb", "test/cases/repair_helper.rb", "test/cases/reserved_word_test_mysql.rb", "test/cases/sanitize_test.rb", "test/cases/schema_authorization_test_postgresql.rb", "test/cases/schema_dumper_test.rb", "test/cases/schema_test_postgresql.rb", "test/cases/serialization_test.rb", "test/cases/state_machine_test.rb", "test/cases/synonym_test_oracle.rb", "test/cases/timestamp_test.rb", "test/cases/transactions_test.rb", "test/cases/unconnected_test.rb", "test/cases/validations", "test/cases/validations/association_validation_test.rb", "test/cases/validations/i18n_generate_message_validation_test.rb", "test/cases/validations/i18n_validation_test.rb", "test/cases/validations/uniqueness_validation_test.rb", "test/cases/validations_test.rb", "test/cases/xml_serialization_test.rb", "test/config.rb", "test/connections", "test/connections/jdbc_jdbcderby", "test/connections/jdbc_jdbcderby/connection.rb", "test/connections/jdbc_jdbch2", "test/connections/jdbc_jdbch2/connection.rb", "test/connections/jdbc_jdbchsqldb", "test/connections/jdbc_jdbchsqldb/connection.rb", "test/connections/jdbc_jdbcmysql", "test/connections/jdbc_jdbcmysql/connection.rb", "test/connections/jdbc_jdbcpostgresql", "test/connections/jdbc_jdbcpostgresql/connection.rb", "test/connections/jdbc_jdbcsqlite3", "test/connections/jdbc_jdbcsqlite3/connection.rb", "test/connections/native_db2", "test/connections/native_db2/connection.rb", "test/connections/native_firebird", "test/connections/native_firebird/connection.rb", "test/connections/native_frontbase", "test/connections/native_frontbase/connection.rb", "test/connections/native_mysql", "test/connections/native_mysql/connection.rb", "test/connections/native_openbase", "test/connections/native_openbase/connection.rb", "test/connections/native_oracle", "test/connections/native_oracle/connection.rb", "test/connections/native_postgresql", "test/connections/native_postgresql/connection.rb", "test/connections/native_sqlite3", "test/connections/native_sqlite3/connection.rb", "test/connections/native_sqlite3/in_memory_connection.rb", "test/connections/native_sybase", "test/connections/native_sybase/connection.rb", "test/fixtures", "test/fixtures/accounts.yml", "test/fixtures/all", "test/fixtures/all/developers.yml", "test/fixtures/all/people.csv", "test/fixtures/all/tasks.yml", "test/fixtures/author_addresses.yml", "test/fixtures/author_favorites.yml", "test/fixtures/authors.yml", "test/fixtures/binaries.yml", "test/fixtures/books.yml", "test/fixtures/categories", "test/fixtures/categories/special_categories.yml", "test/fixtures/categories/subsubdir", "test/fixtures/categories/subsubdir/arbitrary_filename.yml", "test/fixtures/categories.yml", "test/fixtures/categories_ordered.yml", "test/fixtures/categories_posts.yml", "test/fixtures/categorizations.yml", "test/fixtures/clubs.yml", "test/fixtures/comments.yml", "test/fixtures/companies.yml", "test/fixtures/computers.yml", "test/fixtures/courses.yml", "test/fixtures/customers.yml", "test/fixtures/developers.yml", "test/fixtures/developers_projects.yml", "test/fixtures/edges.yml", "test/fixtures/entrants.yml", "test/fixtures/faces.yml", "test/fixtures/fixture_database.sqlite3", "test/fixtures/fixture_database_2.sqlite3", "test/fixtures/fk_test_has_fk.yml", "test/fixtures/fk_test_has_pk.yml", "test/fixtures/funny_jokes.yml", "test/fixtures/interests.yml", "test/fixtures/items.yml", "test/fixtures/jobs.yml", "test/fixtures/legacy_things.yml", "test/fixtures/mateys.yml", "test/fixtures/member_types.yml", "test/fixtures/members.yml", "test/fixtures/memberships.yml", "test/fixtures/men.yml", "test/fixtures/minimalistics.yml", "test/fixtures/mixed_case_monkeys.yml", "test/fixtures/mixins.yml", "test/fixtures/movies.yml", "test/fixtures/naked", "test/fixtures/naked/csv", "test/fixtures/naked/csv/accounts.csv", "test/fixtures/naked/yml", "test/fixtures/naked/yml/accounts.yml", "test/fixtures/naked/yml/companies.yml", "test/fixtures/naked/yml/courses.yml", "test/fixtures/organizations.yml", "test/fixtures/owners.yml", "test/fixtures/parrots.yml", "test/fixtures/parrots_pirates.yml", "test/fixtures/people.yml", "test/fixtures/pets.yml", "test/fixtures/pirates.yml", "test/fixtures/posts.yml", "test/fixtures/price_estimates.yml", "test/fixtures/projects.yml", "test/fixtures/readers.yml", "test/fixtures/references.yml", "test/fixtures/reserved_words", "test/fixtures/reserved_words/distinct.yml", "test/fixtures/reserved_words/distincts_selects.yml", "test/fixtures/reserved_words/group.yml", "test/fixtures/reserved_words/select.yml", "test/fixtures/reserved_words/values.yml", "test/fixtures/ships.yml", "test/fixtures/sponsors.yml", "test/fixtures/subscribers.yml", "test/fixtures/subscriptions.yml", "test/fixtures/taggings.yml", "test/fixtures/tags.yml", "test/fixtures/tasks.yml", "test/fixtures/topics.yml", "test/fixtures/toys.yml", "test/fixtures/treasures.yml", "test/fixtures/vertices.yml", "test/fixtures/warehouse-things.yml", "test/fixtures/zines.yml", "test/migrations", "test/migrations/broken", "test/migrations/broken/100_migration_that_raises_exception.rb", "test/migrations/decimal", "test/migrations/decimal/1_give_me_big_numbers.rb", "test/migrations/duplicate", "test/migrations/duplicate/1_people_have_last_names.rb", "test/migrations/duplicate/2_we_need_reminders.rb", "test/migrations/duplicate/3_foo.rb", "test/migrations/duplicate/3_innocent_jointable.rb", "test/migrations/duplicate_names", "test/migrations/duplicate_names/20080507052938_chunky.rb", "test/migrations/duplicate_names/20080507053028_chunky.rb", "test/migrations/interleaved", "test/migrations/interleaved/pass_1", "test/migrations/interleaved/pass_1/3_innocent_jointable.rb", "test/migrations/interleaved/pass_2", "test/migrations/interleaved/pass_2/1_people_have_last_names.rb", "test/migrations/interleaved/pass_2/3_innocent_jointable.rb", "test/migrations/interleaved/pass_3", "test/migrations/interleaved/pass_3/1_people_have_last_names.rb", "test/migrations/interleaved/pass_3/2_i_raise_on_down.rb", "test/migrations/interleaved/pass_3/3_innocent_jointable.rb", "test/migrations/missing", "test/migrations/missing/1000_people_have_middle_names.rb", "test/migrations/missing/1_people_have_last_names.rb", "test/migrations/missing/3_we_need_reminders.rb", "test/migrations/missing/4_innocent_jointable.rb", "test/migrations/valid", "test/migrations/valid/1_people_have_last_names.rb", "test/migrations/valid/2_we_need_reminders.rb", "test/migrations/valid/3_innocent_jointable.rb", "test/models", "test/models/author.rb", "test/models/auto_id.rb", "test/models/binary.rb", "test/models/bird.rb", "test/models/book.rb", "test/models/categorization.rb", "test/models/category.rb", "test/models/citation.rb", "test/models/club.rb", "test/models/column_name.rb", "test/models/comment.rb", "test/models/company.rb", "test/models/company_in_module.rb", "test/models/computer.rb", "test/models/contact.rb", "test/models/contract.rb", "test/models/course.rb", "test/models/customer.rb", "test/models/default.rb", "test/models/developer.rb", "test/models/edge.rb", "test/models/entrant.rb", "test/models/essay.rb", "test/models/event.rb", "test/models/face.rb", "test/models/guid.rb", "test/models/interest.rb", "test/models/item.rb", "test/models/job.rb", "test/models/joke.rb", "test/models/keyboard.rb", "test/models/legacy_thing.rb", "test/models/man.rb", "test/models/matey.rb", "test/models/member.rb", "test/models/member_detail.rb", "test/models/member_type.rb", "test/models/membership.rb", "test/models/minimalistic.rb", "test/models/mixed_case_monkey.rb", "test/models/movie.rb", "test/models/order.rb", "test/models/organization.rb", "test/models/owner.rb", "test/models/parrot.rb", "test/models/person.rb", "test/models/pet.rb", "test/models/pirate.rb", "test/models/post.rb", "test/models/price_estimate.rb", "test/models/project.rb", "test/models/reader.rb", "test/models/reference.rb", "test/models/reply.rb", "test/models/ship.rb", "test/models/ship_part.rb", "test/models/sponsor.rb", "test/models/subject.rb", "test/models/subscriber.rb", "test/models/subscription.rb", "test/models/tag.rb", "test/models/tagging.rb", "test/models/task.rb", "test/models/topic.rb", "test/models/toy.rb", "test/models/traffic_light.rb", "test/models/treasure.rb", "test/models/vertex.rb", "test/models/warehouse_thing.rb", "test/models/zine.rb", "test/schema", "test/schema/mysql_specific_schema.rb", "test/schema/oracle_specific_schema.rb", "test/schema/postgresql_specific_schema.rb", "test/schema/schema.rb", "test/schema/sqlite_specific_schema.rb", "examples/associations.png", "examples/performance.rb", "examples/simple.rb"] + s.homepage = %q{http://www.rubyonrails.org} + s.rdoc_options = ["--main", "README"] + s.require_paths = ["lib"] + s.rubyforge_project = %q{activerecord} + s.rubygems_version = %q{1.3.5} + s.summary = %q{Implements the ActiveRecord pattern for ORM.} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 3 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q<activesupport>, ["= 3.0.pre"]) + s.add_runtime_dependency(%q<activemodel>, ["= 3.0.pre"]) + else + s.add_dependency(%q<activesupport>, ["= 3.0.pre"]) + s.add_dependency(%q<activemodel>, ["= 3.0.pre"]) + end + else + s.add_dependency(%q<activesupport>, ["= 3.0.pre"]) + s.add_dependency(%q<activemodel>, ["= 3.0.pre"]) + end +end diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index f494e38e2f..266a52d612 100755 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -280,9 +280,10 @@ module ActiveRecord # You can manipulate objects and associations before they are saved to the database, but there is some special behavior you should be # aware of, mostly involving the saving of associated objects. # - # Unless you enable the :autosave option on a <tt>has_one</tt>, <tt>belongs_to</tt>, - # <tt>has_many</tt>, or <tt>has_and_belongs_to_many</tt> association, - # in which case the members are always saved. + # Unless you set the :autosave option on a <tt>has_one</tt>, <tt>belongs_to</tt>, + # <tt>has_many</tt>, or <tt>has_and_belongs_to_many</tt> association. Setting it + # to +true+ will _always_ save the members, whereas setting it to +false+ will + # _never_ save the members. # # === One-to-one associations # @@ -1491,24 +1492,43 @@ module ActiveRecord end before_destroy method_name when :delete_all - module_eval %Q{ - before_destroy do |record| # before_destroy do |record| - delete_all_has_many_dependencies(record, # delete_all_has_many_dependencies(record, - "#{reflection.name}", # "posts", - #{reflection.class_name}, # Post, - %@#{dependent_conditions}@) # %@...@) # this is a string literal like %(...) - end # end - } + # before_destroy do |record| + # self.class.send(:delete_all_has_many_dependencies, + # record, + # "posts", + # Post, + # %@...@) # this is a string literal like %(...) + # end + # end + module_eval <<-CALLBACK + before_destroy do |record| + self.class.send(:delete_all_has_many_dependencies, + record, + "#{reflection.name}", + #{reflection.class_name}, + %@#{dependent_conditions}@) + end + CALLBACK when :nullify - module_eval %Q{ - before_destroy do |record| # before_destroy do |record| - nullify_has_many_dependencies(record, # nullify_has_many_dependencies(record, - "#{reflection.name}", # "posts", - #{reflection.class_name}, # Post, - "#{reflection.primary_key_name}", # "user_id", - %@#{dependent_conditions}@) # %@...@) # this is a string literal like %(...) - end # end - } + # before_destroy do |record| + # self.class.send(:nullify_has_many_dependencies, + # record, + # "posts", + # Post, + # "user_id", + # %@...@) # this is a string literal like %(...) + # end + # end + module_eval <<-CALLBACK + before_destroy do |record| + self.class.send(:nullify_has_many_dependencies, + record, + "#{reflection.name}", + #{reflection.class_name}, + "#{reflection.primary_key_name}", + %@#{dependent_conditions}@) + end + CALLBACK else raise ArgumentError, "The :dependent option expects either :destroy, :delete_all, or :nullify (#{reflection.options[:dependent].inspect})" end @@ -1656,7 +1676,7 @@ module ActiveRecord options[:extend] = create_extension_modules(association_id, extension, options[:extend]) reflection = create_reflection(:has_and_belongs_to_many, association_id, options, self) - + if reflection.association_foreign_key == reflection.primary_key_name raise HasAndBelongsToManyAssociationForeignKeyNeeded.new(reflection) end diff --git a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb index d91c555dad..417e2fdc0f 100644 --- a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb +++ b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb @@ -24,8 +24,8 @@ module ActiveRecord def has_primary_key? return @has_primary_key unless @has_primary_key.nil? - @has_primary_key = (ActiveRecord::Base.connection.supports_primary_key? && - ActiveRecord::Base.connection.primary_key(@reflection.options[:join_table])) + @has_primary_key = (@owner.connection.supports_primary_key? && + @owner.connection.primary_key(@reflection.options[:join_table])) end protected diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index c1bc8423a9..8f37fcd515 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -158,7 +158,7 @@ module ActiveRecord def add_autosave_association_callbacks(reflection) save_method = "autosave_associated_records_for_#{reflection.name}" validation_method = "validate_associated_records_for_#{reflection.name}" - validate validation_method + force_validation = (reflection.options[:validate] == true || reflection.options[:autosave] == true) case reflection.macro when :has_many, :has_and_belongs_to_many @@ -169,7 +169,10 @@ module ActiveRecord after_create save_method after_update save_method - define_method(validation_method) { validate_collection_association(reflection) } + if force_validation || (reflection.macro == :has_many && reflection.options[:validate] != false) + define_method(validation_method) { validate_collection_association(reflection) } + validate validation_method + end else case reflection.macro when :has_one @@ -179,7 +182,11 @@ module ActiveRecord define_method(save_method) { save_belongs_to_association(reflection) } before_save save_method end - define_method(validation_method) { validate_single_association(reflection) } + + if force_validation + define_method(validation_method) { validate_single_association(reflection) } + validate validation_method + end end end end @@ -223,10 +230,8 @@ module ActiveRecord # Validate the association if <tt>:validate</tt> or <tt>:autosave</tt> is # turned on for the association specified by +reflection+. def validate_single_association(reflection) - if reflection.options[:validate] == true || reflection.options[:autosave] == true - if (association = association_instance_get(reflection.name)) && !association.target.nil? - association_valid?(reflection, association) - end + if (association = association_instance_get(reflection.name)) && !association.target.nil? + association_valid?(reflection, association) end end @@ -234,7 +239,7 @@ module ActiveRecord # <tt>:autosave</tt> is turned on for the association specified by # +reflection+. def validate_collection_association(reflection) - if reflection.options[:validate] != false && association = association_instance_get(reflection.name) + if association = association_instance_get(reflection.name) if records = associated_records_to_validate_or_save(association, new_record?, reflection.options[:autosave]) records.each { |record| association_valid?(reflection, record) } end @@ -243,15 +248,15 @@ module ActiveRecord # Returns whether or not the association is valid and applies any errors to # the parent, <tt>self</tt>, if it wasn't. Skips any <tt>:autosave</tt> - # enabled records if they're marked_for_destruction?. + # enabled records if they're marked_for_destruction? or destroyed. def association_valid?(reflection, association) + return true if association.destroyed? || association.marked_for_destruction? + unless valid = association.valid? if reflection.options[:autosave] - unless association.marked_for_destruction? - association.errors.each do |attribute, message| - attribute = "#{reflection.name}_#{attribute}" - errors[attribute] << message if errors[attribute].empty? - end + association.errors.each do |attribute, message| + attribute = "#{reflection.name}_#{attribute}" + errors[attribute] << message if errors[attribute].empty? end else errors.add(reflection.name) @@ -281,9 +286,11 @@ module ActiveRecord if records = associated_records_to_validate_or_save(association, @new_record_before_save, autosave) records.each do |record| + next if record.destroyed? + if autosave && record.marked_for_destruction? association.destroy(record) - elsif @new_record_before_save || record.new_record? + elsif autosave != false && (@new_record_before_save || record.new_record?) if autosave association.send(:insert_record, record, false, false) else @@ -309,14 +316,17 @@ module ActiveRecord # This all happens inside a transaction, _if_ the Transactions module is included into # ActiveRecord::Base after the AutosaveAssociation module, which it does by default. def save_has_one_association(reflection) - if (association = association_instance_get(reflection.name)) && !association.target.nil? + if (association = association_instance_get(reflection.name)) && !association.target.nil? && !association.destroyed? autosave = reflection.options[:autosave] if autosave && association.marked_for_destruction? association.destroy - elsif new_record? || association.new_record? || association[reflection.primary_key_name] != id || autosave - association[reflection.primary_key_name] = id - association.save(!autosave) + else + key = reflection.options[:primary_key] ? send(reflection.options[:primary_key]) : id + if autosave != false && (new_record? || association.new_record? || association[reflection.primary_key_name] != key || autosave) + association[reflection.primary_key_name] = key + association.save(!autosave) + end end end end @@ -330,12 +340,12 @@ module ActiveRecord # This all happens inside a transaction, _if_ the Transactions module is included into # ActiveRecord::Base after the AutosaveAssociation module, which it does by default. def save_belongs_to_association(reflection) - if association = association_instance_get(reflection.name) + if (association = association_instance_get(reflection.name)) && !association.destroyed? autosave = reflection.options[:autosave] if autosave && association.marked_for_destruction? association.destroy - else + elsif autosave != false association.save(!autosave) if association.new_record? || autosave if association.updated? diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index c5be561ea3..502fe0442e 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1648,46 +1648,31 @@ module ActiveRecord #:nodoc: # single-table inheritance model that makes it possible to create # objects of different types from the same table. def instantiate(record) - object = - if subclass_name = record[inheritance_column] - # No type given. - if subclass_name.empty? - allocate + object = find_sti_class(record[inheritance_column]).allocate - else - # Ignore type if no column is present since it was probably - # pulled in from a sloppy join. - unless columns_hash.include?(inheritance_column) - allocate + object.instance_variable_set(:'@attributes', record) + object.instance_variable_set(:'@attributes_cache', {}) - else - begin - compute_type(subclass_name).allocate - rescue NameError - raise SubclassNotFound, - "The single-table inheritance mechanism failed to locate the subclass: '#{record[inheritance_column]}'. " + - "This error is raised because the column '#{inheritance_column}' is reserved for storing the class in case of inheritance. " + - "Please rename this column if you didn't intend it to be used for storing the inheritance class " + - "or overwrite #{self.to_s}.inheritance_column to use another column for that information." - end - end - end - else - allocate - end + object.send(:_run_find_callbacks) + object.send(:_run_initialize_callbacks) - object.instance_variable_set("@attributes", record) - object.instance_variable_set("@attributes_cache", Hash.new) - - if object.respond_to_without_attributes?(:after_find) - object.send(:callback, :after_find) - end + object + end - if object.respond_to_without_attributes?(:after_initialize) - object.send(:callback, :after_initialize) + def find_sti_class(type_name) + if type_name.blank? || !columns_hash.include?(inheritance_column) + self + else + begin + compute_type(type_name) + rescue NameError + raise SubclassNotFound, + "The single-table inheritance mechanism failed to locate the subclass: '#{type_name}'. " + + "This error is raised because the column '#{inheritance_column}' is reserved for storing the class in case of inheritance. " + + "Please rename this column if you didn't intend it to be used for storing the inheritance class " + + "or overwrite #{name}.inheritance_column to use another column for that information." + end end - - object end # Nest the type name in the same module as this class. @@ -2438,7 +2423,7 @@ module ActiveRecord #:nodoc: self.attributes = attributes unless attributes.nil? self.class.send(:scope, :create).each { |att,value| self.send("#{att}=", value) } if self.class.send(:scoped?, :create) result = yield self if block_given? - callback(:after_initialize) if respond_to_without_attributes?(:after_initialize) + _run_initialize_callbacks result end @@ -2943,7 +2928,9 @@ module ActiveRecord #:nodoc: end def log_protected_attribute_removal(*attributes) - logger.debug "WARNING: Can't mass-assign these protected attributes: #{attributes.join(', ')}" + if logger + logger.debug "WARNING: Can't mass-assign these protected attributes: #{attributes.join(', ')}" + end end # The primary key and inheritance column can never be set by mass-assignment for security reasons. diff --git a/activerecord/lib/active_record/callbacks.rb b/activerecord/lib/active_record/callbacks.rb index 4a2ec5bf95..40a25811c4 100644 --- a/activerecord/lib/active_record/callbacks.rb +++ b/activerecord/lib/active_record/callbacks.rb @@ -10,16 +10,14 @@ module ActiveRecord # * (-) <tt>save</tt> # * (-) <tt>valid</tt> # * (1) <tt>before_validation</tt> - # * (2) <tt>before_validation_on_create</tt> # * (-) <tt>validate</tt> # * (-) <tt>validate_on_create</tt> - # * (3) <tt>after_validation</tt> - # * (4) <tt>after_validation_on_create</tt> - # * (5) <tt>before_save</tt> - # * (6) <tt>before_create</tt> + # * (2) <tt>after_validation</tt> + # * (3) <tt>before_save</tt> + # * (4) <tt>before_create</tt> # * (-) <tt>create</tt> - # * (7) <tt>after_create</tt> - # * (8) <tt>after_save</tt> + # * (5) <tt>after_create</tt> + # * (6) <tt>after_save</tt> # # That's a total of eight callbacks, which gives you immense power to react and prepare for each state in the # Active Record lifecycle. The sequence for calling <tt>Base#save</tt> for an existing record is similar, except that each @@ -212,162 +210,122 @@ module ActiveRecord # instead of quietly returning +false+. module Callbacks extend ActiveSupport::Concern + include ActiveSupport::NewCallbacks - CALLBACKS = %w( - after_find after_initialize before_save after_save before_create after_create before_update after_update before_validation - after_validation before_validation_on_create after_validation_on_create before_validation_on_update - after_validation_on_update before_destroy after_destroy - ) + CALLBACKS = [ + :after_initialize, :after_find, :before_validation, :after_validation, + :before_save, :around_save, :after_save, :before_create, :around_create, + :after_create, :before_update, :around_update, :after_update, + :before_destroy, :around_destroy, :after_destroy + ] included do - extend Observable - [:create_or_update, :valid?, :create, :update, :destroy].each do |method| alias_method_chain method, :callbacks end - include ActiveSupport::Callbacks - define_callbacks *CALLBACKS + define_callbacks :initialize, :find, :save, :create, :update, :destroy, + :validation, :terminator => "result == false", :scope => [:kind, :name] end - # Is called when the object was instantiated by one of the finders, like <tt>Base.find</tt>. - #def after_find() end + module ClassMethods + def after_initialize(*args, &block) + options = args.extract_options! + options[:prepend] = true + set_callback(:initialize, :after, *(args << options), &block) + end + + def after_find(*args, &block) + options = args.extract_options! + options[:prepend] = true + set_callback(:find, :after, *(args << options), &block) + end + + [:save, :create, :update, :destroy].each do |callback| + module_eval <<-CALLBACKS, __FILE__, __LINE__ + def before_#{callback}(*args, &block) + set_callback(:#{callback}, :before, *args, &block) + end - # Is called after the object has been instantiated by a call to <tt>Base.new</tt>. - #def after_initialize() end + def around_#{callback}(*args, &block) + set_callback(:#{callback}, :around, *args, &block) + end - # Is called _before_ <tt>Base.save</tt> (regardless of whether it's a +create+ or +update+ save). - def before_save() end + def after_#{callback}(*args, &block) + options = args.extract_options! + options[:prepend] = true + options[:if] = Array(options[:if]) << "!halted && value != false" + set_callback(:#{callback}, :after, *(args << options), &block) + end + CALLBACKS + end + + def before_validation(*args, &block) + options = args.extract_options! + if options[:on] + options[:if] = Array(options[:if]) + options[:if] << "@_on_validate == :#{options[:on]}" + end + set_callback(:validation, :before, *(args << options), &block) + end + + def after_validation(*args, &block) + options = args.extract_options! + options[:if] = Array(options[:if]) + options[:if] << "!halted" + options[:if] << "@_on_validate == :#{options[:on]}" if options[:on] + options[:prepend] = true + set_callback(:validation, :after, *(args << options), &block) + end + + def method_added(meth) + super + if CALLBACKS.include?(meth.to_sym) + ActiveSupport::Deprecation.warn("Base##{meth} has been deprecated, please use Base.#{meth} :method instead", caller[0,1]) + send(meth.to_sym, meth.to_sym) + end + end + end - # Is called _after_ <tt>Base.save</tt> (regardless of whether it's a +create+ or +update+ save). - # Note that this callback is still wrapped in the transaction around +save+. For example, if you - # invoke an external indexer at this point it won't see the changes in the database. - # - # class Contact < ActiveRecord::Base - # after_save { logger.info( 'New contact saved!' ) } - # end - def after_save() end def create_or_update_with_callbacks #:nodoc: - return false if callback(:before_save) == false - if result = create_or_update_without_callbacks - callback(:after_save) + _run_save_callbacks do + create_or_update_without_callbacks end - result end private :create_or_update_with_callbacks - # Is called _before_ <tt>Base.save</tt> on new objects that haven't been saved yet (no record exists). - def before_create() end - - # Is called _after_ <tt>Base.save</tt> on new objects that haven't been saved yet (no record exists). - # Note that this callback is still wrapped in the transaction around +save+. For example, if you - # invoke an external indexer at this point it won't see the changes in the database. - # - # class Contact < ActiveRecord::Base - # after_create { |record| logger.info( "Contact #{record.id} was created." ) } - # end - def after_create() end def create_with_callbacks #:nodoc: - return false if callback(:before_create) == false - result = create_without_callbacks - callback(:after_create) - result + _run_create_callbacks do + create_without_callbacks + end end private :create_with_callbacks - # Is called _before_ <tt>Base.save</tt> on existing objects that have a record. - # - # class Contact < ActiveRecord::Base - # before_update { |record| logger.info( "Contact #{record.id} is about to be updated." ) } - # end - def before_update() end - - # Is called _after_ <tt>Base.save</tt> on existing objects that have a record. - # Note that this callback is still wrapped in the transaction around +save+. For example, if you - # invoke an external indexer at this point it won't see the changes in the database. - # - # class Contact < ActiveRecord::Base - # after_update { |record| logger.info( "Contact #{record.id} was updated." ) } - # end - def after_update() end - def update_with_callbacks(*args) #:nodoc: - return false if callback(:before_update) == false - result = update_without_callbacks(*args) - callback(:after_update) - result + _run_update_callbacks do + update_without_callbacks(*args) + end end private :update_with_callbacks - # Is called _before_ <tt>Validations.validate</tt> (which is part of the <tt>Base.save</tt> call). - def before_validation() end - - # Is called _after_ <tt>Validations.validate</tt> (which is part of the <tt>Base.save</tt> call). - def after_validation() end - - # Is called _before_ <tt>Validations.validate</tt> (which is part of the <tt>Base.save</tt> call) on new objects - # that haven't been saved yet (no record exists). - def before_validation_on_create() end - - # Is called _after_ <tt>Validations.validate</tt> (which is part of the <tt>Base.save</tt> call) on new objects - # that haven't been saved yet (no record exists). - def after_validation_on_create() end - - # Is called _before_ <tt>Validations.validate</tt> (which is part of the <tt>Base.save</tt> call) on - # existing objects that have a record. - def before_validation_on_update() end - - # Is called _after_ <tt>Validations.validate</tt> (which is part of the <tt>Base.save</tt> call) on - # existing objects that have a record. - def after_validation_on_update() end - def valid_with_callbacks? #:nodoc: - return false if callback(:before_validation) == false - if new_record? then result = callback(:before_validation_on_create) else result = callback(:before_validation_on_update) end - return false if false == result - - result = valid_without_callbacks? - - callback(:after_validation) - if new_record? then callback(:after_validation_on_create) else callback(:after_validation_on_update) end - - return result + @_on_validate = new_record? ? :create : :update + _run_validation_callbacks do + valid_without_callbacks? + end end - # Is called _before_ <tt>Base.destroy</tt>. - # - # Note: If you need to _destroy_ or _nullify_ associated records first, - # use the <tt>:dependent</tt> option on your associations. - # - # class Contact < ActiveRecord::Base - # after_destroy { |record| logger.info( "Contact #{record.id} is about to be destroyed." ) } - # end - def before_destroy() end - - # Is called _after_ <tt>Base.destroy</tt> (and all the attributes have been frozen). - # - # class Contact < ActiveRecord::Base - # after_destroy { |record| logger.info( "Contact #{record.id} was destroyed." ) } - # end - def after_destroy() end def destroy_with_callbacks #:nodoc: - return false if callback(:before_destroy) == false - result = destroy_without_callbacks - callback(:after_destroy) - result + _run_destroy_callbacks do + destroy_without_callbacks + end end - private - def callback(method) - result = run_callbacks(method) { |result, object| false == result } - - if result != false && respond_to_without_attributes?(method) - result = send(method) - end - - notify_observers(method) - - return result + def deprecated_callback_method(symbol) #:nodoc: + if respond_to?(symbol) + ActiveSupport::Deprecation.warn("Base##{symbol} has been deprecated, please use Base.#{symbol} :method instead") + send(symbol) end + end end end diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index fab70f34b9..78c7a4b697 100755 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -201,16 +201,12 @@ module ActiveRecord protected def log(sql, name) - if block_given? - result = nil - ms = Benchmark.ms { result = yield } - @runtime += ms - log_info(sql, name, ms) - result - else - log_info(sql, name, 0) - nil + event = ActiveSupport::Orchestra.instrument(:sql, :sql => sql, :name => name) do + yield if block_given? end + @runtime += event.duration + log_info(sql, name, event.duration) + event.result rescue Exception => e # Log message and raise exception. # Set last_verification to 0, so that connection gets verified @@ -221,10 +217,10 @@ module ActiveRecord raise translate_exception(e, message) end - def translate_exception(e, message) - # override in derived class - ActiveRecord::StatementInvalid.new(message) - end + def translate_exception(e, message) + # override in derived class + ActiveRecord::StatementInvalid.new(message) + end def format_log_entry(message, dump = nil) if ActiveRecord::Base.colorize_logging diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb index 4edb64c2c0..1072eb7ac1 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb @@ -8,7 +8,8 @@ module MysqlCompat #:nodoc: raise 'Mysql not loaded' unless defined?(::Mysql) target = defined?(Mysql::Result) ? Mysql::Result : MysqlRes - return if target.instance_methods.include?('all_hashes') + return if target.instance_methods.include?('all_hashes') || + target.instance_methods.include?(:all_hashes) # Ruby driver has a version string and returns null values in each_hash # C driver >= 2.7 returns null values in each_hash @@ -64,12 +65,15 @@ module ActiveRecord raise end end + MysqlCompat.define_all_hashes_method! mysql = Mysql.init mysql.ssl_set(config[:sslkey], config[:sslcert], config[:sslca], config[:sslcapath], config[:sslcipher]) if config[:sslca] || config[:sslkey] - ConnectionAdapters::MysqlAdapter.new(mysql, logger, [host, username, password, database, port, socket], config) + default_flags = Mysql.const_defined?(:CLIENT_MULTI_RESULTS) ? Mysql::CLIENT_MULTI_RESULTS : 0 + options = [host, username, password, database, port, socket, default_flags] + ConnectionAdapters::MysqlAdapter.new(mysql, logger, options, config) end end diff --git a/activerecord/lib/active_record/locking/pessimistic.rb b/activerecord/lib/active_record/locking/pessimistic.rb index 320659596f..fcc9ebb4af 100644 --- a/activerecord/lib/active_record/locking/pessimistic.rb +++ b/activerecord/lib/active_record/locking/pessimistic.rb @@ -1,25 +1,3 @@ -# Copyright (c) 2006 Shugo Maeda <shugo@ruby-lang.org> -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject -# to the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF -# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - module ActiveRecord module Locking # Locking::Pessimistic provides support for row-level locking using diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index de48b10c1c..cd3b182b09 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -66,10 +66,10 @@ module ActiveRecord # accepts_nested_attributes_for :avatar, :allow_destroy => true # end # - # Now, when you add the <tt>_delete</tt> key to the attributes hash, with a + # Now, when you add the <tt>_destroy</tt> key to the attributes hash, with a # value that evaluates to +true+, you will destroy the associated model: # - # member.avatar_attributes = { :id => '2', :_delete => '1' } + # member.avatar_attributes = { :id => '2', :_destroy => '1' } # member.avatar.marked_for_destruction? # => true # member.save # member.reload.avatar #=> nil @@ -89,14 +89,14 @@ module ActiveRecord # the attribute hash. # # For each hash that does _not_ have an <tt>id</tt> key a new record will - # be instantiated, unless the hash also contains a <tt>_delete</tt> key + # be instantiated, unless the hash also contains a <tt>_destroy</tt> key # that evaluates to +true+. # # params = { :member => { # :name => 'joe', :posts_attributes => [ # { :title => 'Kari, the awesome Ruby documentation browser!' }, # { :title => 'The egalitarian assumption of the modern citizen' }, - # { :title => '', :_delete => '1' } # this will be ignored + # { :title => '', :_destroy => '1' } # this will be ignored # ] # }} # @@ -144,7 +144,7 @@ module ActiveRecord # By default the associated records are protected from being destroyed. If # you want to destroy any of the associated records through the attributes # hash, you have to enable it first using the <tt>:allow_destroy</tt> - # option. This will allow you to also use the <tt>_delete</tt> key to + # option. This will allow you to also use the <tt>_destroy</tt> key to # destroy existing records: # # class Member < ActiveRecord::Base @@ -153,7 +153,7 @@ module ActiveRecord # end # # params = { :member => { - # :posts_attributes => [{ :id => '2', :_delete => '1' }] + # :posts_attributes => [{ :id => '2', :_destroy => '1' }] # }} # # member.attributes = params['member'] @@ -176,14 +176,14 @@ module ActiveRecord # Supported options: # [:allow_destroy] # If true, destroys any members from the attributes hash with a - # <tt>_delete</tt> key and a value that evaluates to +true+ + # <tt>_destroy</tt> key and a value that evaluates to +true+ # (eg. 1, '1', true, or 'true'). This option is off by default. # [:reject_if] # Allows you to specify a Proc that checks whether a record should be # built for a certain attribute hash. The hash is passed to the Proc # and the Proc should return either +true+ or +false+. When no Proc # is specified a record will be built for all attribute hashes that - # do not have a <tt>_delete</tt> that evaluates to true. + # do not have a <tt>_destroy</tt> value that evaluates to true. # Passing <tt>:all_blank</tt> instead of a Proc will create a proc # that will reject a record where all the attributes are blank. # @@ -236,15 +236,25 @@ module ActiveRecord # destruction of this association. # # See ActionView::Helpers::FormHelper::fields_for for more info. - def _delete + def _destroy marked_for_destruction? end + # Deal with deprecated _delete. + # + def _delete #:nodoc: + ActiveSupport::Deprecation.warn "_delete is deprecated in nested attributes. Use _destroy instead." + _destroy + end + private # Attribute hash keys that should not be assigned as normal attributes. # These hash keys are nested attributes implementation details. - UNASSIGNABLE_KEYS = %w{ id _delete } + # + # TODO Remove _delete from UNASSIGNABLE_KEYS when deprecation warning are + # removed. + UNASSIGNABLE_KEYS = %w( id _destroy _delete ) # Assigns the given attributes to the association. # @@ -253,14 +263,19 @@ module ActiveRecord # record will be built. # # If the given attributes include a matching <tt>:id</tt> attribute _and_ a - # <tt>:_delete</tt> key set to a truthy value, then the existing record + # <tt>:_destroy</tt> key set to a truthy value, then the existing record # will be marked for destruction. def assign_nested_attributes_for_one_to_one_association(association_name, attributes, allow_destroy) attributes = attributes.stringify_keys if attributes['id'].blank? unless reject_new_record?(association_name, attributes) - send("build_#{association_name}", attributes.except(*UNASSIGNABLE_KEYS)) + method = "build_#{association_name}" + if respond_to?(method) + send(method, attributes.except(*UNASSIGNABLE_KEYS)) + else + raise ArgumentError, "Cannot build association #{association_name}. Are you trying to build a polymorphic one-to-one association?" + end end elsif (existing_record = send(association_name)) && existing_record.id.to_s == attributes['id'].to_s assign_to_or_mark_for_destruction(existing_record, attributes, allow_destroy) @@ -272,7 +287,7 @@ module ActiveRecord # Hashes with an <tt>:id</tt> value matching an existing associated record # will update that record. Hashes without an <tt>:id</tt> value will build # a new record for the association. Hashes with a matching <tt>:id</tt> - # value and a <tt>:_delete</tt> key set to a truthy value will mark the + # value and a <tt>:_destroy</tt> key set to a truthy value will mark the # matched record for destruction. # # For example: @@ -280,7 +295,7 @@ module ActiveRecord # assign_nested_attributes_for_collection_association(:people, { # '1' => { :id => '1', :name => 'Peter' }, # '2' => { :name => 'John' }, - # '3' => { :id => '2', :_delete => true } + # '3' => { :id => '2', :_destroy => true } # }) # # Will update the name of the Person with ID 1, build a new associated @@ -292,7 +307,7 @@ module ActiveRecord # assign_nested_attributes_for_collection_association(:people, [ # { :id => '1', :name => 'Peter' }, # { :name => 'John' }, - # { :id => '2', :_delete => true } + # { :id => '2', :_destroy => true } # ]) def assign_nested_attributes_for_collection_association(association_name, attributes_collection, allow_destroy) unless attributes_collection.is_a?(Hash) || attributes_collection.is_a?(Array) @@ -317,25 +332,26 @@ module ActiveRecord end # Updates a record with the +attributes+ or marks it for destruction if - # +allow_destroy+ is +true+ and has_delete_flag? returns +true+. + # +allow_destroy+ is +true+ and has_destroy_flag? returns +true+. def assign_to_or_mark_for_destruction(record, attributes, allow_destroy) - if has_delete_flag?(attributes) && allow_destroy + if has_destroy_flag?(attributes) && allow_destroy record.mark_for_destruction else record.attributes = attributes.except(*UNASSIGNABLE_KEYS) end end - # Determines if a hash contains a truthy _delete key. - def has_delete_flag?(hash) - ConnectionAdapters::Column.value_to_boolean hash['_delete'] + # Determines if a hash contains a truthy _destroy key. + def has_destroy_flag?(hash) + ConnectionAdapters::Column.value_to_boolean(hash['_destroy']) || + ConnectionAdapters::Column.value_to_boolean(hash['_delete']) # TODO Remove after deprecation. end # Determines if a new record should be build by checking for - # has_delete_flag? or if a <tt>:reject_if</tt> proc exists for this + # has_destroy_flag? or if a <tt>:reject_if</tt> proc exists for this # association and evaluates to +true+. def reject_new_record?(association_name, attributes) - has_delete_flag?(attributes) || + has_destroy_flag?(attributes) || self.class.reject_new_nested_attributes_procs[association_name].try(:call, attributes) end end diff --git a/activerecord/lib/active_record/observer.rb b/activerecord/lib/active_record/observer.rb index a34ff4a47a..4e05b819b5 100644 --- a/activerecord/lib/active_record/observer.rb +++ b/activerecord/lib/active_record/observer.rb @@ -1,6 +1,3 @@ -require 'singleton' -require 'set' - module ActiveRecord # Observer classes respond to lifecycle callbacks to implement trigger-like # behavior outside the original class. This is a great way to reduce the @@ -88,11 +85,17 @@ module ActiveRecord # singletons and that call instantiates and registers them. # class Observer < ActiveModel::Observer + extlib_inheritable_accessor(:observed_methods){ [] } + def initialize super observed_subclasses.each { |klass| add_observer!(klass) } end + def self.method_added(method) + observed_methods << method if ActiveRecord::Callbacks::CALLBACKS.include?(method.to_sym) + end + protected def observed_subclasses observed_classes.sum([]) { |klass| klass.send(:subclasses) } @@ -100,8 +103,15 @@ module ActiveRecord def add_observer!(klass) super - if respond_to?(:after_find) && !klass.method_defined?(:after_find) - klass.class_eval 'def after_find() end' + + # Check if a notifier callback was already added to the given class. If + # it was not, add it. + self.observed_methods.each do |method| + callback = :"_notify_observers_for_#{method}" + if (klass.instance_methods & [callback, callback.to_s]).empty? + klass.class_eval "def #{callback}; notify_observers(:#{method}); end" + klass.send(method, callback) + end end end end diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb index 5fc41cf054..ab79b520a2 100644 --- a/activerecord/lib/active_record/validations.rb +++ b/activerecord/lib/active_record/validations.rb @@ -110,8 +110,6 @@ module ActiveRecord included do alias_method_chain :save, :validation alias_method_chain :save!, :validation - - define_callbacks :validate_on_create, :validate_on_update end module ClassMethods @@ -127,17 +125,6 @@ module ActiveRecord object end end - - def validation_method(on) - case on - when :create - :validate_on_create - when :update - :validate_on_update - else - :validate - end - end end module InstanceMethods @@ -165,27 +152,15 @@ module ActiveRecord def valid? errors.clear - run_callbacks(:validate) + @_on_validate = new_record? ? :create : :update + _run_validate_callbacks - if respond_to?(:validate) - ActiveSupport::Deprecation.warn("Base#validate has been deprecated, please use Base.validate :method instead") - validate - end + deprecated_callback_method(:validate) if new_record? - run_callbacks(:validate_on_create) - - if respond_to?(:validate_on_create) - ActiveSupport::Deprecation.warn("Base#validate_on_create has been deprecated, please use Base.validate_on_create :method instead") - validate_on_create - end + deprecated_callback_method(:validate_on_create) else - run_callbacks(:validate_on_update) - - if respond_to?(:validate_on_update) - ActiveSupport::Deprecation.warn("Base#validate_on_update has been deprecated, please use Base.validate_on_update :method instead") - validate_on_update - end + deprecated_callback_method(:validate_on_update) end errors.empty? diff --git a/activerecord/lib/activerecord.rb b/activerecord/lib/activerecord.rb deleted file mode 100644 index cd62b2afdc..0000000000 --- a/activerecord/lib/activerecord.rb +++ /dev/null @@ -1 +0,0 @@ -require 'active_record' diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index f7178f2c5e..b193f8d8ba 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -813,7 +813,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase firm = companies(:first_firm) clients = firm.clients assert_equal 2, clients.length - clients.last.instance_eval { def before_destroy() raise "Trigger rollback" end } + clients.last.instance_eval { def overwrite_to_raise() raise "Trigger rollback" end } firm.destroy rescue "do nothing" diff --git a/activerecord/test/cases/associations/has_one_associations_test.rb b/activerecord/test/cases/associations/has_one_associations_test.rb index 7140de77ea..cdac86a3b9 100644 --- a/activerecord/test/cases/associations/has_one_associations_test.rb +++ b/activerecord/test/cases/associations/has_one_associations_test.rb @@ -36,6 +36,15 @@ class HasOneAssociationsTest < ActiveRecord::TestCase assert_equal accounts(:rails_core_account), firm.account_using_primary_key end + def test_update_with_foreign_and_primary_keys + firm = companies(:first_firm) + account = firm.account_using_foreign_and_primary_keys + assert_equal Account.find_by_firm_name(firm.name), account + firm.save + firm.reload + assert_equal account, firm.account_using_foreign_and_primary_keys + end + def test_can_marshal_has_one_association_with_nil_target firm = Firm.new assert_nothing_raised do diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb index 271086af8e..9164701601 100644 --- a/activerecord/test/cases/autosave_association_test.rb +++ b/activerecord/test/cases/autosave_association_test.rb @@ -443,6 +443,70 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCa end end +class TestDefaultAutosaveAssociationOnNewRecord < ActiveRecord::TestCase + def test_autosave_new_record_on_belongs_to_can_be_disabled_per_relationship + new_account = Account.new("credit_limit" => 1000) + new_firm = Firm.new("name" => "some firm") + + assert new_firm.new_record? + new_account.firm = new_firm + new_account.save! + + assert !new_firm.new_record? + + new_account = Account.new("credit_limit" => 1000) + new_autosaved_firm = Firm.new("name" => "some firm") + + assert new_autosaved_firm.new_record? + new_account.unautosaved_firm = new_autosaved_firm + new_account.save! + + assert new_autosaved_firm.new_record? + end + + def test_autosave_new_record_on_has_one_can_be_disabled_per_relationship + firm = Firm.new("name" => "some firm") + account = Account.new("credit_limit" => 1000) + + assert account.new_record? + firm.account = account + firm.save! + + assert !account.new_record? + + firm = Firm.new("name" => "some firm") + account = Account.new("credit_limit" => 1000) + + firm.unautosaved_account = account + + assert account.new_record? + firm.unautosaved_account = account + firm.save! + + assert account.new_record? + end + + def test_autosave_new_record_on_has_many_can_be_disabled_per_relationship + firm = Firm.new("name" => "some firm") + account = Account.new("credit_limit" => 1000) + + assert account.new_record? + firm.accounts << account + + firm.save! + assert !account.new_record? + + firm = Firm.new("name" => "some firm") + account = Account.new("credit_limit" => 1000) + + assert account.new_record? + firm.unautosaved_accounts << account + + firm.save! + assert account.new_record? + end +end + class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase self.use_transactional_fixtures = false @@ -480,9 +544,17 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase assert !@pirate.valid? @pirate.ship.mark_for_destruction + @pirate.ship.expects(:valid?).never assert_difference('Ship.count', -1) { @pirate.save! } end + def test_a_child_marked_for_destruction_should_not_be_destroyed_twice + @pirate.ship.mark_for_destruction + assert @pirate.save + @pirate.ship.expects(:destroy).never + assert @pirate.save + end + def test_should_rollback_destructions_if_an_exception_occurred_while_saving_a_child # Stub the save method of the @pirate.ship instance to destroy and then raise an exception class << @pirate.ship @@ -517,9 +589,17 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase assert !@ship.valid? @ship.pirate.mark_for_destruction + @ship.pirate.expects(:valid?).never assert_difference('Pirate.count', -1) { @ship.save! } end + def test_a_parent_marked_for_destruction_should_not_be_destroyed_twice + @ship.pirate.mark_for_destruction + assert @ship.save + @ship.pirate.expects(:destroy).never + assert @ship.save + end + def test_should_rollback_destructions_if_an_exception_occurred_while_saving_a_parent # Stub the save method of the @ship.pirate instance to destroy and then raise an exception class << @ship.pirate @@ -560,9 +640,33 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase children.each { |child| child.name = '' } assert !@pirate.valid? - children.each { |child| child.mark_for_destruction } + children.each do |child| + child.mark_for_destruction + child.expects(:valid?).never + end assert_difference("#{association_name.classify}.count", -2) { @pirate.save! } end + + define_method("test_should_skip_validation_on_the_#{association_name}_association_if_destroyed") do + @pirate.send(association_name).create!(:name => "#{association_name}_1") + children = @pirate.send(association_name) + + children.each { |child| child.name = '' } + assert !@pirate.valid? + + children.each { |child| child.destroy } + assert @pirate.valid? + end + + define_method("test_a_child_marked_for_destruction_should_not_be_destroyed_twice_while_saving_#{association_name}") do + @pirate.send(association_name).create!(:name => "#{association_name}_1") + children = @pirate.send(association_name) + + children.each { |child| child.mark_for_destruction } + assert @pirate.save + children.each { |child| child.expects(:destroy).never } + assert @pirate.save + end define_method("test_should_rollback_destructions_if_an_exception_occurred_while_saving_#{association_name}") do 2.times { |i| @pirate.send(association_name).create!(:name => "#{association_name}_#{i}") } @@ -952,3 +1056,118 @@ class TestAutosaveAssociationOnAHasAndBelongsToManyAssociation < ActiveRecord::T include AutosaveAssociationOnACollectionAssociationTests end + +class TestAutosaveAssociationValidationsOnAHasManyAssocication < ActiveRecord::TestCase + self.use_transactional_fixtures = false + + def setup + @pirate = Pirate.create(:catchphrase => "Don' botharrr talkin' like one, savvy?") + @pirate.birds.create(:name => 'cookoo') + end + + test "should automatically validate associations" do + assert @pirate.valid? + @pirate.birds.each { |bird| bird.name = '' } + + assert !@pirate.valid? + end +end + +class TestAutosaveAssociationValidationsOnAHasOneAssocication < ActiveRecord::TestCase + self.use_transactional_fixtures = false + + def setup + @pirate = Pirate.create(:catchphrase => "Don' botharrr talkin' like one, savvy?") + @pirate.create_ship(:name => 'titanic') + end + + test "should automatically validate associations with :validate => true" do + assert @pirate.valid? + @pirate.ship.name = '' + assert !@pirate.valid? + end + + test "should not automatically validate associations without :validate => true" do + assert @pirate.valid? + @pirate.non_validated_ship.name = '' + assert @pirate.valid? + end +end + +class TestAutosaveAssociationValidationsOnABelongsToAssocication < ActiveRecord::TestCase + self.use_transactional_fixtures = false + + def setup + @pirate = Pirate.create(:catchphrase => "Don' botharrr talkin' like one, savvy?") + end + + test "should automatically validate associations with :validate => true" do + assert @pirate.valid? + @pirate.parrot = Parrot.new(:name => '') + assert !@pirate.valid? + end + + test "should not automatically validate associations without :validate => true" do + assert @pirate.valid? + @pirate.non_validated_parrot = Parrot.new(:name => '') + assert @pirate.valid? + end +end + +class TestAutosaveAssociationValidationsOnAHABTMAssocication < ActiveRecord::TestCase + self.use_transactional_fixtures = false + + def setup + @pirate = Pirate.create(:catchphrase => "Don' botharrr talkin' like one, savvy?") + end + + test "should automatically validate associations with :validate => true" do + assert @pirate.valid? + @pirate.parrots = [ Parrot.new(:name => 'popuga') ] + @pirate.parrots.each { |parrot| parrot.name = '' } + assert !@pirate.valid? + end + + test "should not automatically validate associations without :validate => true" do + assert @pirate.valid? + @pirate.non_validated_parrots = [ Parrot.new(:name => 'popuga') ] + @pirate.non_validated_parrots.each { |parrot| parrot.name = '' } + assert @pirate.valid? + end +end + +class TestAutosaveAssociationValidationMethodsGeneration < ActiveRecord::TestCase + self.use_transactional_fixtures = false + + def setup + @pirate = Pirate.new + end + + test "should generate validation methods for has_many associations" do + assert @pirate.respond_to?(:validate_associated_records_for_birds) + end + + test "should generate validation methods for has_one associations with :validate => true" do + assert @pirate.respond_to?(:validate_associated_records_for_ship) + end + + test "should not generate validation methods for has_one associations without :validate => true" do + assert !@pirate.respond_to?(:validate_associated_records_for_non_validated_ship) + end + + test "should generate validation methods for belongs_to associations with :validate => true" do + assert @pirate.respond_to?(:validate_associated_records_for_parrot) + end + + test "should not generate validation methods for belongs_to associations without :validate => true" do + assert !@pirate.respond_to?(:validate_associated_records_for_non_validated_parrot) + end + + test "should generate validation methods for HABTM associations with :validate => true" do + assert @pirate.respond_to?(:validate_associated_records_for_parrots) + end + + test "should not generate validation methods for HABTM associations without :validate => true" do + assert !@pirate.respond_to?(:validate_associated_records_for_non_validated_parrots) + end +end diff --git a/activerecord/test/cases/callbacks_observers_test.rb b/activerecord/test/cases/callbacks_observers_test.rb index 87de524923..52ce384844 100644 --- a/activerecord/test/cases/callbacks_observers_test.rb +++ b/activerecord/test/cases/callbacks_observers_test.rb @@ -5,7 +5,7 @@ class Comment < ActiveRecord::Base before_validation :record_callers - def after_validation + after_validation do record_callers end @@ -32,7 +32,6 @@ class CallbacksObserversTest < ActiveRecord::TestCase CommentObserver.instance.callers = callers comment.valid? - assert_equal [Comment, Comment, CommentObserver], callers, "model callbacks did not fire before observers were notified" end end diff --git a/activerecord/test/cases/callbacks_test.rb b/activerecord/test/cases/callbacks_test.rb index 95fddaeef6..5a084a611e 100644 --- a/activerecord/test/cases/callbacks_test.rb +++ b/activerecord/test/cases/callbacks_test.rb @@ -13,8 +13,8 @@ class CallbackDeveloper < ActiveRecord::Base end def define_callback_method(callback_method) - define_method("#{callback_method}_method") do |model| - model.history << [callback_method, :method] + define_method(callback_method) do + self.history << [callback_method, :method] end end @@ -27,26 +27,20 @@ class CallbackDeveloper < ActiveRecord::Base end end - ActiveRecord::Callbacks::CALLBACKS.each do |callback_method| - callback_method_sym = callback_method.to_sym - define_callback_method(callback_method_sym) - send(callback_method, callback_method_sym) - send(callback_method, callback_string(callback_method_sym)) - send(callback_method, callback_proc(callback_method_sym)) - send(callback_method, callback_object(callback_method_sym)) - send(callback_method) { |model| model.history << [callback_method_sym, :block] } + ActiveSupport::Deprecation.silence do + ActiveRecord::Callbacks::CALLBACKS.each do |callback_method| + next if callback_method.to_s =~ /^around_/ + define_callback_method(callback_method) + send(callback_method, callback_string(callback_method)) + send(callback_method, callback_proc(callback_method)) + send(callback_method, callback_object(callback_method)) + send(callback_method) { |model| model.history << [callback_method, :block] } + end end def history @history ||= [] end - - # after_initialize and after_find are invoked only if instance methods have been defined. - def after_initialize - end - - def after_find - end end class ParentDeveloper < ActiveRecord::Base @@ -108,12 +102,12 @@ class ImmutableMethodDeveloper < ActiveRecord::Base @cancelled == true end - def before_save + before_save do @cancelled = true false end - def before_destroy + before_destroy do @cancelled = true false end @@ -125,15 +119,15 @@ class CallbackCancellationDeveloper < ActiveRecord::Base attr_reader :after_save_called, :after_create_called, :after_update_called, :after_destroy_called attr_accessor :cancel_before_save, :cancel_before_create, :cancel_before_update, :cancel_before_destroy - def before_save; !@cancel_before_save; end - def before_create; !@cancel_before_create; end - def before_update; !@cancel_before_update; end - def before_destroy; !@cancel_before_destroy; end + before_save { !@cancel_before_save } + before_create { !@cancel_before_create } + before_update { !@cancel_before_update } + before_destroy { !@cancel_before_destroy } - def after_save; @after_save_called = true; end - def after_update; @after_update_called = true; end - def after_create; @after_create_called = true; end - def after_destroy; @after_destroy_called = true; end + after_save { @after_save_called = true } + after_update { @after_update_called = true } + after_create { @after_create_called = true } + after_destroy { @after_destroy_called = true } end class CallbacksTest < ActiveRecord::TestCase @@ -142,6 +136,7 @@ class CallbacksTest < ActiveRecord::TestCase def test_initialize david = CallbackDeveloper.new assert_equal [ + [ :after_initialize, :method ], [ :after_initialize, :string ], [ :after_initialize, :proc ], [ :after_initialize, :object ], @@ -152,10 +147,12 @@ class CallbacksTest < ActiveRecord::TestCase def test_find david = CallbackDeveloper.find(1) assert_equal [ + [ :after_find, :method ], [ :after_find, :string ], [ :after_find, :proc ], [ :after_find, :object ], [ :after_find, :block ], + [ :after_initialize, :method ], [ :after_initialize, :string ], [ :after_initialize, :proc ], [ :after_initialize, :object ], @@ -167,26 +164,21 @@ class CallbacksTest < ActiveRecord::TestCase david = CallbackDeveloper.new david.valid? assert_equal [ + [ :after_initialize, :method ], [ :after_initialize, :string ], [ :after_initialize, :proc ], [ :after_initialize, :object ], [ :after_initialize, :block ], + [ :before_validation, :method ], [ :before_validation, :string ], [ :before_validation, :proc ], [ :before_validation, :object ], [ :before_validation, :block ], - [ :before_validation_on_create, :string ], - [ :before_validation_on_create, :proc ], - [ :before_validation_on_create, :object ], - [ :before_validation_on_create, :block ], + [ :after_validation, :method ], [ :after_validation, :string ], [ :after_validation, :proc ], [ :after_validation, :object ], [ :after_validation, :block ], - [ :after_validation_on_create, :string ], - [ :after_validation_on_create, :proc ], - [ :after_validation_on_create, :object ], - [ :after_validation_on_create, :block ] ], david.history end @@ -194,68 +186,63 @@ class CallbacksTest < ActiveRecord::TestCase david = CallbackDeveloper.find(1) david.valid? assert_equal [ + [ :after_find, :method ], [ :after_find, :string ], [ :after_find, :proc ], [ :after_find, :object ], [ :after_find, :block ], + [ :after_initialize, :method ], [ :after_initialize, :string ], [ :after_initialize, :proc ], [ :after_initialize, :object ], [ :after_initialize, :block ], + [ :before_validation, :method ], [ :before_validation, :string ], [ :before_validation, :proc ], [ :before_validation, :object ], [ :before_validation, :block ], - [ :before_validation_on_update, :string ], - [ :before_validation_on_update, :proc ], - [ :before_validation_on_update, :object ], - [ :before_validation_on_update, :block ], + [ :after_validation, :method ], [ :after_validation, :string ], [ :after_validation, :proc ], [ :after_validation, :object ], [ :after_validation, :block ], - [ :after_validation_on_update, :string ], - [ :after_validation_on_update, :proc ], - [ :after_validation_on_update, :object ], - [ :after_validation_on_update, :block ] ], david.history end def test_create david = CallbackDeveloper.create('name' => 'David', 'salary' => 1000000) assert_equal [ + [ :after_initialize, :method ], [ :after_initialize, :string ], [ :after_initialize, :proc ], [ :after_initialize, :object ], [ :after_initialize, :block ], + [ :before_validation, :method ], [ :before_validation, :string ], [ :before_validation, :proc ], [ :before_validation, :object ], [ :before_validation, :block ], - [ :before_validation_on_create, :string ], - [ :before_validation_on_create, :proc ], - [ :before_validation_on_create, :object ], - [ :before_validation_on_create, :block ], + [ :after_validation, :method ], [ :after_validation, :string ], [ :after_validation, :proc ], [ :after_validation, :object ], [ :after_validation, :block ], - [ :after_validation_on_create, :string ], - [ :after_validation_on_create, :proc ], - [ :after_validation_on_create, :object ], - [ :after_validation_on_create, :block ], + [ :before_save, :method ], [ :before_save, :string ], [ :before_save, :proc ], [ :before_save, :object ], [ :before_save, :block ], + [ :before_create, :method ], [ :before_create, :string ], [ :before_create, :proc ], [ :before_create, :object ], [ :before_create, :block ], + [ :after_create, :method ], [ :after_create, :string ], [ :after_create, :proc ], [ :after_create, :object ], [ :after_create, :block ], + [ :after_save, :method ], [ :after_save, :string ], [ :after_save, :proc ], [ :after_save, :object ], @@ -267,42 +254,42 @@ class CallbacksTest < ActiveRecord::TestCase david = CallbackDeveloper.find(1) david.save assert_equal [ + [ :after_find, :method ], [ :after_find, :string ], [ :after_find, :proc ], [ :after_find, :object ], [ :after_find, :block ], + [ :after_initialize, :method ], [ :after_initialize, :string ], [ :after_initialize, :proc ], [ :after_initialize, :object ], [ :after_initialize, :block ], + [ :before_validation, :method ], [ :before_validation, :string ], [ :before_validation, :proc ], [ :before_validation, :object ], [ :before_validation, :block ], - [ :before_validation_on_update, :string ], - [ :before_validation_on_update, :proc ], - [ :before_validation_on_update, :object ], - [ :before_validation_on_update, :block ], + [ :after_validation, :method ], [ :after_validation, :string ], [ :after_validation, :proc ], [ :after_validation, :object ], [ :after_validation, :block ], - [ :after_validation_on_update, :string ], - [ :after_validation_on_update, :proc ], - [ :after_validation_on_update, :object ], - [ :after_validation_on_update, :block ], + [ :before_save, :method ], [ :before_save, :string ], [ :before_save, :proc ], [ :before_save, :object ], [ :before_save, :block ], + [ :before_update, :method ], [ :before_update, :string ], [ :before_update, :proc ], [ :before_update, :object ], [ :before_update, :block ], + [ :after_update, :method ], [ :after_update, :string ], [ :after_update, :proc ], [ :after_update, :object ], [ :after_update, :block ], + [ :after_save, :method ], [ :after_save, :string ], [ :after_save, :proc ], [ :after_save, :object ], @@ -314,18 +301,22 @@ class CallbacksTest < ActiveRecord::TestCase david = CallbackDeveloper.find(1) david.destroy assert_equal [ + [ :after_find, :method ], [ :after_find, :string ], [ :after_find, :proc ], [ :after_find, :object ], [ :after_find, :block ], + [ :after_initialize, :method ], [ :after_initialize, :string ], [ :after_initialize, :proc ], [ :after_initialize, :object ], [ :after_initialize, :block ], + [ :before_destroy, :method ], [ :before_destroy, :string ], [ :before_destroy, :proc ], [ :before_destroy, :object ], [ :before_destroy, :block ], + [ :after_destroy, :method ], [ :after_destroy, :string ], [ :after_destroy, :proc ], [ :after_destroy, :object ], @@ -337,10 +328,12 @@ class CallbacksTest < ActiveRecord::TestCase david = CallbackDeveloper.find(1) CallbackDeveloper.delete(david.id) assert_equal [ + [ :after_find, :method ], [ :after_find, :string ], [ :after_find, :proc ], [ :after_find, :object ], [ :after_find, :block ], + [ :after_initialize, :method ], [ :after_initialize, :string ], [ :after_initialize, :proc ], [ :after_initialize, :object ], @@ -407,14 +400,17 @@ class CallbacksTest < ActiveRecord::TestCase CallbackDeveloper.before_validation proc { |model| model.history << [:before_validation, :should_never_get_here] } david.save assert_equal [ + [ :after_find, :method ], [ :after_find, :string ], [ :after_find, :proc ], [ :after_find, :object ], [ :after_find, :block ], + [ :after_initialize, :method ], [ :after_initialize, :string ], [ :after_initialize, :proc ], [ :after_initialize, :object ], [ :after_initialize, :block ], + [ :before_validation, :method ], [ :before_validation, :string ], [ :before_validation, :proc ], [ :before_validation, :object ], diff --git a/activerecord/test/cases/class_inheritable_attributes_test.rb b/activerecord/test/cases/class_inheritable_attributes_test.rb deleted file mode 100644 index abeb63c591..0000000000 --- a/activerecord/test/cases/class_inheritable_attributes_test.rb +++ /dev/null @@ -1,32 +0,0 @@ -require 'test/unit' -require "cases/helper" -require 'active_support/core_ext/class/inheritable_attributes' - -class A - include ClassInheritableAttributes -end - -class B < A - write_inheritable_array "first", [ :one, :two ] -end - -class C < A - write_inheritable_array "first", [ :three ] -end - -class D < B - write_inheritable_array "first", [ :four ] -end - - -class ClassInheritableAttributesTest < ActiveRecord::TestCase - def test_first_level - assert_equal [ :one, :two ], B.read_inheritable_attribute("first") - assert_equal [ :three ], C.read_inheritable_attribute("first") - end - - def test_second_level - assert_equal [ :one, :two, :four ], D.read_inheritable_attribute("first") - assert_equal [ :one, :two ], B.read_inheritable_attribute("first") - end -end diff --git a/activerecord/test/cases/connection_test_mysql.rb b/activerecord/test/cases/connection_test_mysql.rb index f79ee2f1f7..8e4842a1b6 100644 --- a/activerecord/test/cases/connection_test_mysql.rb +++ b/activerecord/test/cases/connection_test_mysql.rb @@ -41,6 +41,14 @@ class MysqlConnectionTest < ActiveRecord::TestCase sleep 2 @connection.verify! assert @connection.active? + end + + # Test that MySQL allows multiple results for stored procedures + if Mysql.const_defined?(:CLIENT_MULTI_RESULTS) + def test_multi_results + rows = ActiveRecord::Base.connection.select_rows('CALL ten();') + assert_equal 10, rows[0][0].to_i, "ten() did not return 10 as expected: #{rows.inspect}" + end end private diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb index d1e7caed89..aa09c7061f 100644 --- a/activerecord/test/cases/helper.rb +++ b/activerecord/test/cases/helper.rb @@ -12,8 +12,6 @@ require 'active_record/test_case' require 'active_record/fixtures' require 'connection' -require 'cases/repair_helper' - begin require 'ruby-debug' rescue LoadError diff --git a/activerecord/test/cases/lifecycle_test.rb b/activerecord/test/cases/lifecycle_test.rb index 54fb3d8c39..aa7ce2ecb6 100644 --- a/activerecord/test/cases/lifecycle_test.rb +++ b/activerecord/test/cases/lifecycle_test.rb @@ -1,11 +1,9 @@ -require "cases/helper" +require 'cases/helper' require 'models/topic' require 'models/developer' require 'models/reply' require 'models/minimalistic' -class Topic; def after_find() end end -class Developer; def after_find() end end class SpecialDeveloper < Developer; end class TopicManualObserver @@ -43,6 +41,11 @@ class TopicObserver < ActiveRecord::Observer def after_find(topic) @topic = topic end + + # Create an after_save callback, so a notify_observer hook is created + # on :topic. + def after_save(nothing) + end end class MinimalisticObserver < ActiveRecord::Observer @@ -159,34 +162,6 @@ class LifecycleTest < ActiveRecord::TestCase assert_equal topic, observer.topic end - def test_after_find_is_not_created_if_its_not_used - # use a fresh class so an observer can't have defined an - # after_find on it - model_class = Class.new(ActiveRecord::Base) - observer_class = Class.new(ActiveRecord::Observer) - observer_class.observe(model_class) - - observer = observer_class.instance - - assert !model_class.method_defined?(:after_find) - end - - def test_after_find_is_not_clobbered_if_it_already_exists - # use a fresh observer class so we can instantiate it (Observer is - # a Singleton) - model_class = Class.new(ActiveRecord::Base) do - def after_find; end - end - original_method = model_class.instance_method(:after_find) - observer_class = Class.new(ActiveRecord::Observer) do - def after_find; end - end - observer_class.observe(model_class) - - observer = observer_class.instance - assert_equal original_method, model_class.instance_method(:after_find) - end - def test_invalid_observer assert_raise(ArgumentError) { Topic.observers = Object.new; Topic.instantiate_observers } end diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb index d033c1e760..721792132c 100644 --- a/activerecord/test/cases/nested_attributes_test.rb +++ b/activerecord/test/cases/nested_attributes_test.rb @@ -68,24 +68,38 @@ class TestNestedAttributesInGeneral < ActiveRecord::TestCase ship = pirate.create_ship(:name => 'Nights Dirty Lightning') assert_no_difference('Ship.count') do - pirate.update_attributes(:ship_attributes => { '_delete' => true }) + pirate.update_attributes(:ship_attributes => { '_destroy' => true }) end end - def test_a_model_should_respond_to_underscore_delete_and_return_if_it_is_marked_for_destruction + def test_a_model_should_respond_to_underscore_destroy_and_return_if_it_is_marked_for_destruction ship = Ship.create!(:name => 'Nights Dirty Lightning') - assert !ship._delete + assert !ship._destroy ship.mark_for_destruction - assert ship._delete + assert ship._destroy + end + + def test_underscore_delete_is_deprecated + ActiveSupport::Deprecation.expects(:warn) + ship = Ship.create!(:name => 'Nights Dirty Lightning') + ship._delete end end class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase + include AssertRaiseWithMessage + def setup @pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?") @ship = @pirate.create_ship(:name => 'Nights Dirty Lightning') end + def test_should_raise_argument_error_if_trying_to_build_polymorphic_belongs_to + assert_raise_with_message ArgumentError, "Cannot build association looter. Are you trying to build a polymorphic one-to-one association?" do + Treasure.new(:name => 'pearl', :looter_attributes => {:catchphrase => "Arrr"}) + end + end + def test_should_define_an_attribute_writer_method_for_the_association assert_respond_to @pirate, :ship_attributes= end @@ -98,9 +112,9 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name end - def test_should_not_build_a_new_record_if_there_is_no_id_and_delete_is_truthy + def test_should_not_build_a_new_record_if_there_is_no_id_and_destroy_is_truthy @ship.destroy - @pirate.reload.ship_attributes = { :name => 'Davy Jones Gold Dagger', :_delete => '1' } + @pirate.reload.ship_attributes = { :name => 'Davy Jones Gold Dagger', :_destroy => '1' } assert_nil @pirate.ship end @@ -120,8 +134,8 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase assert_equal 'Nights Dirty Lightning', @ship.name end - def test_should_not_replace_an_existing_record_if_there_is_no_id_and_delete_is_truthy - @pirate.reload.ship_attributes = { :name => 'Davy Jones Gold Dagger', :_delete => '1' } + def test_should_not_replace_an_existing_record_if_there_is_no_id_and_destroy_is_truthy + @pirate.reload.ship_attributes = { :name => 'Davy Jones Gold Dagger', :_destroy => '1' } assert_equal @ship, @pirate.ship assert_equal 'Nights Dirty Lightning', @pirate.ship.name @@ -148,29 +162,29 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name end - def test_should_delete_an_existing_record_if_there_is_a_matching_id_and_delete_is_truthy + def test_should_destroy_an_existing_record_if_there_is_a_matching_id_and_destroy_is_truthy @pirate.ship.destroy [1, '1', true, 'true'].each do |truth| @pirate.reload.create_ship(:name => 'Mister Pablo') assert_difference('Ship.count', -1) do - @pirate.update_attribute(:ship_attributes, { :id => @pirate.ship.id, :_delete => truth }) + @pirate.update_attribute(:ship_attributes, { :id => @pirate.ship.id, :_destroy => truth }) end end end - def test_should_not_delete_an_existing_record_if_delete_is_not_truthy + def test_should_not_destroy_an_existing_record_if_destroy_is_not_truthy [nil, '0', 0, 'false', false].each do |not_truth| assert_no_difference('Ship.count') do - @pirate.update_attribute(:ship_attributes, { :id => @pirate.ship.id, :_delete => not_truth }) + @pirate.update_attribute(:ship_attributes, { :id => @pirate.ship.id, :_destroy => not_truth }) end end end - def test_should_not_delete_an_existing_record_if_allow_destroy_is_false + def test_should_not_destroy_an_existing_record_if_allow_destroy_is_false Pirate.accepts_nested_attributes_for :ship, :allow_destroy => false, :reject_if => proc { |attributes| attributes.empty? } assert_no_difference('Ship.count') do - @pirate.update_attribute(:ship_attributes, { :id => @pirate.ship.id, :_delete => '1' }) + @pirate.update_attribute(:ship_attributes, { :id => @pirate.ship.id, :_destroy => '1' }) end Pirate.accepts_nested_attributes_for :ship, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? } @@ -193,7 +207,7 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase def test_should_not_destroy_the_associated_model_until_the_parent_is_saved assert_no_difference('Ship.count') do - @pirate.attributes = { :ship_attributes => { :id => @ship.id, :_delete => '1' } } + @pirate.attributes = { :ship_attributes => { :id => @ship.id, :_destroy => '1' } } end assert_difference('Ship.count', -1) do @pirate.save @@ -224,9 +238,9 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase assert_equal 'Arr', @ship.pirate.catchphrase end - def test_should_not_build_a_new_record_if_there_is_no_id_and_delete_is_truthy + def test_should_not_build_a_new_record_if_there_is_no_id_and_destroy_is_truthy @pirate.destroy - @ship.reload.pirate_attributes = { :catchphrase => 'Arr', :_delete => '1' } + @ship.reload.pirate_attributes = { :catchphrase => 'Arr', :_destroy => '1' } assert_nil @ship.pirate end @@ -246,8 +260,8 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase assert_equal 'Aye', @pirate.catchphrase end - def test_should_not_replace_an_existing_record_if_there_is_no_id_and_delete_is_truthy - @ship.reload.pirate_attributes = { :catchphrase => 'Arr', :_delete => '1' } + def test_should_not_replace_an_existing_record_if_there_is_no_id_and_destroy_is_truthy + @ship.reload.pirate_attributes = { :catchphrase => 'Arr', :_destroy => '1' } assert_equal @pirate, @ship.pirate assert_equal 'Aye', @ship.pirate.catchphrase @@ -274,29 +288,29 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase assert_equal 'Arr', @ship.pirate.catchphrase end - def test_should_delete_an_existing_record_if_there_is_a_matching_id_and_delete_is_truthy + def test_should_destroy_an_existing_record_if_there_is_a_matching_id_and_destroy_is_truthy @ship.pirate.destroy [1, '1', true, 'true'].each do |truth| @ship.reload.create_pirate(:catchphrase => 'Arr') assert_difference('Pirate.count', -1) do - @ship.update_attribute(:pirate_attributes, { :id => @ship.pirate.id, :_delete => truth }) + @ship.update_attribute(:pirate_attributes, { :id => @ship.pirate.id, :_destroy => truth }) end end end - def test_should_not_delete_an_existing_record_if_delete_is_not_truthy + def test_should_not_destroy_an_existing_record_if_destroy_is_not_truthy [nil, '0', 0, 'false', false].each do |not_truth| assert_no_difference('Pirate.count') do - @ship.update_attribute(:pirate_attributes, { :id => @ship.pirate.id, :_delete => not_truth }) + @ship.update_attribute(:pirate_attributes, { :id => @ship.pirate.id, :_destroy => not_truth }) end end end - def test_should_not_delete_an_existing_record_if_allow_destroy_is_false + def test_should_not_destroy_an_existing_record_if_allow_destroy_is_false Ship.accepts_nested_attributes_for :pirate, :allow_destroy => false, :reject_if => proc { |attributes| attributes.empty? } assert_no_difference('Pirate.count') do - @ship.update_attribute(:pirate_attributes, { :id => @ship.pirate.id, :_delete => '1' }) + @ship.update_attribute(:pirate_attributes, { :id => @ship.pirate.id, :_destroy => '1' }) end Ship.accepts_nested_attributes_for :pirate, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? } @@ -312,7 +326,7 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase def test_should_not_destroy_the_associated_model_until_the_parent_is_saved assert_no_difference('Pirate.count') do - @ship.attributes = { :pirate_attributes => { :id => @ship.pirate.id, '_delete' => true } } + @ship.attributes = { :pirate_attributes => { :id => @ship.pirate.id, '_destroy' => true } } end assert_difference('Pirate.count', -1) { @ship.save } end @@ -380,18 +394,18 @@ module NestedAttributesOnACollectionAssociationTests assert_equal 'Privateers Greed', @pirate.send(@association_name).last.name end - def test_should_not_assign_delete_key_to_a_record + def test_should_not_assign_destroy_key_to_a_record assert_nothing_raised ActiveRecord::UnknownAttributeError do - @pirate.send(association_setter, { 'foo' => { '_delete' => '0' }}) + @pirate.send(association_setter, { 'foo' => { '_destroy' => '0' }}) end end - def test_should_ignore_new_associated_records_with_truthy_delete_attribute + def test_should_ignore_new_associated_records_with_truthy_destroy_attribute @pirate.send(@association_name).destroy_all @pirate.reload.attributes = { association_getter => { 'foo' => { :name => 'Grace OMalley' }, - 'bar' => { :name => 'Privateers Greed', '_delete' => '1' } + 'bar' => { :name => 'Privateers Greed', '_destroy' => '1' } } } @@ -443,7 +457,7 @@ module NestedAttributesOnACollectionAssociationTests ['1', 1, 'true', true].each do |true_variable| record = @pirate.reload.send(@association_name).create!(:name => 'Grace OMalley') @pirate.send(association_setter, - @alternate_params[association_getter].merge('baz' => { :id => record.id, '_delete' => true_variable }) + @alternate_params[association_getter].merge('baz' => { :id => record.id, '_destroy' => true_variable }) ) assert_difference('@pirate.send(@association_name).count', -1) do @@ -454,7 +468,7 @@ module NestedAttributesOnACollectionAssociationTests def test_should_not_destroy_the_associated_model_with_a_non_truthy_argument [nil, '', '0', 0, 'false', false].each do |false_variable| - @alternate_params[association_getter]['foo']['_delete'] = false_variable + @alternate_params[association_getter]['foo']['_destroy'] = false_variable assert_no_difference('@pirate.send(@association_name).count') do @pirate.update_attributes(@alternate_params) end @@ -463,7 +477,7 @@ module NestedAttributesOnACollectionAssociationTests def test_should_not_destroy_the_associated_model_until_the_parent_is_saved assert_no_difference('@pirate.send(@association_name).count') do - @pirate.send(association_setter, @alternate_params[association_getter].merge('baz' => { :id => @child_1.id, '_delete' => true })) + @pirate.send(association_setter, @alternate_params[association_getter].merge('baz' => { :id => @child_1.id, '_destroy' => true })) end assert_difference('@pirate.send(@association_name).count', -1) { @pirate.save } end diff --git a/activerecord/test/cases/reflection_test.rb b/activerecord/test/cases/reflection_test.rb index a164f5e060..0eb2da720e 100644 --- a/activerecord/test/cases/reflection_test.rb +++ b/activerecord/test/cases/reflection_test.rb @@ -176,9 +176,9 @@ class ReflectionTest < ActiveRecord::TestCase def test_reflection_of_all_associations # FIXME these assertions bust a lot - assert_equal 31, Firm.reflect_on_all_associations.size - assert_equal 24, Firm.reflect_on_all_associations(:has_many).size - assert_equal 7, Firm.reflect_on_all_associations(:has_one).size + assert_equal 35, Firm.reflect_on_all_associations.size + assert_equal 26, Firm.reflect_on_all_associations(:has_many).size + assert_equal 9, Firm.reflect_on_all_associations(:has_one).size assert_equal 0, Firm.reflect_on_all_associations(:belongs_to).size end diff --git a/activerecord/test/cases/repair_helper.rb b/activerecord/test/cases/repair_helper.rb deleted file mode 100644 index 80d04010d6..0000000000 --- a/activerecord/test/cases/repair_helper.rb +++ /dev/null @@ -1,46 +0,0 @@ -module ActiveRecord - module Testing - module RepairHelper - extend ActiveSupport::Concern - - module Toolbox - def self.record_validations(*model_classes) - model_classes.inject({}) do |repair, klass| - repair[klass] ||= {} - [:validate, :validate_on_create, :validate_on_update].each do |callback| - the_callback = klass.instance_variable_get("@#{callback.to_s}_callbacks") - repair[klass][callback] = (the_callback.nil? ? nil : the_callback.dup) - end - repair - end - end - - def self.reset_validations(recorded) - recorded.each do |klass, repairs| - [:validate, :validate_on_create, :validate_on_update].each do |callback| - klass.instance_variable_set("@#{callback.to_s}_callbacks", repairs[callback]) - end - end - end - end - - module ClassMethods - def repair_validations(*model_classes) - setup do - @validation_repairs = ActiveRecord::Testing::RepairHelper::Toolbox.record_validations(*model_classes) - end - teardown do - ActiveRecord::Testing::RepairHelper::Toolbox.reset_validations(@validation_repairs) - end - end - end - - def repair_validations(*model_classes, &block) - validation_repairs = ActiveRecord::Testing::RepairHelper::Toolbox.record_validations(*model_classes) - return block.call - ensure - ActiveRecord::Testing::RepairHelper::Toolbox.reset_validations(validation_repairs) - end - end - end -end diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb index f6533b5396..aca70b4238 100644 --- a/activerecord/test/cases/transactions_test.rb +++ b/activerecord/test/cases/transactions_test.rb @@ -382,28 +382,28 @@ class TransactionTest < ActiveRecord::TestCase private def add_exception_raising_after_save_callback_to_topic - Topic.class_eval { def after_save() raise "Make the transaction rollback" end } + Topic.class_eval "def after_save_for_transaction; raise 'Make the transaction rollback' end" end def remove_exception_raising_after_save_callback_to_topic - Topic.class_eval { remove_method :after_save } + Topic.class_eval "def after_save_for_transaction; end" end def add_exception_raising_after_create_callback_to_topic - Topic.class_eval { def after_create() raise "Make the transaction rollback" end } + Topic.class_eval "def after_create_for_transaction; raise 'Make the transaction rollback' end" end def remove_exception_raising_after_create_callback_to_topic - Topic.class_eval { remove_method :after_create } + Topic.class_eval "def after_create_for_transaction; end" end %w(validation save destroy).each do |filter| define_method("add_cancelling_before_#{filter}_with_db_side_effect_to_topic") do - Topic.class_eval "def before_#{filter}() Book.create; false end" + Topic.class_eval "def before_#{filter}_for_transaction() Book.create; false end" end define_method("remove_cancelling_before_#{filter}_with_db_side_effect_to_topic") do - Topic.class_eval "remove_method :before_#{filter}" + Topic.class_eval "def before_#{filter}_for_transaction; end" end end end diff --git a/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb b/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb index 29c10de4fe..3794a0ebb9 100644 --- a/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb +++ b/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb @@ -2,9 +2,9 @@ require "cases/helper" require 'models/topic' require 'models/reply' -class I18nGenerateMessageValidationTest < Test::Unit::TestCase +class I18nGenerateMessageValidationTest < ActiveRecord::TestCase def setup - reset_callbacks Topic + Topic.reset_callbacks(:validate) @topic = Topic.new I18n.backend.store_translations :'en', { :activerecord => { @@ -17,14 +17,6 @@ class I18nGenerateMessageValidationTest < Test::Unit::TestCase } end - def reset_callbacks(*models) - models.each do |model| - model.instance_variable_set("@validate_callbacks", ActiveSupport::Callbacks::CallbackChain.new) - model.instance_variable_set("@validate_on_create_callbacks", ActiveSupport::Callbacks::CallbackChain.new) - model.instance_variable_set("@validate_on_update_callbacks", ActiveSupport::Callbacks::CallbackChain.new) - end - end - # validates_inclusion_of: generate_message(attr_name, :inclusion, :default => configuration[:message], :value => value) def test_generate_message_inclusion_with_default_message assert_equal 'is not included in the list', @topic.errors.generate_message(:title, :inclusion, :default => nil, :value => 'title') diff --git a/activerecord/test/cases/validations/i18n_validation_test.rb b/activerecord/test/cases/validations/i18n_validation_test.rb index 73d9c7249c..252138c0d6 100644 --- a/activerecord/test/cases/validations/i18n_validation_test.rb +++ b/activerecord/test/cases/validations/i18n_validation_test.rb @@ -4,7 +4,7 @@ require 'models/reply' class I18nValidationTest < ActiveRecord::TestCase def setup - reset_callbacks Topic + Topic.reset_callbacks(:validate) @topic = Topic.new @old_load_path, @old_backend = I18n.load_path, I18n.backend I18n.load_path.clear @@ -13,7 +13,7 @@ class I18nValidationTest < ActiveRecord::TestCase end def teardown - reset_callbacks Topic + Topic.reset_callbacks(:validate) I18n.load_path.replace @old_load_path I18n.backend = @old_backend end @@ -30,14 +30,6 @@ class I18nValidationTest < ActiveRecord::TestCase end end - def reset_callbacks(*models) - models.each do |model| - model.instance_variable_set("@validate_callbacks", ActiveSupport::Callbacks::CallbackChain.new) - model.instance_variable_set("@validate_on_create_callbacks", ActiveSupport::Callbacks::CallbackChain.new) - model.instance_variable_set("@validate_on_update_callbacks", ActiveSupport::Callbacks::CallbackChain.new) - end - end - def test_percent_s_interpolation_syntax_in_error_messages_was_deprecated assert_not_deprecated do default = "%s interpolation syntax was deprecated" @@ -710,9 +702,9 @@ class I18nValidationTest < ActiveRecord::TestCase end end -class ActiveRecordValidationsGenerateMessageI18nTests < ActiveSupport::TestCase +class ActiveRecordValidationsGenerateMessageI18nTests < ActiveRecord::TestCase + def setup - reset_callbacks Topic @topic = Topic.new I18n.backend.store_translations :'en', { :activerecord => { @@ -743,14 +735,6 @@ class ActiveRecordValidationsGenerateMessageI18nTests < ActiveSupport::TestCase } end - def reset_callbacks(*models) - models.each do |model| - model.instance_variable_set("@validate_callbacks", ActiveSupport::Callbacks::CallbackChain.new) - model.instance_variable_set("@validate_on_create_callbacks", ActiveSupport::Callbacks::CallbackChain.new) - model.instance_variable_set("@validate_on_update_callbacks", ActiveSupport::Callbacks::CallbackChain.new) - end - end - # validates_inclusion_of: generate_message(attr_name, :inclusion, :default => configuration[:message], :value => value) def test_generate_message_inclusion_with_default_message assert_equal 'is not included in the list', @topic.errors.generate_message(:title, :inclusion, :default => nil, :value => 'title') diff --git a/activerecord/test/cases/validations_test.rb b/activerecord/test/cases/validations_test.rb index a4e874e5e6..5cdb623eef 100644 --- a/activerecord/test/cases/validations_test.rb +++ b/activerecord/test/cases/validations_test.rb @@ -149,24 +149,24 @@ class ValidationsTest < ActiveRecord::TestCase end def test_validates_length_with_globally_modified_error_message - ActiveSupport::Deprecation.silence do - ActiveRecord::Errors.default_error_messages[:too_short] = 'tu est trops petit hombre {{count}}' - end + defaults = ActiveSupport::Deprecation.silence { ActiveRecord::Errors.default_error_messages } + original_message = defaults[:too_short] + defaults[:too_short] = 'tu est trops petit hombre {{count}}' Topic.validates_length_of :title, :minimum => 10 t = Topic.create(:title => 'too short') assert !t.valid? assert_equal ['tu est trops petit hombre 10'], t.errors[:title] + + ensure + defaults[:too_short] = original_message end def test_validates_acceptance_of_as_database_column - repair_validations(Reply) do - Reply.validates_acceptance_of(:author_name) - - reply = Reply.create("author_name" => "Dan Brown") - assert_equal "Dan Brown", reply["author_name"] - end + Topic.validates_acceptance_of(:author_name) + topic = Topic.create("author_name" => "Dan Brown") + assert_equal "Dan Brown", topic["author_name"] end def test_deprecated_validation_instance_methods diff --git a/activerecord/test/fixtures/accounts.yml b/activerecord/test/fixtures/accounts.yml index b2d0191900..32583042a8 100644 --- a/activerecord/test/fixtures/accounts.yml +++ b/activerecord/test/fixtures/accounts.yml @@ -2,6 +2,7 @@ signals37: id: 1 firm_id: 1 credit_limit: 50 + firm_name: 37signals unknown: id: 2 diff --git a/activerecord/test/models/author.rb b/activerecord/test/models/author.rb index f264f980d6..7cbc6e803f 100644 --- a/activerecord/test/models/author.rb +++ b/activerecord/test/models/author.rb @@ -94,8 +94,9 @@ class Author < ActiveRecord::Base belongs_to :author_address_extra, :dependent => :delete, :class_name => "AuthorAddress" attr_accessor :post_log + after_initialize :set_post_log - def after_initialize + def set_post_log @post_log = [] end diff --git a/activerecord/test/models/company.rb b/activerecord/test/models/company.rb index ab09f88a9f..b1a3930e4e 100644 --- a/activerecord/test/models/company.rb +++ b/activerecord/test/models/company.rb @@ -78,7 +78,12 @@ class Firm < Company # added order by id as in fixtures there are two accounts for Rails Core # Oracle tests were failing because of that as the second fixture was selected has_one :account_using_primary_key, :primary_key => "firm_id", :class_name => "Account", :order => "id" + has_one :account_using_foreign_and_primary_keys, :foreign_key => "firm_name", :primary_key => "name", :class_name => "Account" has_one :deletable_account, :foreign_key => "firm_id", :class_name => "Account", :dependent => :delete + + has_one :unautosaved_account, :foreign_key => "firm_id", :class_name => 'Account', :autosave => false + has_many :accounts + has_many :unautosaved_accounts, :foreign_key => "firm_id", :class_name => 'Account', :autosave => false end class DependentFirm < Company @@ -111,6 +116,8 @@ class Client < Company true end + before_destroy :overwrite_to_raise + # Used to test that read and question methods are not generated for these attributes def ruby_type read_attribute :ruby_type @@ -120,6 +127,9 @@ class Client < Company query_attribute :rating end + def overwrite_to_raise + end + class << self private @@ -144,6 +154,7 @@ end class Account < ActiveRecord::Base belongs_to :firm + belongs_to :unautosaved_firm, :foreign_key => "firm_id", :class_name => "Firm", :autosave => false def self.destroyed_account_ids @destroyed_account_ids ||= Hash.new { |h,k| h[k] = [] } diff --git a/activerecord/test/models/pirate.rb b/activerecord/test/models/pirate.rb index acf53fce8b..3d7c4bc48a 100644 --- a/activerecord/test/models/pirate.rb +++ b/activerecord/test/models/pirate.rb @@ -1,6 +1,8 @@ class Pirate < ActiveRecord::Base - belongs_to :parrot - has_and_belongs_to_many :parrots + belongs_to :parrot, :validate => true + belongs_to :non_validated_parrot, :class_name => 'Parrot' + has_and_belongs_to_many :parrots, :validate => true + has_and_belongs_to_many :non_validated_parrots, :class_name => 'Parrot' has_and_belongs_to_many :parrots_with_method_callbacks, :class_name => "Parrot", :before_add => :log_before_add, :after_add => :log_after_add, @@ -16,7 +18,8 @@ class Pirate < ActiveRecord::Base has_many :treasure_estimates, :through => :treasures, :source => :price_estimates # These both have :autosave enabled because accepts_nested_attributes_for is used on them. - has_one :ship + has_one :ship, :validate => true + has_one :non_validated_ship, :class_name => 'Ship' has_many :birds has_many :birds_with_method_callbacks, :class_name => "Bird", :before_add => :log_before_add, diff --git a/activerecord/test/models/project.rb b/activerecord/test/models/project.rb index 422b12dc83..416032cb75 100644 --- a/activerecord/test/models/project.rb +++ b/activerecord/test/models/project.rb @@ -22,8 +22,9 @@ class Project < ActiveRecord::Base has_and_belongs_to_many :well_payed_salary_groups, :class_name => "Developer", :group => "developers.salary", :having => "SUM(salary) > 10000", :select => "SUM(salary) as salary" attr_accessor :developers_log + after_initialize :set_developers_log - def after_initialize + def set_developers_log @developers_log = [] end diff --git a/activerecord/test/models/reply.rb b/activerecord/test/models/reply.rb index f5906dedd1..ba5a1d1d01 100644 --- a/activerecord/test/models/reply.rb +++ b/activerecord/test/models/reply.rb @@ -8,13 +8,13 @@ class Reply < Topic has_many :replies, :class_name => "SillyReply", :dependent => :destroy, :foreign_key => "parent_id" validate :errors_on_empty_content - validate_on_create :title_is_wrong_create + validate :title_is_wrong_create, :on => :create attr_accessible :title, :author_name, :author_email_address, :written_on, :content, :last_read, :parent_title validate :check_empty_title - validate_on_create :check_content_mismatch - validate_on_update :check_wrong_update + validate :check_content_mismatch, :on => :create + validate :check_wrong_update, :on => :update def check_empty_title errors[:title] << "Empty" unless attribute_present?("title") @@ -47,4 +47,4 @@ module Web class Reply < Web::Topic belongs_to :topic, :foreign_key => "parent_id", :counter_cache => true, :class_name => 'Web::Topic' end -end
\ No newline at end of file +end diff --git a/activerecord/test/models/ship.rb b/activerecord/test/models/ship.rb index 06759d64b8..d0df951622 100644 --- a/activerecord/test/models/ship.rb +++ b/activerecord/test/models/ship.rb @@ -1,7 +1,7 @@ class Ship < ActiveRecord::Base self.record_timestamps = false - belongs_to :pirate + belongs_to :pirate, :validate => true has_many :parts, :class_name => 'ShipPart', :autosave => true accepts_nested_attributes_for :pirate, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? } diff --git a/activerecord/test/models/topic.rb b/activerecord/test/models/topic.rb index 9594dc300a..baca4972cb 100644 --- a/activerecord/test/models/topic.rb +++ b/activerecord/test/models/topic.rb @@ -52,6 +52,15 @@ class Topic < ActiveRecord::Base id end + before_validation :before_validation_for_transaction + before_save :before_save_for_transaction + before_destroy :before_destroy_for_transaction + + after_save :after_save_for_transaction + after_create :after_create_for_transaction + + after_initialize :set_email_address + protected def approved=(val) @custom_approved = val @@ -66,15 +75,21 @@ class Topic < ActiveRecord::Base self.class.delete_all "parent_id = #{id}" end - def after_initialize + def set_email_address if self.new_record? self.author_email_address = 'test@test.com' end end + + def before_validation_for_transaction; end + def before_save_for_transaction; end + def before_destroy_for_transaction; end + def after_save_for_transaction; end + def after_create_for_transaction; end end module Web class Topic < ActiveRecord::Base has_many :replies, :dependent => :destroy, :foreign_key => "parent_id", :class_name => 'Web::Reply' end -end
\ No newline at end of file +end diff --git a/activerecord/test/models/treasure.rb b/activerecord/test/models/treasure.rb index 97c690c110..2a98e74f2c 100644 --- a/activerecord/test/models/treasure.rb +++ b/activerecord/test/models/treasure.rb @@ -3,4 +3,6 @@ class Treasure < ActiveRecord::Base belongs_to :looter, :polymorphic => true has_many :price_estimates, :as => :estimate_of + + accepts_nested_attributes_for :looter end diff --git a/activerecord/test/schema/mysql_specific_schema.rb b/activerecord/test/schema/mysql_specific_schema.rb index f44c33ae67..c78d99f4af 100644 --- a/activerecord/test/schema/mysql_specific_schema.rb +++ b/activerecord/test/schema/mysql_specific_schema.rb @@ -9,4 +9,16 @@ ActiveRecord::Schema.define do t.text :medium_text, :limit => 16777215 t.text :long_text, :limit => 2147483647 end + + ActiveRecord::Base.connection.execute <<-SQL +DROP PROCEDURE IF EXISTS ten; +SQL + + ActiveRecord::Base.connection.execute <<-SQL +CREATE PROCEDURE ten() SQL SECURITY INVOKER +BEGIN + select 10; +END +SQL + end diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index 9ab4cf6f43..15e5e12d03 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -22,6 +22,7 @@ ActiveRecord::Schema.define do # unless the ordering matters. In which case, define them below create_table :accounts, :force => true do |t| t.integer :firm_id + t.string :firm_name t.integer :credit_limit end diff --git a/activeresource/Rakefile b/activeresource/Rakefile index def489fad9..54c3fe44c6 100644 --- a/activeresource/Rakefile +++ b/activeresource/Rakefile @@ -34,11 +34,12 @@ Rake::TestTask.new { |t| t.verbose = true t.warning = true } + task :isolated_test do ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')) activesupport_path = "#{File.dirname(__FILE__)}/../activesupport/lib" Dir.glob("test/**/*_test.rb").all? do |file| - system(ruby, "-Ilib:test:#{activesupport_path}", file) + system(ruby, '-w', "-Ilib:test:#{activesupport_path}", file) end or raise "Failures" end @@ -74,6 +75,7 @@ spec = Gem::Specification.new do |s| end s.add_dependency('activesupport', '= 3.0.pre' + PKG_BUILD) + s.add_dependency('activemodel', '= 3.0.pre' + PKG_BUILD) s.require_path = 'lib' s.autorequire = 'active_resource' @@ -94,6 +96,12 @@ Rake::GemPackageTask.new(spec) do |p| p.need_zip = true end +task :gemspec do + File.open(File.join(File.dirname(__FILE__), "#{spec.name}.gemspec"), "w") do |file| + file.puts spec.to_ruby + end +end + task :lines do lines, codelines, total_lines, total_codelines = 0, 0, 0, 0 diff --git a/activeresource/activeresource.gemspec b/activeresource/activeresource.gemspec new file mode 100644 index 0000000000..c3bb6e3622 --- /dev/null +++ b/activeresource/activeresource.gemspec @@ -0,0 +1,37 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{activeresource} + s.version = "3.0.pre" + + s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version= + s.authors = ["David Heinemeier Hansson"] + s.autorequire = %q{active_resource} + s.date = %q{2009-09-01} + s.description = %q{Wraps web resources in model classes that can be manipulated through XML over REST.} + s.email = %q{david@loudthinking.com} + s.extra_rdoc_files = ["README"] + s.files = ["Rakefile", "README", "CHANGELOG", "lib/active_resource", "lib/active_resource/base.rb", "lib/active_resource/connection.rb", "lib/active_resource/custom_methods.rb", "lib/active_resource/exceptions.rb", "lib/active_resource/formats", "lib/active_resource/formats/json_format.rb", "lib/active_resource/formats/xml_format.rb", "lib/active_resource/formats.rb", "lib/active_resource/http_mock.rb", "lib/active_resource/observing.rb", "lib/active_resource/validations.rb", "lib/active_resource/version.rb", "lib/active_resource.rb", "lib/activeresource.rb", "test/abstract_unit.rb", "test/cases", "test/cases/authorization_test.rb", "test/cases/base", "test/cases/base/custom_methods_test.rb", "test/cases/base/equality_test.rb", "test/cases/base/load_test.rb", "test/cases/base_errors_test.rb", "test/cases/base_test.rb", "test/cases/finder_test.rb", "test/cases/format_test.rb", "test/cases/observing_test.rb", "test/cases/validations_test.rb", "test/connection_test.rb", "test/debug.log", "test/fixtures", "test/fixtures/beast.rb", "test/fixtures/customer.rb", "test/fixtures/person.rb", "test/fixtures/project.rb", "test/fixtures/proxy.rb", "test/fixtures/street_address.rb", "test/setter_trap.rb", "examples/simple.rb"] + s.homepage = %q{http://www.rubyonrails.org} + s.rdoc_options = ["--main", "README"] + s.require_paths = ["lib"] + s.rubyforge_project = %q{activeresource} + s.rubygems_version = %q{1.3.5} + s.summary = %q{Think Active Record for web resources.} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 3 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q<activesupport>, ["= 3.0.pre"]) + s.add_runtime_dependency(%q<activemodel>, ["= 3.0.pre"]) + else + s.add_dependency(%q<activesupport>, ["= 3.0.pre"]) + s.add_dependency(%q<activemodel>, ["= 3.0.pre"]) + end + else + s.add_dependency(%q<activesupport>, ["= 3.0.pre"]) + s.add_dependency(%q<activemodel>, ["= 3.0.pre"]) + end +end diff --git a/activeresource/lib/active_resource/observing.rb b/activeresource/lib/active_resource/observing.rb index 94836f4bb1..3c74d49c80 100644 --- a/activeresource/lib/active_resource/observing.rb +++ b/activeresource/lib/active_resource/observing.rb @@ -4,7 +4,18 @@ module ActiveResource include ActiveModel::Observing included do - wrap_with_notifications :create, :save, :update, :destroy + %w( create save update destroy ).each do |method| + class_eval(<<-EOS, __FILE__, __LINE__ + 1) + def #{method}_with_notifications(*args, &block) + notify_observers(:before_#{method}) + if result = #{method}_without_notifications(*args, &block) + notify_observers(:after_#{method}) + end + result + end + EOS + alias_method_chain(method, :notifications) + end end end end diff --git a/activeresource/lib/active_resource/validations.rb b/activeresource/lib/active_resource/validations.rb index d4d282e273..67b69fa505 100644 --- a/activeresource/lib/active_resource/validations.rb +++ b/activeresource/lib/active_resource/validations.rb @@ -93,9 +93,9 @@ module ActiveResource # content-type of the error-block received def load_remote_errors(remote_errors, save_cache = false ) #:nodoc: case remote_errors.response['Content-Type'] - when 'application/xml' + when /xml/ errors.from_xml(remote_errors.response.body, save_cache) - when 'application/json' + when /json/ errors.from_json(remote_errors.response.body, save_cache) end end diff --git a/activeresource/lib/activeresource.rb b/activeresource/lib/activeresource.rb deleted file mode 100644 index e076455b16..0000000000 --- a/activeresource/lib/activeresource.rb +++ /dev/null @@ -1 +0,0 @@ -require 'active_resource' diff --git a/activeresource/test/cases/base_errors_test.rb b/activeresource/test/cases/base_errors_test.rb index eca00e9ca8..1eb7765132 100644 --- a/activeresource/test/cases/base_errors_test.rb +++ b/activeresource/test/cases/base_errors_test.rb @@ -4,8 +4,8 @@ require "fixtures/person" class BaseErrorsTest < Test::Unit::TestCase def setup ActiveResource::HttpMock.respond_to do |mock| - mock.post "/people.xml", {}, %q(<?xml version="1.0" encoding="UTF-8"?><errors><error>Age can't be blank</error><error>Name can't be blank</error><error>Name must start with a letter</error><error>Person quota full for today.</error></errors>), 422, {'Content-Type' => 'application/xml'} - mock.post "/people.json", {}, %q({"errors":["Age can't be blank","Name can't be blank","Name must start with a letter","Person quota full for today."]}), 422, {'Content-Type' => 'application/json'} + mock.post "/people.xml", {}, %q(<?xml version="1.0" encoding="UTF-8"?><errors><error>Age can't be blank</error><error>Name can't be blank</error><error>Name must start with a letter</error><error>Person quota full for today.</error></errors>), 422, {'Content-Type' => 'application/xml; charset=utf-8'} + mock.post "/people.json", {}, %q({"errors":["Age can't be blank","Name can't be blank","Name must start with a letter","Person quota full for today."]}), 422, {'Content-Type' => 'application/json; charset=utf-8'} end end diff --git a/activeresource/test/cases/observing_test.rb b/activeresource/test/cases/observing_test.rb index 334b256772..9599ff7b0f 100644 --- a/activeresource/test/cases/observing_test.rb +++ b/activeresource/test/cases/observing_test.rb @@ -1,4 +1,6 @@ require 'abstract_unit' +require 'fixtures/person' +require 'active_support/core_ext/hash/conversions' class ObservingTest < Test::Unit::TestCase cattr_accessor :history diff --git a/activeresource/test/cases/validations_test.rb b/activeresource/test/cases/validations_test.rb index a8ab7d64e7..c05f625fb7 100644 --- a/activeresource/test/cases/validations_test.rb +++ b/activeresource/test/cases/validations_test.rb @@ -1,5 +1,6 @@ require 'abstract_unit' -require "fixtures/project" +require 'fixtures/project' +require 'active_support/core_ext/hash/conversions' # The validations are tested thoroughly under ActiveModel::Validations # This test case simply makes sur that they are all accessible by diff --git a/activesupport/Rakefile b/activesupport/Rakefile index 238594debb..91c874d729 100644 --- a/activesupport/Rakefile +++ b/activesupport/Rakefile @@ -24,7 +24,7 @@ Rake::TestTask.new { |t| task :isolated_test do ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')) Dir['test/**/*_test.rb'].all? do |file| - system(ruby, '-Ilib:test', file) + system(ruby, '-w', '-Ilib:test', file) end or raise "Failures" end @@ -68,6 +68,12 @@ Rake::GemPackageTask.new(spec) do |p| p.need_zip = true end +task :gemspec do + File.open(File.join(File.dirname(__FILE__), "#{spec.name}.gemspec"), "w") do |file| + file.puts spec.to_ruby + end +end + desc "Publish the beta gem" task :pgem => [:package] do require 'rake/contrib/sshpublisher' diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec new file mode 100644 index 0000000000..9260e068ed --- /dev/null +++ b/activesupport/activesupport.gemspec @@ -0,0 +1,28 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{activesupport} + s.version = "3.0.pre" + + s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version= + s.authors = ["David Heinemeier Hansson"] + s.date = %q{2009-09-01} + s.description = %q{Utility library which carries commonly used classes and goodies from the Rails framework} + s.email = %q{david@loudthinking.com} + s.files = ["CHANGELOG", "README", "lib/active_support", "lib/active_support/all.rb", "lib/active_support/autoload.rb", "lib/active_support/backtrace_cleaner.rb", "lib/active_support/base64.rb", "lib/active_support/basic_object.rb", "lib/active_support/buffered_logger.rb", "lib/active_support/cache", "lib/active_support/cache/compressed_mem_cache_store.rb", "lib/active_support/cache/file_store.rb", "lib/active_support/cache/mem_cache_store.rb", "lib/active_support/cache/memory_store.rb", "lib/active_support/cache/strategy", "lib/active_support/cache/strategy/local_cache.rb", "lib/active_support/cache/synchronized_memory_store.rb", "lib/active_support/cache.rb", "lib/active_support/callbacks.rb", "lib/active_support/concern.rb", "lib/active_support/concurrent_hash.rb", "lib/active_support/core_ext", "lib/active_support/core_ext/array", "lib/active_support/core_ext/array/access.rb", "lib/active_support/core_ext/array/conversions.rb", "lib/active_support/core_ext/array/extract_options.rb", "lib/active_support/core_ext/array/grouping.rb", "lib/active_support/core_ext/array/random_access.rb", "lib/active_support/core_ext/array/wrap.rb", "lib/active_support/core_ext/array.rb", "lib/active_support/core_ext/benchmark.rb", "lib/active_support/core_ext/big_decimal", "lib/active_support/core_ext/big_decimal/conversions.rb", "lib/active_support/core_ext/big_decimal.rb", "lib/active_support/core_ext/boolean", "lib/active_support/core_ext/boolean/conversions.rb", "lib/active_support/core_ext/boolean.rb", "lib/active_support/core_ext/cgi", "lib/active_support/core_ext/cgi/escape_skipping_slashes.rb", "lib/active_support/core_ext/cgi.rb", "lib/active_support/core_ext/class", "lib/active_support/core_ext/class/attribute_accessors.rb", "lib/active_support/core_ext/class/delegating_attributes.rb", "lib/active_support/core_ext/class/inheritable_attributes.rb", "lib/active_support/core_ext/class/removal.rb", "lib/active_support/core_ext/class.rb", "lib/active_support/core_ext/date", "lib/active_support/core_ext/date/acts_like.rb", "lib/active_support/core_ext/date/calculations.rb", "lib/active_support/core_ext/date/conversions.rb", "lib/active_support/core_ext/date/freeze.rb", "lib/active_support/core_ext/date.rb", "lib/active_support/core_ext/date_time", "lib/active_support/core_ext/date_time/acts_like.rb", "lib/active_support/core_ext/date_time/calculations.rb", "lib/active_support/core_ext/date_time/conversions.rb", "lib/active_support/core_ext/date_time/zones.rb", "lib/active_support/core_ext/date_time.rb", "lib/active_support/core_ext/enumerable.rb", "lib/active_support/core_ext/exception.rb", "lib/active_support/core_ext/file", "lib/active_support/core_ext/file/atomic.rb", "lib/active_support/core_ext/file.rb", "lib/active_support/core_ext/float", "lib/active_support/core_ext/float/rounding.rb", "lib/active_support/core_ext/float.rb", "lib/active_support/core_ext/hash", "lib/active_support/core_ext/hash/conversions.rb", "lib/active_support/core_ext/hash/deep_merge.rb", "lib/active_support/core_ext/hash/diff.rb", "lib/active_support/core_ext/hash/except.rb", "lib/active_support/core_ext/hash/indifferent_access.rb", "lib/active_support/core_ext/hash/keys.rb", "lib/active_support/core_ext/hash/reverse_merge.rb", "lib/active_support/core_ext/hash/slice.rb", "lib/active_support/core_ext/hash.rb", "lib/active_support/core_ext/integer", "lib/active_support/core_ext/integer/even_odd.rb", "lib/active_support/core_ext/integer/inflections.rb", "lib/active_support/core_ext/integer/time.rb", "lib/active_support/core_ext/integer.rb", "lib/active_support/core_ext/kernel", "lib/active_support/core_ext/kernel/agnostics.rb", "lib/active_support/core_ext/kernel/daemonizing.rb", "lib/active_support/core_ext/kernel/debugger.rb", "lib/active_support/core_ext/kernel/reporting.rb", "lib/active_support/core_ext/kernel/requires.rb", "lib/active_support/core_ext/kernel.rb", "lib/active_support/core_ext/load_error.rb", "lib/active_support/core_ext/logger.rb", "lib/active_support/core_ext/module", "lib/active_support/core_ext/module/aliasing.rb", "lib/active_support/core_ext/module/attr_accessor_with_default.rb", "lib/active_support/core_ext/module/attr_internal.rb", "lib/active_support/core_ext/module/attribute_accessors.rb", "lib/active_support/core_ext/module/delegation.rb", "lib/active_support/core_ext/module/deprecation.rb", "lib/active_support/core_ext/module/inclusion.rb", "lib/active_support/core_ext/module/introspection.rb", "lib/active_support/core_ext/module/loading.rb", "lib/active_support/core_ext/module/synchronization.rb", "lib/active_support/core_ext/module.rb", "lib/active_support/core_ext/name_error.rb", "lib/active_support/core_ext/nil", "lib/active_support/core_ext/nil/conversions.rb", "lib/active_support/core_ext/nil.rb", "lib/active_support/core_ext/numeric", "lib/active_support/core_ext/numeric/bytes.rb", "lib/active_support/core_ext/numeric/time.rb", "lib/active_support/core_ext/numeric.rb", "lib/active_support/core_ext/object", "lib/active_support/core_ext/object/acts_like.rb", "lib/active_support/core_ext/object/blank.rb", "lib/active_support/core_ext/object/conversions.rb", "lib/active_support/core_ext/object/duplicable.rb", "lib/active_support/core_ext/object/extending.rb", "lib/active_support/core_ext/object/instance_variables.rb", "lib/active_support/core_ext/object/metaclass.rb", "lib/active_support/core_ext/object/misc.rb", "lib/active_support/core_ext/object/returning.rb", "lib/active_support/core_ext/object/tap.rb", "lib/active_support/core_ext/object/try.rb", "lib/active_support/core_ext/object/with_options.rb", "lib/active_support/core_ext/object.rb", "lib/active_support/core_ext/proc.rb", "lib/active_support/core_ext/process", "lib/active_support/core_ext/process/daemon.rb", "lib/active_support/core_ext/process.rb", "lib/active_support/core_ext/range", "lib/active_support/core_ext/range/blockless_step.rb", "lib/active_support/core_ext/range/conversions.rb", "lib/active_support/core_ext/range/include_range.rb", "lib/active_support/core_ext/range/overlaps.rb", "lib/active_support/core_ext/range.rb", "lib/active_support/core_ext/regexp.rb", "lib/active_support/core_ext/rexml.rb", "lib/active_support/core_ext/string", "lib/active_support/core_ext/string/access.rb", "lib/active_support/core_ext/string/behavior.rb", "lib/active_support/core_ext/string/bytesize.rb", "lib/active_support/core_ext/string/conversions.rb", "lib/active_support/core_ext/string/filters.rb", "lib/active_support/core_ext/string/inflections.rb", "lib/active_support/core_ext/string/interpolation.rb", "lib/active_support/core_ext/string/iterators.rb", "lib/active_support/core_ext/string/multibyte.rb", "lib/active_support/core_ext/string/starts_ends_with.rb", "lib/active_support/core_ext/string/xchar.rb", "lib/active_support/core_ext/string.rb", "lib/active_support/core_ext/symbol", "lib/active_support/core_ext/symbol/to_proc.rb", "lib/active_support/core_ext/symbol.rb", "lib/active_support/core_ext/time", "lib/active_support/core_ext/time/acts_like.rb", "lib/active_support/core_ext/time/calculations.rb", "lib/active_support/core_ext/time/conversions.rb", "lib/active_support/core_ext/time/marshal_with_utc_flag.rb", "lib/active_support/core_ext/time/publicize_conversion_methods.rb", "lib/active_support/core_ext/time/zones.rb", "lib/active_support/core_ext/time.rb", "lib/active_support/core_ext/uri.rb", "lib/active_support/core_ext.rb", "lib/active_support/dependencies.rb", "lib/active_support/dependency_module.rb", "lib/active_support/deprecation", "lib/active_support/deprecation/behaviors.rb", "lib/active_support/deprecation/method_wrappers.rb", "lib/active_support/deprecation/proxy_wrappers.rb", "lib/active_support/deprecation/reporting.rb", "lib/active_support/deprecation.rb", "lib/active_support/duration.rb", "lib/active_support/gzip.rb", "lib/active_support/hash_with_indifferent_access.rb", "lib/active_support/inflections.rb", "lib/active_support/inflector.rb", "lib/active_support/json", "lib/active_support/json/backends", "lib/active_support/json/backends/jsongem.rb", "lib/active_support/json/backends/yaml.rb", "lib/active_support/json/decoding.rb", "lib/active_support/json/encoding.rb", "lib/active_support/json/variable.rb", "lib/active_support/json.rb", "lib/active_support/locale", "lib/active_support/locale/en.yml", "lib/active_support/memoizable.rb", "lib/active_support/message_encryptor.rb", "lib/active_support/message_verifier.rb", "lib/active_support/mini.rb", "lib/active_support/multibyte", "lib/active_support/multibyte/chars.rb", "lib/active_support/multibyte/exceptions.rb", "lib/active_support/multibyte/unicode_database.rb", "lib/active_support/multibyte.rb", "lib/active_support/new_callbacks.rb", "lib/active_support/option_merger.rb", "lib/active_support/ordered_hash.rb", "lib/active_support/ordered_options.rb", "lib/active_support/rescuable.rb", "lib/active_support/ruby", "lib/active_support/ruby/shim.rb", "lib/active_support/secure_random.rb", "lib/active_support/string_inquirer.rb", "lib/active_support/test_case.rb", "lib/active_support/testing", "lib/active_support/testing/assertions.rb", "lib/active_support/testing/declarative.rb", "lib/active_support/testing/default.rb", "lib/active_support/testing/deprecation.rb", "lib/active_support/testing/isolation.rb", "lib/active_support/testing/pending.rb", "lib/active_support/testing/performance.rb", "lib/active_support/testing/setup_and_teardown.rb", "lib/active_support/time", "lib/active_support/time/autoload.rb", "lib/active_support/time.rb", "lib/active_support/time_with_zone.rb", "lib/active_support/values", "lib/active_support/values/time_zone.rb", "lib/active_support/values/unicode_tables.dat", "lib/active_support/vendor", "lib/active_support/vendor/builder-2.1.2", "lib/active_support/vendor/builder-2.1.2/blankslate.rb", "lib/active_support/vendor/builder-2.1.2/builder", "lib/active_support/vendor/builder-2.1.2/builder/blankslate.rb", "lib/active_support/vendor/builder-2.1.2/builder/css.rb", "lib/active_support/vendor/builder-2.1.2/builder/xchar.rb", "lib/active_support/vendor/builder-2.1.2/builder/xmlbase.rb", "lib/active_support/vendor/builder-2.1.2/builder/xmlevents.rb", "lib/active_support/vendor/builder-2.1.2/builder/xmlmarkup.rb", "lib/active_support/vendor/builder-2.1.2/builder.rb", "lib/active_support/vendor/i18n-0.1.3", "lib/active_support/vendor/i18n-0.1.3/i18n.gemspec", "lib/active_support/vendor/i18n-0.1.3/lib", "lib/active_support/vendor/i18n-0.1.3/lib/i18n", "lib/active_support/vendor/i18n-0.1.3/lib/i18n/backend", "lib/active_support/vendor/i18n-0.1.3/lib/i18n/backend/simple.rb", "lib/active_support/vendor/i18n-0.1.3/lib/i18n/exceptions.rb", "lib/active_support/vendor/i18n-0.1.3/lib/i18n.rb", "lib/active_support/vendor/i18n-0.1.3/MIT-LICENSE", "lib/active_support/vendor/i18n-0.1.3/Rakefile", "lib/active_support/vendor/i18n-0.1.3/README.textile", "lib/active_support/vendor/i18n-0.1.3/test", "lib/active_support/vendor/i18n-0.1.3/test/all.rb", "lib/active_support/vendor/i18n-0.1.3/test/i18n_exceptions_test.rb", "lib/active_support/vendor/i18n-0.1.3/test/i18n_test.rb", "lib/active_support/vendor/i18n-0.1.3/test/locale", "lib/active_support/vendor/i18n-0.1.3/test/locale/en.rb", "lib/active_support/vendor/i18n-0.1.3/test/locale/en.yml", "lib/active_support/vendor/i18n-0.1.3/test/simple_backend_test.rb", "lib/active_support/vendor/memcache-client-1.6.5", "lib/active_support/vendor/memcache-client-1.6.5/memcache.rb", "lib/active_support/vendor/tzinfo-0.3.13", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/data_timezone.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/data_timezone_info.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Africa", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Africa/Algiers.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Africa/Cairo.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Africa/Casablanca.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Africa/Harare.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Africa/Johannesburg.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Africa/Monrovia.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Africa/Nairobi.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Argentina", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Argentina/Buenos_Aires.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Argentina/San_Juan.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Bogota.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Caracas.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Chicago.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Chihuahua.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Denver.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Godthab.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Guatemala.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Halifax.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Indiana", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Indiana/Indianapolis.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Juneau.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/La_Paz.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Lima.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Los_Angeles.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Mazatlan.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Mexico_City.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Monterrey.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/New_York.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Phoenix.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Regina.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Santiago.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Sao_Paulo.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/St_Johns.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Tijuana.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Almaty.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Baghdad.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Baku.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Bangkok.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Chongqing.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Colombo.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Dhaka.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Hong_Kong.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Irkutsk.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Jakarta.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Jerusalem.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Kabul.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Kamchatka.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Karachi.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Kathmandu.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Kolkata.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Krasnoyarsk.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Kuala_Lumpur.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Kuwait.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Magadan.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Muscat.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Novosibirsk.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Rangoon.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Riyadh.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Seoul.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Shanghai.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Singapore.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Taipei.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Tashkent.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Tbilisi.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Tehran.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Tokyo.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Ulaanbaatar.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Urumqi.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Vladivostok.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Yakutsk.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Yekaterinburg.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Yerevan.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Atlantic", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Atlantic/Azores.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Atlantic/Cape_Verde.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Atlantic/South_Georgia.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Australia", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Australia/Adelaide.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Australia/Brisbane.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Australia/Darwin.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Australia/Hobart.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Australia/Melbourne.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Australia/Perth.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Australia/Sydney.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Etc", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Etc/UTC.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Amsterdam.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Athens.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Belgrade.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Berlin.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Bratislava.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Brussels.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Bucharest.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Budapest.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Copenhagen.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Dublin.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Helsinki.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Istanbul.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Kiev.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Lisbon.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Ljubljana.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/London.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Madrid.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Minsk.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Moscow.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Paris.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Prague.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Riga.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Rome.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Sarajevo.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Skopje.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Sofia.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Stockholm.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Tallinn.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Vienna.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Vilnius.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Warsaw.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Zagreb.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Auckland.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Fiji.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Guam.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Honolulu.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Majuro.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Midway.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Noumea.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Pago_Pago.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Port_Moresby.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Tongatapu.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/info_timezone.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/linked_timezone.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/linked_timezone_info.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/offset_rationals.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/ruby_core_support.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/time_or_datetime.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/timezone.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/timezone_definition.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/timezone_info.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/timezone_offset_info.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/timezone_period.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo/timezone_transition_info.rb", "lib/active_support/vendor/tzinfo-0.3.13/tzinfo.rb", "lib/active_support/vendor.rb", "lib/active_support/version.rb", "lib/active_support/whiny_nil.rb", "lib/active_support/xml_mini", "lib/active_support/xml_mini/jdom.rb", "lib/active_support/xml_mini/libxml.rb", "lib/active_support/xml_mini/nokogiri.rb", "lib/active_support/xml_mini/rexml.rb", "lib/active_support/xml_mini.rb", "lib/active_support.rb", "lib/activesupport.rb"] + s.homepage = %q{http://www.rubyonrails.org} + s.require_paths = ["lib"] + s.rubyforge_project = %q{activesupport} + s.rubygems_version = %q{1.3.5} + s.summary = %q{Support and utility classes used by the Rails framework.} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 3 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + else + end + else + end +end diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb index a20635ba62..3372fb853a 100644 --- a/activesupport/lib/active_support.rb +++ b/activesupport/lib/active_support.rb @@ -37,4 +37,5 @@ end require 'active_support/autoload' require 'active_support/vendor' +require 'active_support/vendor/i18n' I18n.load_path << "#{File.dirname(__FILE__)}/active_support/locale/en.yml" diff --git a/activesupport/lib/active_support/autoload.rb b/activesupport/lib/active_support/autoload.rb index 75706855d6..423d5448c3 100644 --- a/activesupport/lib/active_support/autoload.rb +++ b/activesupport/lib/active_support/autoload.rb @@ -17,6 +17,7 @@ module ActiveSupport autoload :Multibyte, 'active_support/multibyte' autoload :NewCallbacks, 'active_support/new_callbacks' autoload :OptionMerger, 'active_support/option_merger' + autoload :Orchestra, 'active_support/orchestra' autoload :OrderedHash, 'active_support/ordered_hash' autoload :OrderedOptions, 'active_support/ordered_options' autoload :Rescuable, 'active_support/rescuable' diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb index e28df8efa5..25f9555388 100644 --- a/activesupport/lib/active_support/cache.rb +++ b/activesupport/lib/active_support/cache.rb @@ -107,16 +107,14 @@ module ActiveSupport class Store cattr_accessor :logger - attr_reader :silence, :logger_off + attr_reader :silence + alias :silence? :silence def silence! @silence = true self end - alias silence? silence - alias logger_off? logger_off - # Fetches data from the cache, using the given key. If there is data in # the cache with the given key, then that data is returned. # @@ -157,26 +155,13 @@ module ActiveSupport # cache.fetch("foo") # => "bar" # sleep(6) # cache.fetch("foo") # => nil - def fetch(key, options = {}) - @logger_off = true + def fetch(key, options = {}, &block) if !options[:force] && value = read(key, options) - @logger_off = false - log("hit", key, options) value elsif block_given? - @logger_off = false - log("miss", key, options) - - value = nil - ms = Benchmark.ms { value = yield } - - @logger_off = true - write(key, value, options) - @logger_off = false - - log('write (will save %.2fms)' % ms, key, nil) - - value + result = instrument(:generate, key, options, &block) + write(key, result, options) + result end end @@ -191,8 +176,8 @@ module ActiveSupport # For example, FileStore supports the +:expires_in+ option, which # makes the method return nil for cache items older than the specified # period. - def read(key, options = nil) - log("read", key, options) + def read(key, options = nil, &block) + instrument(:read, key, options, &block) end # Writes the given value to the cache, with the given key. @@ -210,20 +195,20 @@ module ActiveSupport # cache.read("foo") # => "bar" # sleep(6) # cache.read("foo") # => nil - def write(key, value, options = nil) - log("write", key, options) + def write(key, value, options = nil, &block) + instrument(:write, key, options, &block) end - def delete(key, options = nil) - log("delete", key, options) + def delete(key, options = nil, &block) + instrument(:delete, key, options, &block) end - def delete_matched(matcher, options = nil) - log("delete matched", matcher.inspect, options) + def delete_matched(matcher, options = nil, &block) + instrument(:delete_matched, matcher.inspect, options, &block) end - def exist?(key, options = nil) - log("exist?", key, options) + def exist?(key, options = nil, &block) + instrument(:exist?, key, options, &block) end def increment(key, amount = 1) @@ -247,14 +232,21 @@ module ActiveSupport private def expires_in(options) expires_in = options && options[:expires_in] - raise ":expires_in must be a number" if expires_in && !expires_in.is_a?(Numeric) - expires_in || 0 end + def instrument(operation, key, options, &block) + payload = { :key => key } + payload.merge!(options) if options.is_a?(Hash) + + event = ActiveSupport::Orchestra.instrument(:"cache_#{operation}", payload, &block) + log("#{operation} (%.1fms)" % event.duration, key, options) + event.result + end + def log(operation, key, options) - logger.debug("Cache #{operation}: #{key}#{options ? " (#{options.inspect})" : ""}") if logger && !silence? && !logger_off? + logger.debug("Cache #{operation}: #{key}#{options ? " (#{options.inspect})" : ""}") if logger && !silence? end end end diff --git a/activesupport/lib/active_support/cache/file_store.rb b/activesupport/lib/active_support/cache/file_store.rb index 75eed5ed94..7521efe7c5 100644 --- a/activesupport/lib/active_support/cache/file_store.rb +++ b/activesupport/lib/active_support/cache/file_store.rb @@ -16,49 +16,53 @@ module ActiveSupport # - +:expires_in+ - the number of seconds that this value may stay in # the cache. def read(name, options = nil) - super + super do + file_name = real_file_path(name) + expires = expires_in(options) - file_name = real_file_path(name) - expires = expires_in(options) - - if File.exist?(file_name) && (expires <= 0 || Time.now - File.mtime(file_name) < expires) - File.open(file_name, 'rb') { |f| Marshal.load(f) } + if File.exist?(file_name) && (expires <= 0 || Time.now - File.mtime(file_name) < expires) + File.open(file_name, 'rb') { |f| Marshal.load(f) } + end end end # Writes a value to the cache. def write(name, value, options = nil) - super - ensure_cache_path(File.dirname(real_file_path(name))) - File.atomic_write(real_file_path(name), cache_path) { |f| Marshal.dump(value, f) } - value + super do + ensure_cache_path(File.dirname(real_file_path(name))) + File.atomic_write(real_file_path(name), cache_path) { |f| Marshal.dump(value, f) } + value + end rescue => e logger.error "Couldn't create cache directory: #{name} (#{e.message})" if logger end def delete(name, options = nil) - super - File.delete(real_file_path(name)) + super do + File.delete(real_file_path(name)) + end rescue SystemCallError => e # If there's no cache, then there's nothing to complain about end def delete_matched(matcher, options = nil) - super - search_dir(@cache_path) do |f| - if f =~ matcher - begin - File.delete(f) - rescue SystemCallError => e - # If there's no cache, then there's nothing to complain about + super do + search_dir(@cache_path) do |f| + if f =~ matcher + begin + File.delete(f) + rescue SystemCallError => e + # If there's no cache, then there's nothing to complain about + end end end end end def exist?(name, options = nil) - super - File.exist?(real_file_path(name)) + super do + File.exist?(real_file_path(name)) + end end private diff --git a/activesupport/lib/active_support/cache/mem_cache_store.rb b/activesupport/lib/active_support/cache/mem_cache_store.rb index 96a8000778..ea38baa9ad 100644 --- a/activesupport/lib/active_support/cache/mem_cache_store.rb +++ b/activesupport/lib/active_support/cache/mem_cache_store.rb @@ -1,4 +1,4 @@ -require 'memcache' +require 'active_support/vendor/memcache' module ActiveSupport module Cache @@ -54,8 +54,9 @@ module ActiveSupport end def read(key, options = nil) # :nodoc: - super - @data.get(key, raw?(options)) + super do + @data.get(key, raw?(options)) + end rescue MemCache::MemCacheError => e logger.error("MemCacheError (#{e}): #{e.message}") nil @@ -69,22 +70,24 @@ module ActiveSupport # - <tt>:expires_in</tt> - the number of seconds that this value may stay in # the cache. See ActiveSupport::Cache::Store#write for an example. def write(key, value, options = nil) - super - method = options && options[:unless_exist] ? :add : :set - # memcache-client will break the connection if you send it an integer - # in raw mode, so we convert it to a string to be sure it continues working. - value = value.to_s if raw?(options) - response = @data.send(method, key, value, expires_in(options), raw?(options)) - response == Response::STORED + super do + method = options && options[:unless_exist] ? :add : :set + # memcache-client will break the connection if you send it an integer + # in raw mode, so we convert it to a string to be sure it continues working. + value = value.to_s if raw?(options) + response = @data.send(method, key, value, expires_in(options), raw?(options)) + response == Response::STORED + end rescue MemCache::MemCacheError => e logger.error("MemCacheError (#{e}): #{e.message}") false end def delete(key, options = nil) # :nodoc: - super - response = @data.delete(key, expires_in(options)) - response == Response::DELETED + super do + response = @data.delete(key, expires_in(options)) + response == Response::DELETED + end rescue MemCache::MemCacheError => e logger.error("MemCacheError (#{e}): #{e.message}") false @@ -94,7 +97,9 @@ module ActiveSupport # Doesn't call super, cause exist? in memcache is in fact a read # But who cares? Reading is very fast anyway # Local cache is checked first, if it doesn't know then memcache itself is read from - !read(key, options).nil? + super do + !read(key, options).nil? + end end def increment(key, amount = 1) # :nodoc: diff --git a/activesupport/lib/active_support/cache/memory_store.rb b/activesupport/lib/active_support/cache/memory_store.rb index 21ba79cf3d..66ce1bc93a 100644 --- a/activesupport/lib/active_support/cache/memory_store.rb +++ b/activesupport/lib/active_support/cache/memory_store.rb @@ -20,28 +20,33 @@ module ActiveSupport end def read(name, options = nil) - super - @data[name] + super do + @data[name] + end end def write(name, value, options = nil) - super - @data[name] = (value.duplicable? ? value.dup : value).freeze + super do + @data[name] = (value.duplicable? ? value.dup : value).freeze + end end def delete(name, options = nil) - super - @data.delete(name) + super do + @data.delete(name) + end end def delete_matched(matcher, options = nil) - super - @data.delete_if { |k,v| k =~ matcher } + super do + @data.delete_if { |k,v| k =~ matcher } + end end def exist?(name,options = nil) - super - @data.has_key?(name) + super do + @data.has_key?(name) + end end def clear diff --git a/activesupport/lib/active_support/core_ext/array/conversions.rb b/activesupport/lib/active_support/core_ext/array/conversions.rb index c53cf3f530..0743ab181e 100644 --- a/activesupport/lib/active_support/core_ext/array/conversions.rb +++ b/activesupport/lib/active_support/core_ext/array/conversions.rb @@ -157,7 +157,7 @@ class Array # def to_xml(options = {}) raise "Not all elements respond to to_xml" unless all? { |e| e.respond_to? :to_xml } - require 'builder' unless defined?(Builder) + require 'active_support/vendor/builder' unless defined?(Builder) options = options.dup options[:root] ||= all? { |e| e.is_a?(first.class) && first.class.to_s != "Hash" } ? ActiveSupport::Inflector.pluralize(ActiveSupport::Inflector.underscore(first.class.name)) : "records" diff --git a/activesupport/lib/active_support/core_ext/hash/conversions.rb b/activesupport/lib/active_support/core_ext/hash/conversions.rb index aa686ec2eb..ffe9e3d1b1 100644 --- a/activesupport/lib/active_support/core_ext/hash/conversions.rb +++ b/activesupport/lib/active_support/core_ext/hash/conversions.rb @@ -132,7 +132,7 @@ class Hash # configure your own builder with the <tt>:builder</tt> option. The method also accepts # options like <tt>:dasherize</tt> and friends, they are forwarded to the builder. def to_xml(options = {}) - require 'builder' unless defined?(Builder) + require 'active_support/vendor/builder' unless defined?(Builder) options = options.dup options[:indent] ||= 2 diff --git a/activesupport/lib/active_support/core_ext/rexml.rb b/activesupport/lib/active_support/core_ext/rexml.rb index decc4f6d9c..5288b639a6 100644 --- a/activesupport/lib/active_support/core_ext/rexml.rb +++ b/activesupport/lib/active_support/core_ext/rexml.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/kernel/reporting' + # Fixes the rexml vulnerability disclosed at: # http://www.ruby-lang.org/en/news/2008/08/23/dos-vulnerability-in-rexml/ # This fix is identical to rexml-expansion-fix version 1.0.1 @@ -5,11 +7,11 @@ require 'rexml/rexml' # Earlier versions of rexml defined REXML::Version, newer ones REXML::VERSION unless (defined?(REXML::VERSION) ? REXML::VERSION : REXML::Version) > "3.1.7.2" - require 'rexml/document' + silence_warnings { require 'rexml/document' } # REXML in 1.8.7 has the patch but early patchlevels didn't update Version from 3.1.7.2. unless REXML::Document.respond_to?(:entity_expansion_limit=) - require 'rexml/entity' + silence_warnings { require 'rexml/entity' } module REXML #:nodoc: class Entity < Child #:nodoc: diff --git a/activesupport/lib/active_support/core_ext/string/xchar.rb b/activesupport/lib/active_support/core_ext/string/xchar.rb index 7183218634..26857c8b0d 100644 --- a/activesupport/lib/active_support/core_ext/string/xchar.rb +++ b/activesupport/lib/active_support/core_ext/string/xchar.rb @@ -6,7 +6,7 @@ rescue LoadError # fast_xs extension unavailable else begin - require 'builder' + require 'active_support/vendor/builder' rescue LoadError # builder demands the first shot at defining String#to_xs end diff --git a/activesupport/lib/active_support/json/backends/jsongem.rb b/activesupport/lib/active_support/json/backends/jsongem.rb index 649e6301d1..c6c17a3c4e 100644 --- a/activesupport/lib/active_support/json/backends/jsongem.rb +++ b/activesupport/lib/active_support/json/backends/jsongem.rb @@ -2,10 +2,9 @@ require 'json' unless defined?(JSON) module ActiveSupport module JSON - ParseError = ::JSON::ParserError unless const_defined?(:ParseError) - module Backends module JSONGem + ParseError = ::JSON::ParserError extend self # Parses a JSON string or IO and convert it into an object @@ -38,4 +37,4 @@ module ActiveSupport end end end -end
\ No newline at end of file +end diff --git a/activesupport/lib/active_support/json/backends/yaml.rb b/activesupport/lib/active_support/json/backends/yaml.rb index 59d2c37e40..215b3d6f90 100644 --- a/activesupport/lib/active_support/json/backends/yaml.rb +++ b/activesupport/lib/active_support/json/backends/yaml.rb @@ -2,13 +2,9 @@ require 'active_support/core_ext/string/starts_ends_with' module ActiveSupport module JSON - unless const_defined?(:ParseError) - class ParseError < StandardError - end - end - module Backends module Yaml + ParseError = ::StandardError extend self # Parses a JSON string or IO and converts it into an object diff --git a/activesupport/lib/active_support/json/decoding.rb b/activesupport/lib/active_support/json/decoding.rb index 356b6cebeb..a5908365af 100644 --- a/activesupport/lib/active_support/json/decoding.rb +++ b/activesupport/lib/active_support/json/decoding.rb @@ -7,6 +7,7 @@ module ActiveSupport module JSON class << self + attr_reader :parse_error delegate :decode, :to => :backend def backend @@ -21,6 +22,7 @@ module ActiveSupport require "active_support/json/backends/#{name.to_s.downcase}.rb" @backend = ActiveSupport::JSON::Backends::const_get(name) end + @parse_error = @backend::ParseError end def with_backend(name) diff --git a/activesupport/lib/active_support/message_verifier.rb b/activesupport/lib/active_support/message_verifier.rb index b24acb9f47..0474b476df 100644 --- a/activesupport/lib/active_support/message_verifier.rb +++ b/activesupport/lib/active_support/message_verifier.rb @@ -25,10 +25,10 @@ module ActiveSupport def verify(signed_message) data, digest = signed_message.split("--") - if digest != generate_digest(data) - raise InvalidSignature - else + if secure_compare(digest, generate_digest(data)) Marshal.load(ActiveSupport::Base64.decode64(data)) + else + raise InvalidSignature end end @@ -38,6 +38,17 @@ module ActiveSupport end private + # constant-time comparison algorithm to prevent timing attacks + def secure_compare(a, b) + return false unless a.bytesize == b.bytesize + + l = a.unpack "C#{a.bytesize}" + + res = 0 + b.each_byte { |byte| res |= byte ^ l.shift } + res == 0 + end + def generate_digest(data) require 'openssl' unless defined?(OpenSSL) OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new(@digest), @secret, data) diff --git a/activesupport/lib/active_support/mini.rb b/activesupport/lib/active_support/mini.rb deleted file mode 100644 index b787650655..0000000000 --- a/activesupport/lib/active_support/mini.rb +++ /dev/null @@ -1,9 +0,0 @@ -$LOAD_PATH.unshift File.dirname(__FILE__) - -# whole object.rb pulls up rarely used introspection extensions -require "core_ext/object/blank" -require "core_ext/object/metaclass" -require 'core_ext/array' -require 'core_ext/hash' -require 'core_ext/module/attribute_accessors' -require 'core_ext/string/inflections' diff --git a/activesupport/lib/active_support/multibyte.rb b/activesupport/lib/active_support/multibyte.rb index d8d58f3bce..6f2016a409 100644 --- a/activesupport/lib/active_support/multibyte.rb +++ b/activesupport/lib/active_support/multibyte.rb @@ -1,9 +1,5 @@ # encoding: utf-8 -require 'active_support/multibyte/chars' -require 'active_support/multibyte/exceptions' -require 'active_support/multibyte/unicode_database' - require 'active_support/core_ext/module/attribute_accessors' module ActiveSupport #:nodoc: @@ -29,7 +25,35 @@ module ActiveSupport #:nodoc: # # Example: # ActiveSupport::Multibyte.proxy_class = CharsForUTF32 - mattr_accessor :proxy_class - self.proxy_class = ActiveSupport::Multibyte::Chars + def self.proxy_class=(klass) + @proxy_class = klass + end + + # Returns the currect proxy class + def self.proxy_class + @proxy_class ||= ActiveSupport::Multibyte::Chars + end + + # Regular expressions that describe valid byte sequences for a character + VALID_CHARACTER = { + # Borrowed from the Kconv library by Shinji KONO - (also as seen on the W3C site) + 'UTF-8' => /\A(?: + [\x00-\x7f] | + [\xc2-\xdf] [\x80-\xbf] | + \xe0 [\xa0-\xbf] [\x80-\xbf] | + [\xe1-\xef] [\x80-\xbf] [\x80-\xbf] | + \xf0 [\x90-\xbf] [\x80-\xbf] [\x80-\xbf] | + [\xf1-\xf3] [\x80-\xbf] [\x80-\xbf] [\x80-\xbf] | + \xf4 [\x80-\x8f] [\x80-\xbf] [\x80-\xbf])\z /xn, + # Quick check for valid Shift-JIS characters, disregards the odd-even pairing + 'Shift_JIS' => /\A(?: + [\x00-\x7e \xa1-\xdf] | + [\x81-\x9f \xe0-\xef] [\x40-\x7e \x80-\x9e \x9f-\xfc])\z /xn + } end end + +require 'active_support/multibyte/chars' +require 'active_support/multibyte/exceptions' +require 'active_support/multibyte/unicode_database' +require 'active_support/multibyte/utils' diff --git a/activesupport/lib/active_support/multibyte/chars.rb b/activesupport/lib/active_support/multibyte/chars.rb index 64a35dca40..579ccc124d 100644 --- a/activesupport/lib/active_support/multibyte/chars.rb +++ b/activesupport/lib/active_support/multibyte/chars.rb @@ -74,16 +74,7 @@ module ActiveSupport #:nodoc: UNICODE_TRAILERS_PAT = /(#{codepoints_to_pattern(UNICODE_LEADERS_AND_TRAILERS)})+\Z/ UNICODE_LEADERS_PAT = /\A(#{codepoints_to_pattern(UNICODE_LEADERS_AND_TRAILERS)})+/ - # Borrowed from the Kconv library by Shinji KONO - (also as seen on the W3C site) - UTF8_PAT = /\A(?: - [\x00-\x7f] | - [\xc2-\xdf] [\x80-\xbf] | - \xe0 [\xa0-\xbf] [\x80-\xbf] | - [\xe1-\xef] [\x80-\xbf] [\x80-\xbf] | - \xf0 [\x90-\xbf] [\x80-\xbf] [\x80-\xbf] | - [\xf1-\xf3] [\x80-\xbf] [\x80-\xbf] [\x80-\xbf] | - \xf4 [\x80-\x8f] [\x80-\xbf] [\x80-\xbf] - )*\z/xn + UTF8_PAT = ActiveSupport::Multibyte::VALID_CHARACTER['UTF-8'] attr_reader :wrapped_string alias to_s wrapped_string @@ -308,23 +299,23 @@ module ActiveSupport #:nodoc: def rstrip chars(@wrapped_string.gsub(UNICODE_TRAILERS_PAT, '')) end - + # Strips entire range of Unicode whitespace from the left of the string. def lstrip chars(@wrapped_string.gsub(UNICODE_LEADERS_PAT, '')) end - + # Strips entire range of Unicode whitespace from the right and left of the string. def strip rstrip.lstrip end - + # Returns the number of codepoints in the string def size self.class.u_unpack(@wrapped_string).size end alias_method :length, :size - + # Reverses all characters in the string. # # Example: @@ -332,7 +323,7 @@ module ActiveSupport #:nodoc: def reverse chars(self.class.u_unpack(@wrapped_string).reverse.pack('U*')) end - + # Implements Unicode-aware slice with codepoints. Slicing on one point returns the codepoints for that # character. # @@ -647,7 +638,7 @@ module ActiveSupport #:nodoc: string.split(//u).map do |c| c.force_encoding(Encoding::ASCII) if c.respond_to?(:force_encoding) - if !UTF8_PAT.match(c) + if !ActiveSupport::Multibyte::VALID_CHARACTER['UTF-8'].match(c) n = c.unpack('C')[0] n < 128 ? n.chr : n < 160 ? [UCD.cp1252[n] || n].pack('U') : diff --git a/activesupport/lib/active_support/multibyte/utils.rb b/activesupport/lib/active_support/multibyte/utils.rb new file mode 100644 index 0000000000..8e47763d39 --- /dev/null +++ b/activesupport/lib/active_support/multibyte/utils.rb @@ -0,0 +1,61 @@ +# encoding: utf-8 + +module ActiveSupport #:nodoc: + module Multibyte #:nodoc: + if Kernel.const_defined?(:Encoding) + # Returns a regular expression that matches valid characters in the current encoding + def self.valid_character + VALID_CHARACTER[Encoding.default_external.to_s] + end + else + def self.valid_character + case $KCODE + when 'UTF8' + VALID_CHARACTER['UTF-8'] + when 'SJIS' + VALID_CHARACTER['Shift_JIS'] + end + end + end + + if 'string'.respond_to?(:valid_encoding?) + # Verifies the encoding of a string + def self.verify(string) + string.valid_encoding? + end + else + def self.verify(string) + if expression = valid_character + for c in string.split(//) + return false unless expression.match(c) + end + end + true + end + end + + # Verifies the encoding of the string and raises an exception when it's not valid + def self.verify!(string) + raise EncodingError.new("Found characters with invalid encoding") unless verify(string) + end + + if 'string'.respond_to?(:force_encoding) + # Removes all invalid characters from the string. + # + # Note: this method is a no-op in Ruby 1.9 + def self.clean(string) + string + end + else + def self.clean(string) + if expression = valid_character + stripped = []; for c in string.split(//) + stripped << c if expression.match(c) + end; stripped.join + else + string + end + end + end + end +end diff --git a/activesupport/lib/active_support/new_callbacks.rb b/activesupport/lib/active_support/new_callbacks.rb index 56b510d52e..c56b9ad1ac 100644 --- a/activesupport/lib/active_support/new_callbacks.rb +++ b/activesupport/lib/active_support/new_callbacks.rb @@ -1,5 +1,6 @@ require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/class/inheritable_attributes' +require 'active_support/core_ext/kernel/reporting' module ActiveSupport # Callbacks are hooks into the lifecycle of an object that allow you to trigger logic @@ -15,17 +16,17 @@ module ActiveSupport # end # # class ConfigStorage < Storage - # save_callback :before, :saving_message + # set_callback :save, :before, :saving_message # def saving_message # puts "saving..." # end # - # save_callback :after do |object| + # set_callback :save, :after do |object| # puts "saved" # end # # def save - # _run_save_callbacks do + # _run_set_callback :save,s do # puts "- save" # end # end @@ -47,24 +48,24 @@ module ActiveSupport # # define_callbacks :save # - # save_callback :before, :prepare + # set_callback :save, :before, :prepare # def prepare # puts "preparing save" # end # end # # class ConfigStorage < Storage - # save_callback :before, :saving_message + # set_callback :save, :before, :saving_message # def saving_message # puts "saving..." # end # - # save_callback :after do |object| + # set_callback :save, :after do |object| # puts "saved" # end # # def save - # _run_save_callbacks do + # _run_set_callback :save,s do # puts "- save" # end # end @@ -78,22 +79,23 @@ module ActiveSupport # saving... # - save # saved + # module NewCallbacks def self.included(klass) klass.extend ClassMethods end - + def run_callbacks(kind, options = {}, &blk) send("_run_#{kind}_callbacks", &blk) end - + class Callback @@_callback_sequence = 0 - - attr_accessor :filter, :kind, :name, :options, :per_key, :klass - def initialize(filter, kind, options, klass) - @kind, @klass = kind, klass - + + attr_accessor :name, :filter, :kind, :options, :per_key, :klass + + def initialize(name, filter, kind, options, klass) + @name, @kind, @klass = name, kind, klass normalize_options!(options) @per_key = options.delete(:per_key) @@ -104,9 +106,10 @@ module ActiveSupport _compile_per_key_options end - + def clone(klass) obj = super() + obj.name = name obj.klass = klass obj.per_key = @per_key.dup obj.options = @options.dup @@ -114,36 +117,39 @@ module ActiveSupport obj.per_key[:unless] = @per_key[:unless].dup obj.options[:if] = @options[:if].dup obj.options[:unless] = @options[:unless].dup + obj.options[:scope] = @options[:scope].dup obj end - + def normalize_options!(options) options[:if] = Array.wrap(options[:if]) options[:unless] = Array.wrap(options[:unless]) + options[:scope] ||= [:kind] + options[:scope] = Array.wrap(options[:scope]) + options[:per_key] ||= {} options[:per_key][:if] = Array.wrap(options[:per_key][:if]) options[:per_key][:unless] = Array.wrap(options[:per_key][:unless]) end - + def next_id @@_callback_sequence += 1 end - + def matches?(_kind, _filter) - @kind == _kind && - @filter == _filter + @kind == _kind && @filter == _filter end def _update_filter(filter_options, new_options) filter_options[:if].push(new_options[:unless]) if new_options.key?(:unless) filter_options[:unless].push(new_options[:if]) if new_options.key?(:if) end - + def recompile!(_options, _per_key) _update_filter(self.options, _options) _update_filter(self.per_key, _per_key) - + @callback_id = next_id @filter = _compile_filter(@raw_filter) @compiled_options = _compile_options(@options) @@ -164,14 +170,13 @@ module ActiveSupport # contents for after filters (for the forward pass). def start(key = nil, options = {}) object, terminator = (options || {}).values_at(:object, :terminator) - return if key && !object.send("_one_time_conditions_valid_#{@callback_id}?") - + terminator ||= false - + # options[0] is the compiled form of supplied conditions # options[1] is the "end" for the conditional - + if @kind == :before || @kind == :around if @kind == :before # if condition # before_save :filter_name, :if => :condition @@ -183,7 +188,7 @@ module ActiveSupport halted = (#{terminator}) end RUBY_EVAL - + [@compiled_options[0], filter, @compiled_options[1]].compact.join("\n") else # Compile around filters with conditions into proxy methods @@ -200,7 +205,7 @@ module ActiveSupport # yield self # end # end - + # name = "_conditional_callback_#{@kind}_#{next_id}" txt, line = <<-RUBY_EVAL, __LINE__ + 1 def #{name}(halted) @@ -223,9 +228,8 @@ module ActiveSupport # before filters (for the backward pass). def end(key = nil, options = {}) object = (options || {})[:object] - return if key && !object.send("_one_time_conditions_valid_#{@callback_id}?") - + if @kind == :around || @kind == :after # if condition # after_save :filter_name, :if => :condition # filter_name @@ -237,28 +241,30 @@ module ActiveSupport end end end - + private + # Options support the same options as filters themselves (and support # symbols, string, procs, and objects), so compile a conditional # expression based on the options - def _compile_options(options) + def _compile_options(options) return [] if options[:if].empty? && options[:unless].empty? - + conditions = [] - + unless options[:if].empty? conditions << Array.wrap(_compile_filter(options[:if])) end - + unless options[:unless].empty? conditions << Array.wrap(_compile_filter(options[:unless])).map {|f| "!#{f}"} end - + ["if #{conditions.flatten.join(" && ")}", "end"] end - + # Filters support: + # # Arrays:: Used in conditions. This is used to specify # multiple conditions. Used internally to # merge conditions from skip_* filters @@ -269,6 +275,7 @@ module ActiveSupport # # All of these objects are compiled into methods and handled # the same after this point: + # # Arrays:: Merged together into a single filter # Symbols:: Already methods # Strings:: class_eval'ed into methods @@ -276,6 +283,7 @@ module ActiveSupport # Objects:: # a method is created that calls the before_foo method # on the object. + # def _compile_filter(filter) method_name = "_callback_#{@kind}_#{next_id}" case filter @@ -287,17 +295,18 @@ module ActiveSupport "(#{filter})" when Proc @klass.send(:define_method, method_name, &filter) - return method_name if filter.arity == 0 + return method_name if filter.arity <= 0 method_name << (filter.arity == 1 ? "(self)" : " self, Proc.new ") else @klass.send(:define_method, "#{method_name}_object") { filter } _normalize_legacy_filter(kind, filter) + method_to_call = @options[:scope].map{ |s| s.is_a?(Symbol) ? send(s) : s }.join("_") @klass.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 def #{method_name}(&blk) - #{method_name}_object.send(:#{kind}, self, &blk) + #{method_name}_object.send(:#{method_to_call}, self, &blk) end RUBY_EVAL @@ -318,59 +327,67 @@ module ActiveSupport end end end - end # An Array with a compile method class CallbackChain < Array - def initialize(symbol) + attr_reader :symbol, :config + + def initialize(symbol, config) @symbol = symbol + @config = config end - - def compile(key = nil, options = {}) + + def compile(key=nil, options={}) + options = config.merge(options) + method = [] + method << "value = nil" method << "halted = false" + each do |callback| method << callback.start(key, options) end - method << "yield self if block_given? && !halted" + + method << "value = yield if block_given? && !halted" + reverse_each do |callback| method << callback.end(key, options) end + + method << "halted ? false : (block_given? ? value : true)" method.compact.join("\n") end - + def clone(klass) - chain = CallbackChain.new(@symbol) + chain = CallbackChain.new(@symbol, @config.dup) chain.push(*map {|c| c.clone(klass)}) end end - + module ClassMethods - CHAINS = {:before => :before, :around => :before, :after => :after} - - # Make the _run_save_callbacks method. The generated method takes + # Make the _run_set_callback :save method. The generated method takes # a block that it'll yield to. It'll call the before and around filters # in order, yield the block, and then run the after filters. # - # _run_save_callbacks do + # _run_set_callback :save do # save # end # - # The _run_save_callbacks method can optionally take a key, which + # The _run_set_callback :save method can optionally take a key, which # will be used to compile an optimized callback method for each # key. See #define_callbacks for more information. - def _define_runner(symbol) - body = send("_#{symbol}_callbacks"). - compile(nil, :terminator => send("_#{symbol}_terminator")) + # + def __define_runner(symbol) #:nodoc: + body = send("_#{symbol}_callbacks").compile(nil) body, line = <<-RUBY_EVAL, __LINE__ def _run_#{symbol}_callbacks(key = nil, &blk) if key name = "_run__\#{self.class.name.hash.abs}__#{symbol}__\#{key.hash.abs}__callbacks" - + unless respond_to?(name) - self.class._create_keyed_callback(name, :#{symbol}, self, &blk) + self.class.__create_keyed_callback(name, :#{symbol}, self, &blk) end send(name, &blk) @@ -379,40 +396,46 @@ module ActiveSupport end end RUBY_EVAL - - undef_method "_run_#{symbol}_callbacks" if method_defined?("_run_#{symbol}_callbacks") - class_eval body, __FILE__, line + + silence_warnings do + undef_method "_run_#{symbol}_callbacks" if method_defined?("_run_#{symbol}_callbacks") + class_eval body, __FILE__, line + end end # This is called the first time a callback is called with a particular # key. It creates a new callback method for the key, calculating # which callbacks can be omitted because of per_key conditions. - def _create_keyed_callback(name, kind, obj, &blk) + # + def __create_keyed_callback(name, kind, obj, &blk) #:nodoc: @_keyed_callbacks ||= {} @_keyed_callbacks[name] ||= begin - str = send("_#{kind}_callbacks"). - compile(name, :object => obj, :terminator => send("_#{kind}_terminator")) - + str = send("_#{kind}_callbacks").compile(name, :object => obj) class_eval "def #{name}() #{str} end", __FILE__, __LINE__ - true end end - + + def __update_callbacks(name, filters = CallbackChain.new(name, {}), block = nil) + type = [:before, :after, :around].include?(filters.first) ? filters.shift : :before + options = filters.last.is_a?(Hash) ? filters.pop : {} + filters.unshift(block) if block + + callbacks = send("_#{name}_callbacks") + yield callbacks, type, filters, options if block_given? + + __define_runner(name) + end + # Define callbacks. # - # Creates a <name>_callback method that you can use to add callbacks. - # # Syntax: - # save_callback :before, :before_meth - # save_callback :after, :after_meth, :if => :condition - # save_callback :around {|r| stuff; yield; stuff } - # - # The <name>_callback method also updates the _run_<name>_callbacks - # method, which is the public API to run the callbacks. + # set_callback :save, :before, :before_meth + # set_callback :save, :after, :after_meth, :if => :condition + # set_callback :save, :around {|r| stuff; yield; stuff } # - # Also creates a skip_<name>_callback method that you can use to skip - # callbacks. + # It also updates the _run_<name>_callbacks method, which is the public + # API to run the callbacks. Use skip_callback to skip any defined one. # # When creating or skipping callbacks, you can specify conditions that # are always the same for a given key. For instance, in ActionPack, @@ -430,25 +453,12 @@ module ActiveSupport # In that case, each action_name would get its own compiled callback # method that took into consideration the per_key conditions. This # is a speed improvement for ActionPack. - def _update_callbacks(name, filters = CallbackChain.new(name), block = nil) - type = [:before, :after, :around].include?(filters.first) ? filters.shift : :before - options = filters.last.is_a?(Hash) ? filters.pop : {} - filters.unshift(block) if block - - callbacks = send("_#{name}_callbacks") - yield callbacks, type, filters, options if block_given? - - _define_runner(name) - end - - alias_method :_reset_callbacks, :_update_callbacks - + # def set_callback(name, *filters, &block) - _update_callbacks(name, filters, block) do |callbacks, type, filters, options| + __update_callbacks(name, filters, block) do |callbacks, type, filters, options| filters.map! do |filter| - # overrides parent class callbacks.delete_if {|c| c.matches?(type, filter) } - Callback.new(filter, type, options.dup, self) + Callback.new(name, filter, type, options.merge(callbacks.config), self) end options[:prepend] ? callbacks.unshift(*filters) : callbacks.push(*filters) @@ -456,10 +466,9 @@ module ActiveSupport end def skip_callback(name, *filters, &block) - _update_callbacks(name, filters, block) do |callbacks, type, filters, options| + __update_callbacks(name, filters, block) do |callbacks, type, filters, options| filters.each do |filter| callbacks = send("_#{name}_callbacks=", callbacks.clone(self)) - filter = callbacks.find {|c| c.matches?(type, filter) } if filter && options.any? @@ -471,16 +480,19 @@ module ActiveSupport end end + def reset_callbacks(symbol) + send("_#{symbol}_callbacks").clear + __define_runner(symbol) + end + def define_callbacks(*symbols) - terminator = symbols.pop if symbols.last.is_a?(String) + config = symbols.last.is_a?(Hash) ? symbols.pop : {} symbols.each do |symbol| - extlib_inheritable_accessor("_#{symbol}_terminator") { terminator } - extlib_inheritable_accessor("_#{symbol}_callbacks") do - CallbackChain.new(symbol) + CallbackChain.new(symbol, config) end - _define_runner(symbol) + __define_runner(symbol) end end end diff --git a/activesupport/lib/active_support/orchestra.rb b/activesupport/lib/active_support/orchestra.rb new file mode 100644 index 0000000000..efe30669d8 --- /dev/null +++ b/activesupport/lib/active_support/orchestra.rb @@ -0,0 +1,103 @@ +require 'thread' + +module ActiveSupport + # Orchestra provides an instrumentation API for Ruby. To instrument an action + # in Ruby you just need to: + # + # ActiveSupport::Orchestra.instrument(:render, :extra => :information) do + # render :text => "Foo" + # end + # + # Those actions are consumed by listeners. A listener is anything that responds + # to push. You can even register an array: + # + # @listener = [] + # ActiveSupport::Orchestra.register @listener + # + # ActiveSupport::Orchestra.instrument(:render, :extra => :information) do + # render :text => "Foo" + # end + # + # event #=> ActiveSupport::Orchestra::Event + # event.name #=> :render + # event.duration #=> 10 (in miliseconds) + # event.result #=> "Foo" + # event.payload #=> { :extra => :information } + # + # Orchestra ships with a default listener implementation which puts events in + # a stream and consume them in a Thread. This implementation is thread safe + # and is available at ActiveSupport::Orchestra::Listener. + # + module Orchestra + @stacked_events = Hash.new { |h,k| h[k] = [] } + @listeners = [] + + def self.instrument(name, payload=nil) + stack = @stacked_events[Thread.current.object_id] + event = Event.new(name, stack.last, payload) + stack << event + event.result = yield + event + ensure + event.finish! + stack.delete(event) + @listeners.each { |s| s.push(event) } + end + + def self.register(listener) + @listeners << listener + end + + def self.unregister(listener) + @listeners.delete(listener) + end + + class Event + attr_reader :name, :time, :duration, :parent, :thread_id, :payload + attr_accessor :result + + def initialize(name, parent=nil, payload=nil) + @name = name + @time = Time.now + @thread_id = Thread.current.object_id + @parent = parent + @payload = payload + end + + def finish! + @duration = 1000 * (Time.now.to_f - @time.to_f) + end + end + + class Listener + attr_reader :mutex, :signaler, :thread + + def initialize + @mutex, @signaler = Mutex.new, ConditionVariable.new + @stream = [] + @thread = Thread.new do + loop do + (event = @stream.shift) ? consume(event) : wait + end + end + end + + def wait + @mutex.synchronize do + @signaler.wait(@mutex) + end + end + + def push(event) + @mutex.synchronize do + @stream.push(event) + @signaler.broadcast + end + end + + def consume(event) + raise NotImplementedError + end + end + end +end diff --git a/activesupport/lib/active_support/test_case.rb b/activesupport/lib/active_support/test_case.rb index c915bf799d..1646891e00 100644 --- a/activesupport/lib/active_support/test_case.rb +++ b/activesupport/lib/active_support/test_case.rb @@ -7,7 +7,6 @@ require 'active_support/testing/pending' require 'active_support/testing/isolation' begin - gem 'mocha', ">= 0.9.7" require 'mocha' rescue LoadError # Fake Mocha::ExpectationError so we can rescue it in #run. Bleh. diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index f8d12e82b3..ab34f975f6 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -1,5 +1,3 @@ -require 'rubygems' -gem 'ruby-prof', '>= 0.6.1' require 'ruby-prof' require 'fileutils' diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb index 564528bfe2..4eb268ac7d 100644 --- a/activesupport/lib/active_support/values/time_zone.rb +++ b/activesupport/lib/active_support/values/time_zone.rb @@ -306,7 +306,7 @@ module ActiveSupport # TODO: Preload instead of lazy load for thread safety def tzinfo - require 'tzinfo' unless defined?(TZInfo) + require 'active_support/vendor/tzinfo' unless defined?(TZInfo) @tzinfo ||= TZInfo::Timezone.get(MAPPING[name]) end diff --git a/activesupport/lib/active_support/vendor.rb b/activesupport/lib/active_support/vendor.rb index ca64c5ebe3..10dbfd9a77 100644 --- a/activesupport/lib/active_support/vendor.rb +++ b/activesupport/lib/active_support/vendor.rb @@ -1,27 +1,23 @@ -# Prefer gems to the bundled libs. -require 'rubygems' +# Fakes out gem optional dependencies until they are fully supported by gemspec. +# Activate any optional dependencies that are available. +if defined? Gem + begin + gem 'builder', '~> 2.1.2' + rescue Gem::LoadError + end -begin - gem 'builder', '~> 2.1.2' -rescue Gem::LoadError - $:.unshift "#{File.dirname(__FILE__)}/vendor/builder-2.1.2" -end - -begin - gem 'memcache-client', '>= 1.6.5' -rescue Gem::LoadError - $:.unshift "#{File.dirname(__FILE__)}/vendor/memcache-client-1.6.5" -end + begin + gem 'memcache-client', '>= 1.6.5' + rescue Gem::LoadError + end -begin - gem 'tzinfo', '~> 0.3.13' -rescue Gem::LoadError - $:.unshift "#{File.dirname(__FILE__)}/vendor/tzinfo-0.3.13" -end + begin + gem 'tzinfo', '~> 0.3.13' + rescue Gem::LoadError + end -begin - gem 'i18n', '~> 0.1.3' -rescue Gem::LoadError - $:.unshift "#{File.dirname(__FILE__)}/vendor/i18n-0.1.3/lib" - require 'i18n' + begin + gem 'i18n', '~> 0.1.3' + rescue Gem::LoadError + end end diff --git a/activesupport/lib/active_support/vendor/builder-2.1.2/blankslate.rb b/activesupport/lib/active_support/vendor/builder-2.1.2/lib/blankslate.rb index da6034d9c4..da6034d9c4 100644 --- a/activesupport/lib/active_support/vendor/builder-2.1.2/blankslate.rb +++ b/activesupport/lib/active_support/vendor/builder-2.1.2/lib/blankslate.rb diff --git a/activesupport/lib/active_support/vendor/builder-2.1.2/builder.rb b/activesupport/lib/active_support/vendor/builder-2.1.2/lib/builder.rb index 9719277669..9719277669 100644 --- a/activesupport/lib/active_support/vendor/builder-2.1.2/builder.rb +++ b/activesupport/lib/active_support/vendor/builder-2.1.2/lib/builder.rb diff --git a/activesupport/lib/active_support/vendor/builder-2.1.2/builder/blankslate.rb b/activesupport/lib/active_support/vendor/builder-2.1.2/lib/builder/blankslate.rb index 2935b6f1d1..2935b6f1d1 100644 --- a/activesupport/lib/active_support/vendor/builder-2.1.2/builder/blankslate.rb +++ b/activesupport/lib/active_support/vendor/builder-2.1.2/lib/builder/blankslate.rb diff --git a/activesupport/lib/active_support/vendor/builder-2.1.2/builder/css.rb b/activesupport/lib/active_support/vendor/builder-2.1.2/lib/builder/css.rb index e086a1b132..e086a1b132 100644 --- a/activesupport/lib/active_support/vendor/builder-2.1.2/builder/css.rb +++ b/activesupport/lib/active_support/vendor/builder-2.1.2/lib/builder/css.rb diff --git a/activesupport/lib/active_support/vendor/builder-2.1.2/builder/xchar.rb b/activesupport/lib/active_support/vendor/builder-2.1.2/lib/builder/xchar.rb index 8bdbd05899..8bdbd05899 100644 --- a/activesupport/lib/active_support/vendor/builder-2.1.2/builder/xchar.rb +++ b/activesupport/lib/active_support/vendor/builder-2.1.2/lib/builder/xchar.rb diff --git a/activesupport/lib/active_support/vendor/builder-2.1.2/builder/xmlbase.rb b/activesupport/lib/active_support/vendor/builder-2.1.2/lib/builder/xmlbase.rb index ace4b56d59..ace4b56d59 100644 --- a/activesupport/lib/active_support/vendor/builder-2.1.2/builder/xmlbase.rb +++ b/activesupport/lib/active_support/vendor/builder-2.1.2/lib/builder/xmlbase.rb diff --git a/activesupport/lib/active_support/vendor/builder-2.1.2/builder/xmlevents.rb b/activesupport/lib/active_support/vendor/builder-2.1.2/lib/builder/xmlevents.rb index b373e4da3c..b373e4da3c 100644 --- a/activesupport/lib/active_support/vendor/builder-2.1.2/builder/xmlevents.rb +++ b/activesupport/lib/active_support/vendor/builder-2.1.2/lib/builder/xmlevents.rb diff --git a/activesupport/lib/active_support/vendor/builder-2.1.2/builder/xmlmarkup.rb b/activesupport/lib/active_support/vendor/builder-2.1.2/lib/builder/xmlmarkup.rb index ec59dddc36..ec59dddc36 100644 --- a/activesupport/lib/active_support/vendor/builder-2.1.2/builder/xmlmarkup.rb +++ b/activesupport/lib/active_support/vendor/builder-2.1.2/lib/builder/xmlmarkup.rb diff --git a/activesupport/lib/active_support/vendor/builder.rb b/activesupport/lib/active_support/vendor/builder.rb new file mode 100644 index 0000000000..ad89e6635d --- /dev/null +++ b/activesupport/lib/active_support/vendor/builder.rb @@ -0,0 +1,6 @@ +begin + require 'builder' +rescue LoadError + $:.unshift File.expand_path(File.join(File.dirname(__FILE__), 'builder-2.1.2', 'lib')) + retry +end diff --git a/activesupport/lib/active_support/vendor/i18n.rb b/activesupport/lib/active_support/vendor/i18n.rb new file mode 100644 index 0000000000..6011253035 --- /dev/null +++ b/activesupport/lib/active_support/vendor/i18n.rb @@ -0,0 +1,6 @@ +begin + require 'i18n' +rescue LoadError + $:.unshift File.expand_path(File.join(File.dirname(__FILE__), 'i18n-0.1.3', 'lib')) + retry +end diff --git a/activesupport/lib/active_support/vendor/memcache-client-1.6.5/memcache.rb b/activesupport/lib/active_support/vendor/memcache-client-1.7.5/lib/memcache.rb index 4d594c2089..3fcc388ba0 100644 --- a/activesupport/lib/active_support/vendor/memcache-client-1.6.5/memcache.rb +++ b/activesupport/lib/active_support/vendor/memcache-client-1.7.5/lib/memcache.rb @@ -2,9 +2,9 @@ $TESTING = defined?($TESTING) && $TESTING require 'socket' require 'thread' -require 'timeout' require 'zlib' require 'digest/sha1' +require 'net/protocol' ## # A Ruby client library for memcached. @@ -15,18 +15,22 @@ class MemCache ## # The version of MemCache you are using. - VERSION = '1.6.4.99' + VERSION = '1.7.5' ## # Default options for the cache object. DEFAULT_OPTIONS = { - :namespace => nil, - :readonly => false, - :multithread => true, - :failover => true, - :timeout => 0.5, - :logger => nil, + :namespace => nil, + :readonly => false, + :multithread => true, + :failover => true, + :timeout => 0.5, + :logger => nil, + :no_reply => false, + :check_size => true, + :autofix_keys => false, + :namespace_separator => ':', } ## @@ -50,6 +54,19 @@ class MemCache attr_reader :multithread ## + # Whether to try to fix keys that are too long and will be truncated by + # using their SHA1 hash instead. + # The hash is only used on keys longer than 250 characters, or containing spaces, + # to avoid impacting performance unnecesarily. + # + # In theory, your code should generate correct keys when calling memcache, + # so it's your responsibility and you should try to fix this problem at its source. + # + # But if that's not possible, enable this option and memcache-client will give you a hand. + + attr_reader :autofix_keys + + ## # The servers this client talks to. Play at your own peril. attr_reader :servers @@ -72,19 +89,32 @@ class MemCache attr_reader :logger ## + # Don't send or look for a reply from the memcached server for write operations. + # Please note this feature only works in memcached 1.2.5 and later. Earlier + # versions will reply with "ERROR". + attr_reader :no_reply + + ## # Accepts a list of +servers+ and a list of +opts+. +servers+ may be # omitted. See +servers=+ for acceptable server list arguments. # # Valid options for +opts+ are: # - # [:namespace] Prepends this value to all keys added or retrieved. - # [:readonly] Raises an exception on cache writes when true. - # [:multithread] Wraps cache access in a Mutex for thread safety. - # [:failover] Should the client try to failover to another server if the - # first server is down? Defaults to true. - # [:timeout] Time to use as the socket read timeout. Defaults to 0.5 sec, - # set to nil to disable timeouts (this is a major performance penalty in Ruby 1.8). - # [:logger] Logger to use for info/debug output, defaults to nil + # [:namespace] Prepends this value to all keys added or retrieved. + # [:readonly] Raises an exception on cache writes when true. + # [:multithread] Wraps cache access in a Mutex for thread safety. Defaults to true. + # [:failover] Should the client try to failover to another server if the + # first server is down? Defaults to true. + # [:timeout] Time to use as the socket read timeout. Defaults to 0.5 sec, + # set to nil to disable timeouts. + # [:logger] Logger to use for info/debug output, defaults to nil + # [:no_reply] Don't bother looking for a reply for write operations (i.e. they + # become 'fire and forget'), memcached 1.2.5 and later only, speeds up + # set/add/delete/incr/decr significantly. + # [:check_size] Raises a MemCacheError if the value to be set is greater than 1 MB, which + # is the maximum key size for the standard memcached server. Defaults to true. + # [:autofix_keys] If a key is longer than 250 characters or contains spaces, + # use an SHA1 hash instead, to prevent collisions on truncated keys. # Other options are ignored. def initialize(*args) @@ -108,13 +138,17 @@ class MemCache end opts = DEFAULT_OPTIONS.merge opts - @namespace = opts[:namespace] - @readonly = opts[:readonly] - @multithread = opts[:multithread] - @timeout = opts[:timeout] - @failover = opts[:failover] - @logger = opts[:logger] - @mutex = Mutex.new if @multithread + @namespace = opts[:namespace] + @readonly = opts[:readonly] + @multithread = opts[:multithread] + @autofix_keys = opts[:autofix_keys] + @timeout = opts[:timeout] + @failover = opts[:failover] + @logger = opts[:logger] + @no_reply = opts[:no_reply] + @check_size = opts[:check_size] + @namespace_separator = opts[:namespace_separator] + @mutex = Mutex.new if @multithread logger.info { "memcache-client #{VERSION} #{Array(servers).inspect}" } if logger @@ -192,8 +226,8 @@ class MemCache def get(key, raw = false) with_server(key) do |server, cache_key| + logger.debug { "get #{key} from #{server.inspect}" } if logger value = cache_get server, cache_key - logger.debug { "GET #{key} from #{server.inspect}: #{value ? value.to_s.size : 'nil'}" } if logger return nil if value.nil? value = Marshal.load value unless raw return value @@ -203,6 +237,25 @@ class MemCache end ## + # Performs a +get+ with the given +key+. If + # the value does not exist and a block was given, + # the block will be called and the result saved via +add+. + # + # If you do not provide a block, using this + # method is the same as using +get+. + # + def fetch(key, expiry = 0, raw = false) + value = get(key, raw) + + if value.nil? && block_given? + value = yield + add(key, value, expiry, raw) + end + + value + end + + ## # Retrieves multiple values from memcached in parallel, if possible. # # The memcached protocol supports the ability to retrieve multiple @@ -280,18 +333,64 @@ class MemCache def set(key, value, expiry = 0, raw = false) raise MemCacheError, "Update of readonly cache" if @readonly + + value = Marshal.dump value unless raw with_server(key) do |server, cache_key| + logger.debug { "set #{key} to #{server.inspect}: #{value.to_s.size}" } if logger - value = Marshal.dump value unless raw - logger.debug { "SET #{key} to #{server.inspect}: #{value ? value.to_s.size : 'nil'}" } if logger + if @check_size && value.to_s.size > ONE_MB + raise MemCacheError, "Value too large, memcached can only store 1MB of data per key" + end - data = value.to_s - raise MemCacheError, "Value too large, memcached can only store 1MB of data per key" if data.size > ONE_MB + command = "set #{cache_key} 0 #{expiry} #{value.to_s.size}#{noreply}\r\n#{value}\r\n" - command = "set #{cache_key} 0 #{expiry} #{data.size}\r\n#{data}\r\n" + with_socket_management(server) do |socket| + socket.write command + break nil if @no_reply + result = socket.gets + raise_on_error_response! result + + if result.nil? + server.close + raise MemCacheError, "lost connection to #{server.host}:#{server.port}" + end + + result + end + end + end + + ## + # "cas" is a check and set operation which means "store this data but + # only if no one else has updated since I last fetched it." This can + # be used as a form of optimistic locking. + # + # Works in block form like so: + # cache.cas('some-key') do |value| + # value + 1 + # end + # + # Returns: + # +nil+ if the value was not found on the memcached server. + # +STORED+ if the value was updated successfully + # +EXISTS+ if the value was updated by someone else since last fetch + + def cas(key, expiry=0, raw=false) + raise MemCacheError, "Update of readonly cache" if @readonly + raise MemCacheError, "A block is required" unless block_given? + + (value, token) = gets(key, raw) + return nil unless value + updated = yield value + value = Marshal.dump updated unless raw + + with_server(key) do |server, cache_key| + logger.debug { "cas #{key} to #{server.inspect}: #{value.to_s.size}" } if logger + command = "cas #{cache_key} 0 #{expiry} #{value.to_s.size} #{token}#{noreply}\r\n#{value}\r\n" with_socket_management(server) do |socket| socket.write command + break nil if @no_reply result = socket.gets raise_on_error_response! result @@ -311,17 +410,79 @@ class MemCache # If +raw+ is true, +value+ will not be Marshalled. # # Readers should call this method in the event of a cache miss, not - # MemCache#set or MemCache#[]=. + # MemCache#set. def add(key, value, expiry = 0, raw = false) raise MemCacheError, "Update of readonly cache" if @readonly + value = Marshal.dump value unless raw + with_server(key) do |server, cache_key| + logger.debug { "add #{key} to #{server}: #{value ? value.to_s.size : 'nil'}" } if logger + command = "add #{cache_key} 0 #{expiry} #{value.to_s.size}#{noreply}\r\n#{value}\r\n" + + with_socket_management(server) do |socket| + socket.write command + break nil if @no_reply + result = socket.gets + raise_on_error_response! result + result + end + end + end + + ## + # Add +key+ to the cache with value +value+ that expires in +expiry+ + # seconds, but only if +key+ already exists in the cache. + # If +raw+ is true, +value+ will not be Marshalled. + def replace(key, value, expiry = 0, raw = false) + raise MemCacheError, "Update of readonly cache" if @readonly + value = Marshal.dump value unless raw + with_server(key) do |server, cache_key| + logger.debug { "replace #{key} to #{server}: #{value ? value.to_s.size : 'nil'}" } if logger + command = "replace #{cache_key} 0 #{expiry} #{value.to_s.size}#{noreply}\r\n#{value}\r\n" + + with_socket_management(server) do |socket| + socket.write command + break nil if @no_reply + result = socket.gets + raise_on_error_response! result + result + end + end + end + + ## + # Append - 'add this data to an existing key after existing data' + # Please note the value is always passed to memcached as raw since it + # doesn't make a lot of sense to concatenate marshalled data together. + def append(key, value) + raise MemCacheError, "Update of readonly cache" if @readonly with_server(key) do |server, cache_key| - value = Marshal.dump value unless raw - logger.debug { "ADD #{key} to #{server}: #{value ? value.to_s.size : 'nil'}" } if logger - command = "add #{cache_key} 0 #{expiry} #{value.to_s.size}\r\n#{value}\r\n" + logger.debug { "append #{key} to #{server}: #{value ? value.to_s.size : 'nil'}" } if logger + command = "append #{cache_key} 0 0 #{value.to_s.size}#{noreply}\r\n#{value}\r\n" with_socket_management(server) do |socket| socket.write command + break nil if @no_reply + result = socket.gets + raise_on_error_response! result + result + end + end + end + + ## + # Prepend - 'add this data to an existing key before existing data' + # Please note the value is always passed to memcached as raw since it + # doesn't make a lot of sense to concatenate marshalled data together. + def prepend(key, value) + raise MemCacheError, "Update of readonly cache" if @readonly + with_server(key) do |server, cache_key| + logger.debug { "prepend #{key} to #{server}: #{value ? value.to_s.size : 'nil'}" } if logger + command = "prepend #{cache_key} 0 0 #{value.to_s.size}#{noreply}\r\n#{value}\r\n" + + with_socket_management(server) do |socket| + socket.write command + break nil if @no_reply result = socket.gets raise_on_error_response! result result @@ -336,7 +497,9 @@ class MemCache raise MemCacheError, "Update of readonly cache" if @readonly with_server(key) do |server, cache_key| with_socket_management(server) do |socket| - socket.write "delete #{cache_key} #{expiry}\r\n" + logger.debug { "delete #{cache_key} on #{server}" } if logger + socket.write "delete #{cache_key} #{expiry}#{noreply}\r\n" + break nil if @no_reply result = socket.gets raise_on_error_response! result result @@ -346,19 +509,33 @@ class MemCache ## # Flush the cache from all memcache servers. - - def flush_all + # A non-zero value for +delay+ will ensure that the flush + # is propogated slowly through your memcached server farm. + # The Nth server will be flushed N*delay seconds from now, + # asynchronously so this method returns quickly. + # This prevents a huge database spike due to a total + # flush all at once. + + def flush_all(delay=0) raise MemCacheError, 'No active servers' unless active? raise MemCacheError, "Update of readonly cache" if @readonly begin + delay_time = 0 @servers.each do |server| with_socket_management(server) do |socket| - socket.write "flush_all\r\n" + logger.debug { "flush_all #{delay_time} on #{server}" } if logger + if delay == 0 # older versions of memcached will fail silently otherwise + socket.write "flush_all#{noreply}\r\n" + else + socket.write "flush_all #{delay_time}#{noreply}\r\n" + end + break nil if @no_reply result = socket.gets raise_on_error_response! result result end + delay_time += delay end rescue IndexError => err handle_error nil, err @@ -466,10 +643,14 @@ class MemCache # requested. def make_cache_key(key) + if @autofix_keys and (key =~ /\s/ or (key.length + (namespace.nil? ? 0 : namespace.length)) > 250) + key = "#{Digest::SHA1.hexdigest(key)}-autofixed" + end + if namespace.nil? then key else - "#{@namespace}:#{key}" + "#{@namespace}#{@namespace_separator}#{key}" end end @@ -500,7 +681,7 @@ class MemCache break unless failover hkey = hash_for "#{try}#{key}" end - + raise MemCacheError, "No servers available" end @@ -510,7 +691,8 @@ class MemCache def cache_decr(server, cache_key, amount) with_socket_management(server) do |socket| - socket.write "decr #{cache_key} #{amount}\r\n" + socket.write "decr #{cache_key} #{amount}#{noreply}\r\n" + break nil if @no_reply text = socket.gets raise_on_error_response! text return nil if text == "NOT_FOUND\r\n" @@ -546,6 +728,38 @@ class MemCache end end + def gets(key, raw = false) + with_server(key) do |server, cache_key| + logger.debug { "gets #{key} from #{server.inspect}" } if logger + result = with_socket_management(server) do |socket| + socket.write "gets #{cache_key}\r\n" + keyline = socket.gets # "VALUE <key> <flags> <bytes> <cas token>\r\n" + + if keyline.nil? then + server.close + raise MemCacheError, "lost connection to #{server.host}:#{server.port}" + end + + raise_on_error_response! keyline + return nil if keyline == "END\r\n" + + unless keyline =~ /(\d+) (\w+)\r/ then + server.close + raise MemCacheError, "unexpected response #{keyline.inspect}" + end + value = socket.read $1.to_i + socket.read 2 # "\r\n" + socket.gets # "END\r\n" + [value, $2] + end + result[0] = Marshal.load result[0] unless raw + result + end + rescue TypeError => err + handle_error nil, err + end + + ## # Fetches +cache_keys+ from +server+ using a multi-get. @@ -579,7 +793,8 @@ class MemCache def cache_incr(server, cache_key, amount) with_socket_management(server) do |socket| - socket.write "incr #{cache_key} #{amount}\r\n" + socket.write "incr #{cache_key} #{amount}#{noreply}\r\n" + break nil if @no_reply text = socket.gets raise_on_error_response! text return nil if text == "NOT_FOUND\r\n" @@ -617,7 +832,7 @@ class MemCache block.call(socket) - rescue SocketError => err + rescue SocketError, Errno::EAGAIN, Timeout::Error => err logger.warn { "Socket failure: #{err.message}" } if logger server.mark_dead(err) handle_error(server, err) @@ -659,6 +874,10 @@ class MemCache raise new_error end + def noreply + @no_reply ? ' noreply' : '' + end + ## # Performs setup for making a request with +key+ from memcached. Returns # the server to fetch the key from and the complete key to use. @@ -713,13 +932,6 @@ class MemCache class Server ## - # The amount of time to wait to establish a connection with a memcached - # server. If a connection cannot be established within this time limit, - # the server will be marked as down. - - CONNECT_TIMEOUT = 0.25 - - ## # The amount of time to wait before attempting to re-establish a # connection with a server that is marked dead. @@ -802,14 +1014,11 @@ class MemCache # Attempt to connect if not already connected. begin - @sock = @timeout ? TCPTimeoutSocket.new(@host, @port, @timeout) : TCPSocket.new(@host, @port) - - if Socket.constants.include? 'TCP_NODELAY' then - @sock.setsockopt Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 - end + @sock = connect_to(@host, @port, @timeout) + @sock.setsockopt Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 @retry = nil @status = 'CONNECTED' - rescue SocketError, SystemCallError, IOError, Timeout::Error => err + rescue SocketError, SystemCallError, IOError => err logger.warn { "Unable to open socket: #{err.class.name}, #{err.message}" } if logger mark_dead err end @@ -817,6 +1026,12 @@ class MemCache return @sock end + def connect_to(host, port, timeout=nil) + io = MemCache::BufferedIO.new(TCPSocket.new(host, port)) + io.read_timeout = timeout + io + end + ## # Close the connection to the memcached server targeted by this # object. The server is not considered dead. @@ -848,51 +1063,33 @@ class MemCache class MemCacheError < RuntimeError; end -end - -# TCPSocket facade class which implements timeouts. -class TCPTimeoutSocket - - def initialize(host, port, timeout) - Timeout::timeout(MemCache::Server::CONNECT_TIMEOUT, SocketError) do - @sock = TCPSocket.new(host, port) - @len = timeout - end - end - - def write(*args) - Timeout::timeout(@len, SocketError) do - @sock.write(*args) + class BufferedIO < Net::BufferedIO # :nodoc: + BUFSIZE = 1024 * 16 + + if RUBY_VERSION < '1.9.1' + def rbuf_fill + begin + @rbuf << @io.read_nonblock(BUFSIZE) + rescue Errno::EWOULDBLOCK + retry unless @read_timeout + if IO.select([@io], nil, nil, @read_timeout) + retry + else + raise Timeout::Error, 'IO timeout' + end + end + end end - end - def gets(*args) - Timeout::timeout(@len, SocketError) do - @sock.gets(*args) + def setsockopt(*args) + @io.setsockopt(*args) end - end - def read(*args) - Timeout::timeout(@len, SocketError) do - @sock.read(*args) + def gets + readuntil("\n") end end - def _socket - @sock - end - - def method_missing(meth, *args) - @sock.__send__(meth, *args) - end - - def closed? - @sock.closed? - end - - def close - @sock.close - end end module Continuum @@ -932,4 +1129,5 @@ module Continuum "<#{value}, #{server.host}:#{server.port}>" end end + end diff --git a/activesupport/lib/active_support/vendor/memcache.rb b/activesupport/lib/active_support/vendor/memcache.rb new file mode 100644 index 0000000000..442f50a817 --- /dev/null +++ b/activesupport/lib/active_support/vendor/memcache.rb @@ -0,0 +1,6 @@ +begin + require 'memcache' +rescue LoadError + $:.unshift File.expand_path(File.join(File.dirname(__FILE__), 'memcache-client-1.7.5', 'lib')) + retry +end diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo.rb index c8bdbeec5d..c8bdbeec5d 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/data_timezone.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/data_timezone.rb index 5eccbdf0db..5eccbdf0db 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/data_timezone.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/data_timezone.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/data_timezone_info.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/data_timezone_info.rb index a45d94554b..a45d94554b 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/data_timezone_info.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/data_timezone_info.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Africa/Algiers.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Algiers.rb index 8c5f25577f..8c5f25577f 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Africa/Algiers.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Algiers.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Africa/Cairo.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Cairo.rb index 6e6daf3522..6e6daf3522 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Africa/Cairo.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Cairo.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Africa/Casablanca.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Casablanca.rb index 18d73c93a0..18d73c93a0 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Africa/Casablanca.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Casablanca.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Africa/Harare.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Harare.rb index 070c95ae0f..070c95ae0f 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Africa/Harare.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Harare.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Africa/Johannesburg.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Johannesburg.rb index f0af0d8e33..f0af0d8e33 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Africa/Johannesburg.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Johannesburg.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Africa/Monrovia.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Monrovia.rb index 40e711fa44..40e711fa44 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Africa/Monrovia.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Monrovia.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Africa/Nairobi.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Nairobi.rb index 7b0a2f43be..7b0a2f43be 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Africa/Nairobi.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Africa/Nairobi.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Argentina/Buenos_Aires.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Argentina/Buenos_Aires.rb index 8f4dd31dbb..8f4dd31dbb 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Argentina/Buenos_Aires.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Argentina/Buenos_Aires.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Argentina/San_Juan.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Argentina/San_Juan.rb index ba8be4705f..ba8be4705f 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Argentina/San_Juan.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Argentina/San_Juan.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Bogota.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Bogota.rb index ef96435c6a..ef96435c6a 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Bogota.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Bogota.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Caracas.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Caracas.rb index 27392a540a..27392a540a 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Caracas.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Caracas.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Chicago.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Chicago.rb index 0996857cf0..0996857cf0 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Chicago.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Chicago.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Chihuahua.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Chihuahua.rb index 1710b57c79..1710b57c79 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Chihuahua.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Chihuahua.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Denver.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Denver.rb index 1c1efb5ff3..1c1efb5ff3 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Denver.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Denver.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Godthab.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Godthab.rb index 1e05518b0d..1e05518b0d 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Godthab.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Godthab.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Guatemala.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Guatemala.rb index a2bf73401c..a2bf73401c 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Guatemala.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Guatemala.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Halifax.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Halifax.rb index d25ae775b3..d25ae775b3 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Halifax.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Halifax.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Indiana/Indianapolis.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Indiana/Indianapolis.rb index f1430f6c24..f1430f6c24 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Indiana/Indianapolis.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Indiana/Indianapolis.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Juneau.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Juneau.rb index f646f3f54a..f646f3f54a 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Juneau.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Juneau.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/La_Paz.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/La_Paz.rb index 45c907899f..45c907899f 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/La_Paz.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/La_Paz.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Lima.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Lima.rb index af68ac29f7..af68ac29f7 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Lima.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Lima.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Los_Angeles.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Los_Angeles.rb index 16007fd675..16007fd675 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Los_Angeles.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Los_Angeles.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Mazatlan.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Mazatlan.rb index ba9e6efcf1..ba9e6efcf1 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Mazatlan.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Mazatlan.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Mexico_City.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Mexico_City.rb index 2347fce647..2347fce647 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Mexico_City.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Mexico_City.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Monterrey.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Monterrey.rb index 5816a9eab1..5816a9eab1 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Monterrey.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Monterrey.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/New_York.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/New_York.rb index 7d802bd2de..7d802bd2de 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/New_York.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/New_York.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Phoenix.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Phoenix.rb index b514e0c0f9..b514e0c0f9 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Phoenix.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Phoenix.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Regina.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Regina.rb index ebdb68814a..ebdb68814a 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Regina.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Regina.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Santiago.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Santiago.rb index 0287c9ebc4..0287c9ebc4 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Santiago.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Santiago.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Sao_Paulo.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Sao_Paulo.rb index 0524f81c04..0524f81c04 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Sao_Paulo.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Sao_Paulo.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/St_Johns.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/St_Johns.rb index e4a3599d35..e4a3599d35 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/St_Johns.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/St_Johns.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Tijuana.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Tijuana.rb index 423059da46..423059da46 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/America/Tijuana.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/America/Tijuana.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Almaty.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Almaty.rb index 9ee18970f1..9ee18970f1 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Almaty.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Almaty.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Baghdad.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Baghdad.rb index 774dca1587..774dca1587 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Baghdad.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Baghdad.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Baku.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Baku.rb index e86340ebfa..e86340ebfa 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Baku.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Baku.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Bangkok.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Bangkok.rb index 139194e5e5..139194e5e5 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Bangkok.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Bangkok.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Chongqing.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Chongqing.rb index 8c94b4ba86..8c94b4ba86 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Chongqing.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Chongqing.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Colombo.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Colombo.rb index f6531fa819..f6531fa819 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Colombo.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Colombo.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Dhaka.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Dhaka.rb index ccd0265503..ccd0265503 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Dhaka.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Dhaka.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Hong_Kong.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Hong_Kong.rb index f1edd75ac8..f1edd75ac8 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Hong_Kong.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Hong_Kong.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Irkutsk.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Irkutsk.rb index 2d47d9580b..2d47d9580b 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Irkutsk.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Irkutsk.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Jakarta.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Jakarta.rb index cc58fa173b..cc58fa173b 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Jakarta.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Jakarta.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Jerusalem.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Jerusalem.rb index 9b737b899e..9b737b899e 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Jerusalem.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Jerusalem.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Kabul.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kabul.rb index 669c09790a..669c09790a 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Kabul.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kabul.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Kamchatka.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kamchatka.rb index 2f1690b3a9..2f1690b3a9 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Kamchatka.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kamchatka.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Karachi.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Karachi.rb index 4f187b4ad4..4f187b4ad4 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Karachi.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Karachi.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Kathmandu.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kathmandu.rb index 37b241612e..37b241612e 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Kathmandu.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kathmandu.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Kolkata.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kolkata.rb index 1b6ffbd59d..1b6ffbd59d 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Kolkata.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kolkata.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Krasnoyarsk.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Krasnoyarsk.rb index d6c503c155..d6c503c155 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Krasnoyarsk.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Krasnoyarsk.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Kuala_Lumpur.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kuala_Lumpur.rb index 77a0c206fa..77a0c206fa 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Kuala_Lumpur.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kuala_Lumpur.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Kuwait.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kuwait.rb index 5bd5283197..5bd5283197 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Kuwait.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Kuwait.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Magadan.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Magadan.rb index 302093693e..302093693e 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Magadan.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Magadan.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Muscat.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Muscat.rb index 604f651dfa..604f651dfa 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Muscat.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Muscat.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Novosibirsk.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Novosibirsk.rb index a4e7796e75..a4e7796e75 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Novosibirsk.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Novosibirsk.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Rangoon.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Rangoon.rb index 759b82d77a..759b82d77a 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Rangoon.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Rangoon.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Riyadh.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Riyadh.rb index 7add410620..7add410620 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Riyadh.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Riyadh.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Seoul.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Seoul.rb index 795d2a75df..795d2a75df 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Seoul.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Seoul.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Shanghai.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Shanghai.rb index 34b13d59ae..34b13d59ae 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Shanghai.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Shanghai.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Singapore.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Singapore.rb index b323a78f74..b323a78f74 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Singapore.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Singapore.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Taipei.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Taipei.rb index 3ba12108fb..3ba12108fb 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Taipei.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Taipei.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Tashkent.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Tashkent.rb index c205c7934d..c205c7934d 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Tashkent.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Tashkent.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Tbilisi.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Tbilisi.rb index 15792a5651..15792a5651 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Tbilisi.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Tbilisi.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Tehran.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Tehran.rb index d8df964a46..d8df964a46 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Tehran.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Tehran.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Tokyo.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Tokyo.rb index 51c9e16421..51c9e16421 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Tokyo.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Tokyo.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Ulaanbaatar.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Ulaanbaatar.rb index 2854f5c5fd..2854f5c5fd 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Ulaanbaatar.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Ulaanbaatar.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Urumqi.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Urumqi.rb index d793ff1341..d793ff1341 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Urumqi.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Urumqi.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Vladivostok.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Vladivostok.rb index bd9e3d60ec..bd9e3d60ec 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Vladivostok.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Vladivostok.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Yakutsk.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Yakutsk.rb index 56435a788f..56435a788f 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Yakutsk.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Yakutsk.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Yekaterinburg.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Yekaterinburg.rb index 8ef8df4a41..8ef8df4a41 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Yekaterinburg.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Yekaterinburg.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Yerevan.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Yerevan.rb index e7f160861f..e7f160861f 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Asia/Yerevan.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Asia/Yerevan.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Atlantic/Azores.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Atlantic/Azores.rb index 1bd16a75ac..1bd16a75ac 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Atlantic/Azores.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Atlantic/Azores.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Atlantic/Cape_Verde.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Atlantic/Cape_Verde.rb index 61c8c15043..61c8c15043 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Atlantic/Cape_Verde.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Atlantic/Cape_Verde.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Atlantic/South_Georgia.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Atlantic/South_Georgia.rb index 6a4cbafb9f..6a4cbafb9f 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Atlantic/South_Georgia.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Atlantic/South_Georgia.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Australia/Adelaide.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Adelaide.rb index c5d561cc1e..c5d561cc1e 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Australia/Adelaide.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Adelaide.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Australia/Brisbane.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Brisbane.rb index dd85ddae94..dd85ddae94 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Australia/Brisbane.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Brisbane.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Australia/Darwin.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Darwin.rb index 17de88124d..17de88124d 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Australia/Darwin.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Darwin.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Australia/Hobart.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Hobart.rb index 11384b9840..11384b9840 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Australia/Hobart.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Hobart.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Australia/Melbourne.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Melbourne.rb index c1304488ea..c1304488ea 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Australia/Melbourne.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Melbourne.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Australia/Perth.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Perth.rb index d9e66f14a8..d9e66f14a8 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Australia/Perth.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Perth.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Australia/Sydney.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Sydney.rb index 9062bd7c3c..9062bd7c3c 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Australia/Sydney.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Australia/Sydney.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Etc/UTC.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Etc/UTC.rb index 28b2c6a04c..28b2c6a04c 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Etc/UTC.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Etc/UTC.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Amsterdam.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Amsterdam.rb index 2d0c95c4bc..2d0c95c4bc 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Amsterdam.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Amsterdam.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Athens.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Athens.rb index 4e21e535ca..4e21e535ca 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Athens.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Athens.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Belgrade.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Belgrade.rb index 4dbd893d75..4dbd893d75 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Belgrade.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Belgrade.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Berlin.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Berlin.rb index 721054236c..721054236c 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Berlin.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Berlin.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Bratislava.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Bratislava.rb index 7a731a0b6a..7a731a0b6a 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Bratislava.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Bratislava.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Brussels.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Brussels.rb index 6b0a242944..6b0a242944 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Brussels.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Brussels.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Bucharest.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Bucharest.rb index 521c3c932e..521c3c932e 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Bucharest.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Bucharest.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Budapest.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Budapest.rb index 1f3a9738b7..1f3a9738b7 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Budapest.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Budapest.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Copenhagen.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Copenhagen.rb index 47cbaf14a7..47cbaf14a7 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Copenhagen.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Copenhagen.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Dublin.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Dublin.rb index 0560bb5436..0560bb5436 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Dublin.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Dublin.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Helsinki.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Helsinki.rb index 13a806bcc7..13a806bcc7 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Helsinki.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Helsinki.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Istanbul.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Istanbul.rb index 8306c47536..8306c47536 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Istanbul.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Istanbul.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Kiev.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Kiev.rb index 513d3308be..513d3308be 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Kiev.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Kiev.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Lisbon.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Lisbon.rb index 1c6d2a3d30..1c6d2a3d30 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Lisbon.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Lisbon.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Ljubljana.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Ljubljana.rb index a9828e6ef8..a9828e6ef8 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Ljubljana.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Ljubljana.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/London.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/London.rb index 64ce41e900..64ce41e900 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/London.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/London.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Madrid.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Madrid.rb index 1fb568239a..1fb568239a 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Madrid.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Madrid.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Minsk.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Minsk.rb index fa15816cc8..fa15816cc8 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Minsk.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Minsk.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Moscow.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Moscow.rb index ef269b675b..ef269b675b 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Moscow.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Moscow.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Paris.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Paris.rb index e3236c0ba1..e3236c0ba1 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Paris.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Paris.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Prague.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Prague.rb index bcabee96c1..bcabee96c1 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Prague.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Prague.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Riga.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Riga.rb index 784837f758..784837f758 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Riga.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Riga.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Rome.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Rome.rb index aa7b43d9d2..aa7b43d9d2 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Rome.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Rome.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Sarajevo.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Sarajevo.rb index 068c5fe6ad..068c5fe6ad 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Sarajevo.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Sarajevo.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Skopje.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Skopje.rb index 10b71f285e..10b71f285e 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Skopje.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Skopje.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Sofia.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Sofia.rb index 38a70eceb9..38a70eceb9 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Sofia.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Sofia.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Stockholm.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Stockholm.rb index 43db70fa61..43db70fa61 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Stockholm.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Stockholm.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Tallinn.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Tallinn.rb index de5a8569f3..de5a8569f3 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Tallinn.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Tallinn.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Vienna.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Vienna.rb index 990aabab66..990aabab66 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Vienna.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Vienna.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Vilnius.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Vilnius.rb index d89d095a75..d89d095a75 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Vilnius.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Vilnius.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Warsaw.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Warsaw.rb index 7fa51c2691..7fa51c2691 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Warsaw.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Warsaw.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Zagreb.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Zagreb.rb index ecdd903d28..ecdd903d28 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Europe/Zagreb.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Europe/Zagreb.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Auckland.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Auckland.rb index a524fd6b6b..a524fd6b6b 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Auckland.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Auckland.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Fiji.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Fiji.rb index 5fe9bbd9a6..5fe9bbd9a6 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Fiji.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Fiji.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Guam.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Guam.rb index d4c1a0a682..d4c1a0a682 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Guam.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Guam.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Honolulu.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Honolulu.rb index 204b226537..204b226537 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Honolulu.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Honolulu.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Majuro.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Majuro.rb index 32adad92c1..32adad92c1 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Majuro.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Majuro.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Midway.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Midway.rb index 97784fcc10..97784fcc10 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Midway.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Midway.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Noumea.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Noumea.rb index 70173db8ab..70173db8ab 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Noumea.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Noumea.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Pago_Pago.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Pago_Pago.rb index c8fcd7d527..c8fcd7d527 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Pago_Pago.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Pago_Pago.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Port_Moresby.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Port_Moresby.rb index f06cf6d54f..f06cf6d54f 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Port_Moresby.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Port_Moresby.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Tongatapu.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Tongatapu.rb index 7578d92f38..7578d92f38 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/definitions/Pacific/Tongatapu.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/definitions/Pacific/Tongatapu.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/info_timezone.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/info_timezone.rb index 001303c594..001303c594 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/info_timezone.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/info_timezone.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/linked_timezone.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/linked_timezone.rb index f8ec4fca87..f8ec4fca87 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/linked_timezone.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/linked_timezone.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/linked_timezone_info.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/linked_timezone_info.rb index 8197ff3e81..8197ff3e81 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/linked_timezone_info.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/linked_timezone_info.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/offset_rationals.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/offset_rationals.rb index b1f10b2b63..b1f10b2b63 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/offset_rationals.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/offset_rationals.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/ruby_core_support.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/ruby_core_support.rb index b65eeaaae7..b65eeaaae7 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/ruby_core_support.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/ruby_core_support.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/time_or_datetime.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/time_or_datetime.rb index 264517f3ee..264517f3ee 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/time_or_datetime.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/time_or_datetime.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/timezone.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone.rb index ef4ecd8ae1..ef4ecd8ae1 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/timezone.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/timezone_definition.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone_definition.rb index 39ca8bfa53..39ca8bfa53 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/timezone_definition.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone_definition.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/timezone_info.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone_info.rb index 68e38c35fb..68e38c35fb 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/timezone_info.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone_info.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/timezone_offset_info.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone_offset_info.rb index 6a0bbca46f..6a0bbca46f 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/timezone_offset_info.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone_offset_info.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/timezone_period.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone_period.rb index 00888fcfdc..00888fcfdc 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/timezone_period.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone_period.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/timezone_transition_info.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone_transition_info.rb index 6b0669cc4a..6b0669cc4a 100644 --- a/activesupport/lib/active_support/vendor/tzinfo-0.3.13/tzinfo/timezone_transition_info.rb +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.13/lib/tzinfo/timezone_transition_info.rb diff --git a/activesupport/lib/active_support/vendor/tzinfo.rb b/activesupport/lib/active_support/vendor/tzinfo.rb new file mode 100644 index 0000000000..01fba6d632 --- /dev/null +++ b/activesupport/lib/active_support/vendor/tzinfo.rb @@ -0,0 +1,6 @@ +begin + require 'tzinfo' +rescue LoadError + $:.unshift File.expand_path(File.join(File.dirname(__FILE__), 'tzinfo-0.3.13', 'lib')) + retry +end diff --git a/activesupport/lib/active_support/xml_mini/nokogiri.rb b/activesupport/lib/active_support/xml_mini/nokogiri.rb index 847ab0152b..17bacd8441 100644 --- a/activesupport/lib/active_support/xml_mini/nokogiri.rb +++ b/activesupport/lib/active_support/xml_mini/nokogiri.rb @@ -18,7 +18,7 @@ module ActiveSupport {} else data.ungetc(char) - doc = Nokogiri::XML(data) + doc = Nokogiri::XML(data) { |cfg| cfg.noblanks } raise doc.errors.first if doc.errors.length > 0 doc.to_hash end @@ -39,33 +39,25 @@ module ActiveSupport # hash:: # Hash to merge the converted element into. def to_hash(hash = {}) - hash[name] ||= attributes_as_hash + attributes = attributes_as_hash + if hash[name] + hash[name] = [hash[name]].flatten + hash[name] << attributes + else + hash[name] ||= attributes + end - walker = lambda { |memo, parent, child, callback| - next if child.blank? && 'file' != parent['type'] + children.each { |child| + next if child.blank? && 'file' != self['type'] - if child.text? - (memo[CONTENT_ROOT] ||= '') << child.content + if child.text? || child.cdata? + (attributes[CONTENT_ROOT] ||= '') << child.content next end - name = child.name - - child_hash = child.attributes_as_hash - if memo[name] - memo[name] = [memo[name]].flatten - memo[name] << child_hash - else - memo[name] = child_hash - end - - # Recursively walk children - child.children.each { |c| - callback.call(child_hash, child, c, callback) - } + child.to_hash attributes } - children.each { |c| walker.call(hash[name], self, c, walker) } hash end diff --git a/activesupport/lib/active_support/xml_mini/rexml.rb b/activesupport/lib/active_support/xml_mini/rexml.rb index aaf4bb6bfd..3db48ce5a3 100644 --- a/activesupport/lib/active_support/xml_mini/rexml.rb +++ b/activesupport/lib/active_support/xml_mini/rexml.rb @@ -1,3 +1,4 @@ +require 'active_support/core_ext/kernel/reporting' require 'active_support/core_ext/object/blank' # = XmlMini ReXML implementation @@ -24,7 +25,7 @@ module ActiveSupport {} else data.ungetc(char) - require 'rexml/document' unless defined?(REXML::Document) + silence_warnings { require 'rexml/document' } unless defined?(REXML::Document) doc = REXML::Document.new(data) merge_element!({}, doc.root) end diff --git a/activesupport/lib/activesupport.rb b/activesupport/lib/activesupport.rb deleted file mode 100644 index 69f36f7934..0000000000 --- a/activesupport/lib/activesupport.rb +++ /dev/null @@ -1 +0,0 @@ -require 'active_support' diff --git a/activesupport/test/abstract_unit.rb b/activesupport/test/abstract_unit.rb index 61914231ef..ee6084dfcd 100644 --- a/activesupport/test/abstract_unit.rb +++ b/activesupport/test/abstract_unit.rb @@ -1,15 +1,25 @@ ORIG_ARGV = ARGV.dup -require 'rubygems' require 'test/unit' +begin + require 'mocha' +rescue LoadError + $stderr.puts 'Loading rubygems' + require 'rubygems' + require 'mocha' +end + ENV['NO_RELOAD'] = '1' $:.unshift "#{File.dirname(__FILE__)}/../lib" require 'active_support' require 'active_support/test_case' +# Include shims until we get off 1.8.6 +require 'active_support/ruby/shim' + def uses_memcached(test_name) - require 'memcache' + require 'active_support/vendor/memcache' begin MemCache.new('localhost').stats yield diff --git a/activesupport/test/core_ext/boolean_ext_test.rb b/activesupport/test/core_ext/boolean_ext_test.rb index 751f703745..9439716efb 100644 --- a/activesupport/test/core_ext/boolean_ext_test.rb +++ b/activesupport/test/core_ext/boolean_ext_test.rb @@ -1,3 +1,6 @@ +require 'abstract_unit' +require 'active_support/core_ext/boolean/conversions' + class BooleanExtAccessTests < Test::Unit::TestCase def test_to_param_on_true assert_equal true, true.to_param @@ -6,4 +9,4 @@ class BooleanExtAccessTests < Test::Unit::TestCase def test_to_param_on_false assert_equal false, false.to_param end -end
\ No newline at end of file +end diff --git a/activesupport/test/core_ext/nil_ext_test.rb b/activesupport/test/core_ext/nil_ext_test.rb index 945d3af239..1062676d65 100644 --- a/activesupport/test/core_ext/nil_ext_test.rb +++ b/activesupport/test/core_ext/nil_ext_test.rb @@ -1,5 +1,8 @@ +require 'abstract_unit' +require 'active_support/core_ext/nil/conversions' + class NilExtAccessTests < Test::Unit::TestCase def test_to_param assert_nil nil.to_param end -end
\ No newline at end of file +end diff --git a/activesupport/test/core_ext/object_ext_test.rb b/activesupport/test/core_ext/object_ext_test.rb index 72e3bffa4c..484eecaab6 100644 --- a/activesupport/test/core_ext/object_ext_test.rb +++ b/activesupport/test/core_ext/object_ext_test.rb @@ -1,4 +1,6 @@ require 'abstract_unit' +require 'active_support/core_ext/object/metaclass' +require 'active_support/core_ext/object/conversions' class ObjectExtTest < Test::Unit::TestCase def test_tap_yields_and_returns_self diff --git a/activesupport/test/core_ext/regexp_ext_test.rb b/activesupport/test/core_ext/regexp_ext_test.rb index e2d9140bca..cc3f07d5c5 100644 --- a/activesupport/test/core_ext/regexp_ext_test.rb +++ b/activesupport/test/core_ext/regexp_ext_test.rb @@ -1,3 +1,6 @@ +require 'abstract_unit' +require 'active_support/core_ext/regexp' + class RegexpExtAccessTests < Test::Unit::TestCase def test_number_of_captures assert_equal 0, //.number_of_captures @@ -23,4 +26,4 @@ class RegexpExtAccessTests < Test::Unit::TestCase assert_equal "foo", Regexp.unoptionalize("(?:foo)?") assert_equal "", Regexp.unoptionalize("") end -end
\ No newline at end of file +end diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb index 1005a7e7ad..db9073e298 100644 --- a/activesupport/test/core_ext/string_ext_test.rb +++ b/activesupport/test/core_ext/string_ext_test.rb @@ -316,8 +316,12 @@ class TestGetTextString < Test::Unit::TestCase end def test_no_placeholder - assert_equal("aaa", "aaa" % {:num => 1}) - assert_equal("bbb", "bbb" % [1]) + # Causes a "too many arguments for format string" warning + # on 1.8.7 and 1.9 but we still want to make sure the behavior works + silence_warnings do + assert_equal("aaa", "aaa" % {:num => 1}) + assert_equal("bbb", "bbb" % [1]) + end end def test_sprintf_ruby19_style diff --git a/activesupport/test/flush_cache_on_private_memoization_test.rb b/activesupport/test/flush_cache_on_private_memoization_test.rb index ddbd05b0e0..1cd313ec81 100644 --- a/activesupport/test/flush_cache_on_private_memoization_test.rb +++ b/activesupport/test/flush_cache_on_private_memoization_test.rb @@ -1,5 +1,4 @@ -require 'rubygems' -require 'activesupport' +require 'active_support' require 'test/unit' class FlashCacheOnPrivateMemoizationTest < Test::Unit::TestCase @@ -41,4 +40,4 @@ class FlashCacheOnPrivateMemoizationTest < Test::Unit::TestCase end end -end
\ No newline at end of file +end diff --git a/activesupport/test/isolation_test.rb b/activesupport/test/isolation_test.rb index 7aecdb8009..20e11df1dd 100644 --- a/activesupport/test/isolation_test.rb +++ b/activesupport/test/isolation_test.rb @@ -1,158 +1,162 @@ require 'abstract_unit' +require 'rbconfig' -# Does awesome -if defined?(MiniTest) - $stderr.puts "Umm, MiniTest not supported yet, mmkay?" -elsif ENV['CHILD'] - class ChildIsolationTest < ActiveSupport::TestCase - include ActiveSupport::Testing::Isolation +if defined?(MiniTest) || defined?(Test::Unit::TestResultFailureSupport) + $stderr.puts "Isolation tests can test test-unit 1 only" - def self.setup - File.open(File.join(File.dirname(__FILE__), "fixtures", "isolation_test"), "a") do |f| - f.puts "hello" +else + # Does awesome + if ENV['CHILD'] + class ChildIsolationTest < ActiveSupport::TestCase + include ActiveSupport::Testing::Isolation + + def self.setup + File.open(File.join(File.dirname(__FILE__), "fixtures", "isolation_test"), "a") do |f| + f.puts "hello" + end end - end - def setup - @instance = "HELLO" - end + def setup + @instance = "HELLO" + end - def teardown - raise if @boom - end + def teardown + raise if @boom + end - test "runs the test" do - assert true - end + test "runs the test" do + assert true + end - test "captures errors" do - raise - end + test "captures errors" do + raise + end - test "captures failures" do - assert false - end + test "captures failures" do + assert false + end - test "first runs in isolation" do - assert_nil $x - $x = 1 - end + test "first runs in isolation" do + assert_nil $x + $x = 1 + end - test "second runs in isolation" do - assert_nil $x - $x = 2 - end + test "second runs in isolation" do + assert_nil $x + $x = 2 + end - test "runs with slow tests" do - sleep 0.3 - assert true - sleep 0.2 - end + test "runs with slow tests" do + sleep 0.3 + assert true + sleep 0.2 + end - test "runs setup" do - assert "HELLO", @instance - end + test "runs setup" do + assert "HELLO", @instance + end - test "runs teardown" do - @boom = true - end + test "runs teardown" do + @boom = true + end - test "resets requires one" do - assert !defined?(OmgOmg) - assert_equal 0, $LOADED_FEATURES.grep(/fixtures\/omgomg/).size - require File.expand_path(File.join(File.dirname(__FILE__), "fixtures", "omgomg")) - end + test "resets requires one" do + assert !defined?(OmgOmg) + assert_equal 0, $LOADED_FEATURES.grep(/fixtures\/omgomg/).size + require File.expand_path(File.join(File.dirname(__FILE__), "fixtures", "omgomg")) + end - test "resets requires two" do - assert !defined?(OmgOmg) - assert_equal 0, $LOADED_FEATURES.grep(/fixtures\/omgomg/).size - require File.expand_path(File.join(File.dirname(__FILE__), "fixtures", "omgomg")) + test "resets requires two" do + assert !defined?(OmgOmg) + assert_equal 0, $LOADED_FEATURES.grep(/fixtures\/omgomg/).size + require File.expand_path(File.join(File.dirname(__FILE__), "fixtures", "omgomg")) + end end - end -else - class ParentIsolationTest < ActiveSupport::TestCase - - File.open(File.join(File.dirname(__FILE__), "fixtures", "isolation_test"), "w") {} - - ENV["CHILD"] = "1" - OUTPUT = `#{Gem.ruby} -I#{File.dirname(__FILE__)} "#{File.expand_path(__FILE__)}" -v` - ENV.delete("CHILD") - - def setup - # Extract the results - @results = {} - OUTPUT[/Started\n\s*(.*)\s*\nFinished/mi, 1].split(/\s*\n\s*/).each do |result| - result =~ %r'^(\w+)\(\w+\):\s*(\.|E|F)$' - @results[$1] = { 'E' => :error, '.' => :success, 'F' => :failure }[$2] + else + class ParentIsolationTest < ActiveSupport::TestCase + + File.open(File.join(File.dirname(__FILE__), "fixtures", "isolation_test"), "w") {} + + ENV["CHILD"] = "1" + OUTPUT = `#{RbConfig::CONFIG["bindir"]}/#{RbConfig::CONFIG["ruby_install_name"]} -I#{File.dirname(__FILE__)} "#{File.expand_path(__FILE__)}" -v` + ENV.delete("CHILD") + + def setup + # Extract the results + @results = {} + OUTPUT[/Started\n\s*(.*)\s*\nFinished/mi, 1].to_s.split(/\s*\n\s*/).each do |result| + result =~ %r'^(\w+)\(\w+\):\s*(\.|E|F)$' + @results[$1] = { 'E' => :error, '.' => :success, 'F' => :failure }[$2] + end + + # Extract the backtraces + @backtraces = {} + OUTPUT.scan(/^\s*\d+\).*?\n\n/m).each do |backtrace| + # \n 1) Error:\ntest_captures_errors(ChildIsolationTest): + backtrace =~ %r'\s*\d+\)\s*(Error|Failure):\n(\w+)'i + @backtraces[$2] = { :type => $1, :output => backtrace } + end end - # Extract the backtraces - @backtraces = {} - OUTPUT.scan(/^\s*\d+\).*?\n\n/m).each do |backtrace| - # \n 1) Error:\ntest_captures_errors(ChildIsolationTest): - backtrace =~ %r'\s*\d+\)\s*(Error|Failure):\n(\w+)'i - @backtraces[$2] = { :type => $1, :output => backtrace } + def assert_failing(name) + assert_equal :failure, @results[name.to_s], "Test #{name} did not fail" end - end - def assert_failing(name) - assert_equal :failure, @results[name.to_s], "Test #{name} did not fail" - end + def assert_passing(name) + assert_equal :success, @results[name.to_s], "Test #{name} did not pass" + end - def assert_passing(name) - assert_equal :success, @results[name.to_s], "Test #{name} did not pass" - end + def assert_erroring(name) + assert_equal :error, @results[name.to_s], "Test #{name} did not error" + end - def assert_erroring(name) - assert_equal :error, @results[name.to_s], "Test #{name} did not error" - end + test "has all tests" do + assert_equal 10, @results.length + end - test "has all tests" do - assert_equal 10, @results.length - end + test "passing tests are still reported" do + assert_passing :test_runs_the_test + assert_passing :test_runs_with_slow_tests + end - test "passing tests are still reported" do - assert_passing :test_runs_the_test - assert_passing :test_runs_with_slow_tests - end + test "resets global variables" do + assert_passing :test_first_runs_in_isolation + assert_passing :test_second_runs_in_isolation + end - test "resets global variables" do - assert_passing :test_first_runs_in_isolation - assert_passing :test_second_runs_in_isolation - end + test "resets requires" do + assert_passing :test_resets_requires_one + assert_passing :test_resets_requires_two + end - test "resets requires" do - assert_passing :test_resets_requires_one - assert_passing :test_resets_requires_two - end + test "erroring tests are still reported" do + assert_erroring :test_captures_errors + end - test "erroring tests are still reported" do - assert_erroring :test_captures_errors - end + test "runs setup and teardown methods" do + assert_passing :test_runs_setup + assert_erroring :test_runs_teardown + end - test "runs setup and teardown methods" do - assert_passing :test_runs_setup - assert_erroring :test_runs_teardown - end + test "correct tests fail" do + assert_failing :test_captures_failures + end - test "correct tests fail" do - assert_failing :test_captures_failures - end + test "backtrace is printed for errors" do + assert_equal 'Error', @backtraces["test_captures_errors"][:type] + assert_match %r{isolation_test.rb:\d+:in `test_captures_errors'}, @backtraces["test_captures_errors"][:output] + end - test "backtrace is printed for errors" do - assert_equal 'Error', @backtraces["test_captures_errors"][:type] - assert_match %r{isolation_test.rb:\d+:in `test_captures_errors'}, @backtraces["test_captures_errors"][:output] - end + test "backtrace is printed for failures" do + assert_equal 'Failure', @backtraces["test_captures_failures"][:type] + assert_match %r{isolation_test.rb:\d+:in `test_captures_failures'}, @backtraces["test_captures_failures"][:output] + end - test "backtrace is printed for failures" do - assert_equal 'Failure', @backtraces["test_captures_failures"][:type] - assert_match %r{isolation_test.rb:\d+:in `test_captures_failures'}, @backtraces["test_captures_failures"][:output] - end + test "self.setup is run only once" do + text = File.read(File.join(File.dirname(__FILE__), "fixtures", "isolation_test")) + assert_equal "hello\n", text + end - test "self.setup is run only once" do - text = File.read(File.join(File.dirname(__FILE__), "fixtures", "isolation_test")) - assert_equal "hello\n", text end - end end diff --git a/activesupport/test/json/decoding_test.rb b/activesupport/test/json/decoding_test.rb index 05e420ae36..7b5a4d0416 100644 --- a/activesupport/test/json/decoding_test.rb +++ b/activesupport/test/json/decoding_test.rb @@ -47,13 +47,7 @@ class TestJSONDecoding < ActiveSupport::TestCase ActiveSupport::JSON.backend backends = %w(Yaml) - begin - gem 'json', '>= 1.1' - require 'json' - backends << "JSONGem" - rescue Gem::LoadError - # Skip JSON gem tests - end + backends << "JSONGem" if defined?(::JSON) backends.each do |backend| TESTS.each do |json, expected| @@ -81,7 +75,7 @@ class TestJSONDecoding < ActiveSupport::TestCase end def test_failed_json_decoding - assert_raise(ActiveSupport::JSON::ParseError) { ActiveSupport::JSON.decode(%({: 1})) } + assert_raise(ActiveSupport::JSON.parse_error) { ActiveSupport::JSON.decode(%({: 1})) } end end diff --git a/activesupport/test/memoizable_test.rb b/activesupport/test/memoizable_test.rb index 214e243aa5..3bad683093 100644 --- a/activesupport/test/memoizable_test.rb +++ b/activesupport/test/memoizable_test.rb @@ -124,16 +124,6 @@ class MemoizableTest < ActiveSupport::TestCase assert_equal 1, @person.age_calls end - def test_memorized_results_are_immutable - # This is purely a performance enhancement that we can revisit once the rest of - # the code is in place. Ideally, we'd be able to do memoization in a freeze-friendly - # way without amc hacks - pending do - assert_equal "Josh", @person.name - assert_raise(ActiveSupport::FrozenObjectError) { @person.name.gsub!("Josh", "Gosh") } - end - end - def test_reloadable counter = @calculator.counter assert_equal 1, @calculator.counter diff --git a/activesupport/test/multibyte_chars_test.rb b/activesupport/test/multibyte_chars_test.rb index ed37a1a0da..680936ded5 100644 --- a/activesupport/test/multibyte_chars_test.rb +++ b/activesupport/test/multibyte_chars_test.rb @@ -390,7 +390,7 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase assert_equal 'ちわ', @chars.slice(2..10) assert_equal '', @chars.slice(4..10) assert_equal 'に', @chars.slice(/に/u) - assert_equal 'にち', @chars.slice(/に\w/u) + assert_equal 'にち', @chars.slice(/に./u) assert_equal nil, @chars.slice(/unknown/u) assert_equal 'にち', @chars.slice(/(にち)/u, 1) assert_equal nil, @chars.slice(/(にち)/u, 2) diff --git a/activesupport/test/multibyte_utils_test.rb b/activesupport/test/multibyte_utils_test.rb new file mode 100644 index 0000000000..0a2f20d282 --- /dev/null +++ b/activesupport/test/multibyte_utils_test.rb @@ -0,0 +1,137 @@ +# encoding: utf-8 + +require 'abstract_unit' +require 'multibyte_test_helpers' + +class MultibyteUtilsTest < ActiveSupport::TestCase + include MultibyteTestHelpers + + test "valid_character returns an expression for the current encoding" do + with_encoding('None') do + assert_nil ActiveSupport::Multibyte.valid_character + end + with_encoding('UTF8') do + assert_equal ActiveSupport::Multibyte::VALID_CHARACTER['UTF-8'], ActiveSupport::Multibyte.valid_character + end + with_encoding('SJIS') do + assert_equal ActiveSupport::Multibyte::VALID_CHARACTER['Shift_JIS'], ActiveSupport::Multibyte.valid_character + end + end + + test "verify verifies ASCII strings are properly encoded" do + with_encoding('None') do + examples.each do |example| + assert ActiveSupport::Multibyte.verify(example) + end + end + end + + test "verify verifies UTF-8 strings are properly encoded" do + with_encoding('UTF8') do + assert ActiveSupport::Multibyte.verify(example('valid UTF-8')) + assert !ActiveSupport::Multibyte.verify(example('invalid UTF-8')) + end + end + + test "verify verifies Shift-JIS strings are properly encoded" do + with_encoding('SJIS') do + assert ActiveSupport::Multibyte.verify(example('valid Shift-JIS')) + assert !ActiveSupport::Multibyte.verify(example('invalid Shift-JIS')) + end + end + + test "verify! raises an exception when it finds an invalid character" do + with_encoding('UTF8') do + assert_raises(ActiveSupport::Multibyte::EncodingError) do + ActiveSupport::Multibyte.verify!(example('invalid UTF-8')) + end + end + end + + test "verify! doesn't raise an exception when the encoding is valid" do + with_encoding('UTF8') do + assert_nothing_raised do + ActiveSupport::Multibyte.verify!(example('valid UTF-8')) + end + end + end + + if RUBY_VERSION < '1.9' + test "clean leaves ASCII strings intact" do + with_encoding('None') do + [ + 'word', "\270\236\010\210\245" + ].each do |string| + assert_equal string, ActiveSupport::Multibyte.clean(string) + end + end + end + + test "clean cleans invalid characters from UTF-8 encoded strings" do + with_encoding('UTF8') do + cleaned_utf8 = [8].pack('C*') + assert_equal example('valid UTF-8'), ActiveSupport::Multibyte.clean(example('valid UTF-8')) + assert_equal cleaned_utf8, ActiveSupport::Multibyte.clean(example('invalid UTF-8')) + end + end + + test "clean cleans invalid characters from Shift-JIS encoded strings" do + with_encoding('SJIS') do + cleaned_sjis = [184, 0, 136, 165].pack('C*') + assert_equal example('valid Shift-JIS'), ActiveSupport::Multibyte.clean(example('valid Shift-JIS')) + assert_equal cleaned_sjis, ActiveSupport::Multibyte.clean(example('invalid Shift-JIS')) + end + end + else + test "clean is a no-op" do + with_encoding('UTF8') do + assert_equal example('invalid Shift-JIS'), ActiveSupport::Multibyte.clean(example('invalid Shift-JIS')) + end + end + end + + private + + STRINGS = { + 'valid ASCII' => [65, 83, 67, 73, 73].pack('C*'), + 'invalid ASCII' => [128].pack('C*'), + 'valid UTF-8' => [227, 129, 147, 227, 129, 171, 227, 129, 161, 227, 130, 143].pack('C*'), + 'invalid UTF-8' => [184, 158, 8, 136, 165].pack('C*'), + 'valid Shift-JIS' => [131, 122, 129, 91, 131, 128].pack('C*'), + 'invalid Shift-JIS' => [184, 158, 8, 0, 255, 136, 165].pack('C*') + } + + if Kernel.const_defined?(:Encoding) + def example(key) + STRINGS[key].force_encoding(Encoding.default_external) + end + + def examples + STRINGS.values.map { |s| s.force_encoding(Encoding.default_external) } + end + else + def example(key) + STRINGS[key] + end + + def examples + STRINGS.values + end + end + + if 'string'.respond_to?(:encoding) + KCODE_TO_ENCODING = Hash.new(Encoding::BINARY). + update('UTF8' => Encoding::UTF_8, 'SJIS' => Encoding::Shift_JIS) + + def with_encoding(enc) + before = Encoding.default_external + silence_warnings { Encoding.default_external = KCODE_TO_ENCODING[enc] } + + yield + + silence_warnings { Encoding.default_external = before } + end + else + alias with_encoding with_kcode + end +end diff --git a/activesupport/test/new_callbacks_test.rb b/activesupport/test/new_callbacks_test.rb index 7e092b5f63..04db376fc6 100644 --- a/activesupport/test/new_callbacks_test.rb +++ b/activesupport/test/new_callbacks_test.rb @@ -180,6 +180,10 @@ module NewCallbacksTest end end + class CleanPerson < ConditionalPerson + reset_callbacks :save + end + class MySuper include ActiveSupport::NewCallbacks define_callbacks :save @@ -349,10 +353,18 @@ module NewCallbacksTest end end + class ResetCallbackTest < Test::Unit::TestCase + def test_save_conditional_person + person = CleanPerson.new + person.save + assert_equal [], person.history + end + end + class CallbackTerminator include ActiveSupport::NewCallbacks - define_callbacks :save, "result == :halt" + define_callbacks :save, :terminator => "result == :halt" set_callback :save, :before, :first set_callback :save, :before, :second @@ -400,7 +412,11 @@ module NewCallbacksTest def before(caller) caller.record << "before" end - + + def before_save(caller) + caller.record << "before save" + end + def around(caller) caller.record << "around before" yield @@ -410,15 +426,15 @@ module NewCallbacksTest class UsingObjectBefore include ActiveSupport::NewCallbacks - + define_callbacks :save set_callback :save, :before, CallbackObject.new - + attr_accessor :record def initialize @record = [] end - + def save _run_save_callbacks do @record << "yielded" @@ -443,19 +459,49 @@ module NewCallbacksTest end end end - + + class CustomScopeObject + include ActiveSupport::NewCallbacks + + define_callbacks :save, :scope => [:kind, :name] + set_callback :save, :before, CallbackObject.new + + attr_accessor :record + def initialize + @record = [] + end + + def save + _run_save_callbacks do + @record << "yielded" + "CallbackResult" + end + end + end + class UsingObjectTest < Test::Unit::TestCase def test_before_object u = UsingObjectBefore.new u.save assert_equal ["before", "yielded"], u.record end - + def test_around_object u = UsingObjectAround.new u.save assert_equal ["around before", "yielded", "around after"], u.record - end + end + + def test_customized_object + u = CustomScopeObject.new + u.save + assert_equal ["before save", "yielded"], u.record + end + + def test_block_result_is_returned + u = CustomScopeObject.new + assert_equal "CallbackResult", u.save + end end class CallbackTerminatorTest < Test::Unit::TestCase @@ -469,7 +515,7 @@ module NewCallbacksTest obj = CallbackTerminator.new obj.save assert !obj.saved - end + end end class HyphenatedKeyTest < Test::Unit::TestCase @@ -477,6 +523,6 @@ module NewCallbacksTest obj = HyphenatedCallbacks.new obj.save assert_equal obj.stuff, "OMG" - end - end + end + end end diff --git a/activesupport/test/orchestra_test.rb b/activesupport/test/orchestra_test.rb new file mode 100644 index 0000000000..683cc36f6a --- /dev/null +++ b/activesupport/test/orchestra_test.rb @@ -0,0 +1,161 @@ +require 'abstract_unit' + +class OrchestraEventTest < Test::Unit::TestCase + def setup + @parent = ActiveSupport::Orchestra::Event.new(:parent) + end + + def test_initialization_with_name_and_parent_and_payload + event = ActiveSupport::Orchestra::Event.new(:awesome, @parent, :payload => "orchestra") + assert_equal(:awesome, event.name) + assert_equal(@parent, event.parent) + assert_equal({ :payload => "orchestra" }, event.payload) + end + + def test_thread_id_is_set_on_initialization + event = ActiveSupport::Orchestra::Event.new(:awesome) + assert_equal Thread.current.object_id, event.thread_id + end + + def test_current_time_is_set_on_initialization + previous_time = Time.now.utc + event = ActiveSupport::Orchestra::Event.new(:awesome) + assert_kind_of Time, event.time + assert event.time.to_f >= previous_time.to_f + end + + def test_duration_is_set_when_event_finishes + event = ActiveSupport::Orchestra::Event.new(:awesome) + sleep(0.1) + event.finish! + assert_in_delta 100, event.duration, 30 + end +end + +class OrchestraMainTest < Test::Unit::TestCase + def setup + @listener = [] + ActiveSupport::Orchestra.register @listener + end + + def teardown + ActiveSupport::Orchestra.unregister @listener + end + + def test_orchestra_allows_any_action_to_be_instrumented + event = ActiveSupport::Orchestra.instrument(:awesome, "orchestra") do + sleep(0.1) + end + + assert_equal :awesome, event.name + assert_equal "orchestra", event.payload + assert_in_delta 100, event.duration, 30 + end + + def test_block_result_is_stored + event = ActiveSupport::Orchestra.instrument(:awesome, "orchestra") do + 1 + 1 + end + + assert_equal 2, event.result + end + + def test_events_are_published_to_a_listener + event = ActiveSupport::Orchestra.instrument(:awesome, "orchestra") do + 1 + 1 + end + + assert_equal 1, @listener.size + assert_equal :awesome, @listener.last.name + assert_equal "orchestra", @listener.last.payload + end + + def test_nested_events_can_be_instrumented + ActiveSupport::Orchestra.instrument(:awesome, "orchestra") do + ActiveSupport::Orchestra.instrument(:wot, "child") do + sleep(0.1) + end + + assert_equal 1, @listener.size + assert_equal :wot, @listener.first.name + assert_equal "child", @listener.first.payload + + assert_nil @listener.first.parent.duration + assert_in_delta 100, @listener.first.duration, 30 + end + + assert_equal 2, @listener.size + assert_equal :awesome, @listener.last.name + assert_equal "orchestra", @listener.last.payload + assert_in_delta 100, @listener.first.parent.duration, 30 + end + + def test_event_is_pushed_even_if_block_fails + ActiveSupport::Orchestra.instrument(:awesome, "orchestra") do + raise "OMG" + end rescue RuntimeError + + assert_equal 1, @listener.size + assert_equal :awesome, @listener.last.name + assert_equal "orchestra", @listener.last.payload + end +end + +class OrchestraListenerTest < Test::Unit::TestCase + class MyListener < ActiveSupport::Orchestra::Listener + attr_reader :consumed + + def consume(event) + @consumed ||= [] + @consumed << event + end + end + + def setup + @listener = MyListener.new + ActiveSupport::Orchestra.register @listener + end + + def teardown + ActiveSupport::Orchestra.unregister @listener + end + + def test_thread_is_exposed_by_listener + assert_kind_of Thread, @listener.thread + end + + def test_event_is_consumed_when_an_action_is_instrumented + ActiveSupport::Orchestra.instrument(:sum) do + 1 + 1 + end + sleep 0.1 + assert_equal 1, @listener.consumed.size + assert_equal :sum, @listener.consumed.first.name + assert_equal 2, @listener.consumed.first.result + end + + def test_with_sevaral_consumers_and_several_events + @another = MyListener.new + ActiveSupport::Orchestra.register @another + + 1.upto(100) do |i| + ActiveSupport::Orchestra.instrument(:value) do + i + end + end + + sleep 0.1 + + assert_equal 100, @listener.consumed.size + assert_equal :value, @listener.consumed.first.name + assert_equal 1, @listener.consumed.first.result + assert_equal 100, @listener.consumed.last.result + + assert_equal 100, @another.consumed.size + assert_equal :value, @another.consumed.first.name + assert_equal 1, @another.consumed.first.result + assert_equal 100, @another.consumed.last.result + ensure + ActiveSupport::Orchestra.unregister @another + end +end diff --git a/activesupport/test/xml_mini/nokogiri_engine_test.rb b/activesupport/test/xml_mini/nokogiri_engine_test.rb index 7c3a591e63..e16f36acee 100644 --- a/activesupport/test/xml_mini/nokogiri_engine_test.rb +++ b/activesupport/test/xml_mini/nokogiri_engine_test.rb @@ -3,13 +3,11 @@ require 'active_support/xml_mini' require 'active_support/core_ext/hash/conversions' begin - gem 'nokogiri', '>= 1.1.1' -rescue Gem::LoadError + require 'nokogiri' +rescue LoadError # Skip nokogiri tests else -require 'nokogiri' - class NokogiriEngineTest < Test::Unit::TestCase include ActiveSupport @@ -161,6 +159,17 @@ class NokogiriEngineTest < Test::Unit::TestCase XmlMini.parse(io) end + def test_children_with_cdata + assert_equal_rexml(<<-eoxml) + <root> + <products> + hello <![CDATA[everyone]]> + morning + </products> + </root> + eoxml + end + private def assert_equal_rexml(xml) hash = XmlMini.with_backend('REXML') { XmlMini.parse(xml) } diff --git a/ci/ci_build.rb b/ci/ci_build.rb index 06e513f907..ab627b93e6 100755 --- a/ci/ci_build.rb +++ b/ci/ci_build.rb @@ -21,6 +21,7 @@ cd "#{root_dir}/activesupport" do puts "[CruiseControl] Building ActiveSupport" puts build_results[:activesupport] = system 'rake' + build_results[:activesupport_isolated] = system 'rake isolated_test' end rm_f "#{root_dir}/activerecord/debug.log" @@ -64,7 +65,7 @@ cd "#{root_dir}/actionpack" do puts puts "[CruiseControl] Building ActionPack" puts - build_results[:actionpack] = system 'rake' + build_results[:actionpack] = system 'gem bundle && rake' end cd "#{root_dir}/actionmailer" do diff --git a/ci/geminstaller.yml b/ci/geminstaller.yml index 3a4079ddbb..5a6f9bde01 100644 --- a/ci/geminstaller.yml +++ b/ci/geminstaller.yml @@ -15,8 +15,8 @@ gems: version: >= 0.8.0 - name: rack version: '~> 1.0.0' -- name: josh-rack-test - version: >= 0.4.1 +- name: rack-test + version: >= 0.4.2 - name: rake version: >= 0.8.1 - name: sqlite-ruby diff --git a/railties/Rakefile b/railties/Rakefile index 3212bf3a4f..6ebb11dbb5 100644 --- a/railties/Rakefile +++ b/railties/Rakefile @@ -142,7 +142,7 @@ PKG_FILES = FileList[ 'bin/**/*', 'builtin/**/*', 'guides/**/*', - 'lib/**/*' + 'lib/**/{*,.[a-z]*}' ] - [ 'test' ] spec = Gem::Specification.new do |s| @@ -181,6 +181,12 @@ Rake::GemPackageTask.new(spec) do |pkg| pkg.gem_spec = spec end +task :gemspec do + File.open(File.join(File.dirname(__FILE__), "#{spec.name}.gemspec"), "w") do |file| + file.puts spec.to_ruby + end +end + # Publishing ------------------------------------------------------- desc "Publish the rails gem" diff --git a/railties/builtin/rails_info/rails/info.rb b/railties/builtin/rails_info/rails/info.rb index fdacc469f5..aabe976d4e 100644 --- a/railties/builtin/rails_info/rails/info.rb +++ b/railties/builtin/rails_info/rails/info.rb @@ -29,8 +29,10 @@ module Rails end def framework_version(framework) - require "#{framework}/version" - "#{framework.classify}::VERSION::STRING".constantize + if Object.const_defined?(framework.classify) + require "#{framework}/version" + "#{framework.classify}::VERSION::STRING".constantize + end end def edge_rails_revision(info = git_info) diff --git a/railties/lib/commands/plugin.rb b/railties/lib/commands/plugin.rb index 3d76bcc73f..159db707e7 100644 --- a/railties/lib/commands/plugin.rb +++ b/railties/lib/commands/plugin.rb @@ -232,7 +232,7 @@ class Plugin def install_using_git(options = {}) root = rails_env.root - install_path = mkdir_p "#{root}/vendor/plugins/#{name}" + mkdir_p(install_path = "#{root}/vendor/plugins/#{name}") Dir.chdir install_path do init_cmd = "git init" init_cmd += " -q" if options[:quiet] and not $verbose diff --git a/railties/lib/generators.rb b/railties/lib/generators.rb index 879abb1c41..2a196f65ea 100644 --- a/railties/lib/generators.rb +++ b/railties/lib/generators.rb @@ -1,17 +1,15 @@ activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib" -$:.unshift(activesupport_path) if File.directory?(activesupport_path) - -begin - require 'active_support/mini' -rescue LoadError - require 'rubygems' - gem 'activesupport' - require 'active_support/mini' -end - -$:.unshift(File.dirname(__FILE__)) - -require 'vendor/thor-0.11.6/lib/thor' +$LOAD_PATH.unshift(activesupport_path) if File.directory?(activesupport_path) +require 'active_support' +require 'active_support/core_ext/object/blank' +require 'active_support/core_ext/object/metaclass' +require 'active_support/core_ext/array' +require 'active_support/core_ext/hash' +require 'active_support/core_ext/module/attribute_accessors' +require 'active_support/core_ext/string/inflections' + +$LOAD_PATH.unshift(File.dirname(__FILE__)) +$LOAD_PATH.unshift("#{File.dirname(__FILE__)}/vendor/thor-0.11.6/lib") require 'generators/base' require 'generators/named_base' diff --git a/railties/lib/generators/base.rb b/railties/lib/generators/base.rb index c5d769b6ed..cb6a129264 100644 --- a/railties/lib/generators/base.rb +++ b/railties/lib/generators/base.rb @@ -1,3 +1,4 @@ +require 'thor' require 'generators/actions' module Rails diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index 336bff9534..d882a6714a 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -148,15 +148,6 @@ module Rails $LOAD_PATH.uniq! end - Initializer.default.add :add_gem_load_paths do - require 'rails/gem_dependency' - Rails::GemDependency.add_frozen_gem_path - unless config.gems.empty? - require "rubygems" - config.gems.each { |gem| gem.add_load_paths } - end - end - # Requires all frameworks specified by the Configuration#frameworks # list. By default, all frameworks (Active Record, Active Support, # Action Pack, Action Mailer, and Active Resource) are loaded. @@ -221,6 +212,15 @@ module Rails end end + Initializer.default.add :add_gem_load_paths do + require 'rails/gem_dependency' + Rails::GemDependency.add_frozen_gem_path + unless config.gems.empty? + require "rubygems" + config.gems.each { |gem| gem.add_load_paths } + end + end + # Preload all frameworks specified by the Configuration#frameworks. # Used by Passenger to ensure everything's loaded before forking and # to avoid autoload race conditions in JRuby. diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index 5cc4f80684..2b362a9c50 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -109,6 +109,7 @@ module Rails # TODO: Fix this when there is an application object def middleware + require 'action_controller' ActionController::Dispatcher.middleware end diff --git a/railties/lib/test_help.rb b/railties/lib/test_help.rb index 4318203a42..53f28264e8 100644 --- a/railties/lib/test_help.rb +++ b/railties/lib/test_help.rb @@ -2,6 +2,10 @@ # so fixtures are loaded to the right database silence_warnings { RAILS_ENV = "test" } +require 'rubygems' +gem "rack", "~> 1.0.0" +gem "rack-test", "~> 0.4.2" + require 'test/unit' require 'active_support/core_ext/kernel/requires' require 'action_controller/testing/test_case' diff --git a/railties/lib/vendor/bundler/README.markdown b/railties/lib/vendor/bundler/README.markdown new file mode 100644 index 0000000000..26863e96f2 --- /dev/null +++ b/railties/lib/vendor/bundler/README.markdown @@ -0,0 +1,162 @@ +## Bundler : A gem to bundle gems + + Github: http://github.com/wycats/bundler + Mailing list: http://groups.google.com/group/ruby-bundler + IRC: #carlhuda on freenode + +## Intro + +Bundler is a tool that manages gem dependencies for your ruby application. It +takes a gem manifest file and is able to fetch, download, and install the gems +and all child dependencies specified in this manifest. It can manage any update +to the gem manifest file and update the bundled gems accordingly. It also lets +you run any ruby code in context of the bundled gem environment. + +## Disclaimer + +This project is under rapid development. It is usable today, but there will be +many changes in the near future, including to the Gemfile DSL. We will bump up +versions with changes though. We greatly appreciate feedback. + +## Installation + +Bundler has no dependencies. Just clone the git repository and install the gem +with the following rake task: + + rake install + +## Usage + +Bundler requires a gem manifest file to be created. This should be a file named +`Gemfile` located in the root directory of your application. After the manifest +has been created, in your shell, cd into your application's directory and run +`gem bundle`. This will start the bundling process. + +### Manifest file + +This is where you specify all of your application's dependencies. By default +this should be in a file named `Gemfile` located in your application's root +directory. The following is an example of a potential `Gemfile`. For more +information, please refer to Bundler::ManifestBuilder. + + # Specify a dependency on rails. When the bundler downloads gems, + # it will download rails as well as all of rails' dependencies (such as + # activerecord, actionpack, etc...) + # + # At least one dependency must be specified + gem "rails" + + # Specify a dependency on rack v.1.0.0. The version is optional. If present, + # it can be specified the same way as with rubygems' #gem method. + gem "rack", "1.0.0" + + # Specify a dependency rspec, but only activate that gem in the "testing" + # environment (read more about environments later). :except is also a valid + # option to specify environment restrictions. + gem "rspec", :only => :testing + + # Add http://gems.github.com as a source that the bundler will use + # to find gems listed in the manifest. By default, + # http://gems.rubyforge.org is already added to the list. + # + # This is an optional setting. + source "http://gems.github.com" + + # Specify where the bundled gems should be stashed. This directory will + # be a gem repository where all gems are downloaded to and installed to. + # + # This is an optional setting. + # The default is: vendor/gems + bundle_path "my/bundled/gems" + + # Specify where gem executables should be copied to. + # + # This is an optional setting. + # The default is: bin + bin_path "my/executables" + + # Specify that rubygems should be completely disabled. This means that it + # will be impossible to require it and that available gems will be + # limited exclusively to gems that have been bundled. + # + # The default is to automatically require rubygems. There is also a + # `disable_system_gems` option that will limit available rubygems to + # the ones that have been bundled. + disable_rubygems + +### Running Bundler + +Once a manifest file has been created, the only thing that needs to be done +is to run the `gem bundle` command anywhere in your application. The script +will load the manifest file, resole all the dependencies, download all +needed gems, and install them into the specified directory. + +Every time an update is made to the manifest file, run `gem bundle` again to +get the changes installed. This will only check the remote sources if your +currently installed gems do not satisfy the `Gemfile`. If you want to force +checking for updates on the remote sources, use the `--update` option. + +### Running your application + +The easiest way to run your application is to start it with an executable +copied to the specified bin directory (by default, simply bin). For example, +if the application in question is a rack app, start it with `bin/rackup`. +This will automatically set the gem environment correctly. + +Another way to run arbitrary ruby code in context of the bundled gems is to +run it with the `gem exec` command. For example: + + gem exec ruby my_ruby_script.rb + +Yet another way is to manually require the environment file first. This is +located in `[bundle_path]/environments/default.rb`. For example: + + ruby -r vendor/gems/environment.rb my_ruby_script.rb + +### Using Bundler with Rails today + +It should be possible to use Bundler with Rails today. Here are the steps +to follow. + +* In your rails app, create a Gemfile and specify the gems that your + application depends on. Make sure to specify rails as well: + + gem "rails", "2.1.2" + gem "will_paginate" + + # Optionally, you can disable system gems all together and only + # use bundled gems. + disable_system_gems + +* Run `gem bundle` + +* You can now use rails if you prepend `gem exec` to every call to `script/*` + but that isn't fun. + +* At the top of `config/boot.rb`, add the following line: + + require File.expand_path(File.join(File.dirname(__FILE__), '..', 'vendor', 'gems', 'environment')) + +In theory, this should be enough to get going. + +## To require rubygems or not + +Ideally, no gem would assume the presence of rubygems at runtime. Rubygems provides +enough features so that this isn't necessary. However, there are a number of gems +that require specific rubygem features. + +If the `disable_rubygems` option is used, Bundler will stub out the most common +of these features, but it is possible that things will not go as intended quite +yet. So, if you are brave, try your code without rubygems at runtime. + +## Known Issues + +* When a gem points to a git repository, the git repository will be cloned + every time Bundler does a gem dependency resolve. + +## Reporting bugs + +Please report all bugs on the github issue tracker for the project located +at: + + http://github.com/wycats/bundler/issues/
\ No newline at end of file diff --git a/railties/lib/vendor/bundler/Rakefile b/railties/lib/vendor/bundler/Rakefile index fd39fbff77..dc4c3d6d46 100644 --- a/railties/lib/vendor/bundler/Rakefile +++ b/railties/lib/vendor/bundler/Rakefile @@ -1,52 +1,57 @@ require 'rubygems' unless ENV['NO_RUBYGEMS'] -require 'rake/gempackagetask' require 'rubygems/specification' require 'date' -require 'spec/rake/spectask' spec = Gem::Specification.new do |s| - s.name = "bundler" - s.version = "0.0.1" - s.author = "Your Name" - s.email = "Your Email" - s.homepage = "http://example.com" - s.description = s.summary = "A gem that provides..." + s.name = "bundler" + s.version = "0.5.0.pre" + s.author = "Yehuda Katz" + s.email = "wycats@gmail.com" + s.homepage = "http://github.com/wycats/bundler" + s.description = s.summary = "An easy way to vendor gem dependencies" s.platform = Gem::Platform::RUBY s.has_rdoc = true - s.extra_rdoc_files = ["README", "LICENSE"] - s.summary = "" + s.extra_rdoc_files = ["README.markdown", "LICENSE"] - # Uncomment this to add a dependency - # s.add_dependency "foo" + s.required_rubygems_version = ">= 1.3.5" - s.bindir = "bin" - s.executables = %w( gem_bundler ) s.require_path = 'lib' - s.files = %w(LICENSE README Rakefile) + Dir.glob("{bin,lib,spec}/**/*") + s.files = %w(LICENSE README.markdown Rakefile) + Dir.glob("lib/**/*") end task :default => :spec -desc "Run specs" -Spec::Rake::SpecTask.new do |t| - t.spec_files = FileList['spec/**/*_spec.rb'] - t.spec_opts = %w(-fs --color) +begin + require 'spec/rake/spectask' +rescue LoadError + task(:spec) { $stderr.puts '`gem install rspec` to run specs' } +else + desc "Run specs" + Spec::Rake::SpecTask.new do |t| + t.spec_files = FileList['spec/**/*_spec.rb'] - FileList['spec/fixtures/**/*_spec.rb'] + t.spec_opts = %w(-fs --color) + end end - -Rake::GemPackageTask.new(spec) do |pkg| - pkg.gem_spec = spec +begin + require 'rake/gempackagetask' +rescue LoadError + task(:gem) { $stderr.puts '`gem install rake` to package gems' } +else + Rake::GemPackageTask.new(spec) do |pkg| + pkg.gem_spec = spec + end end desc "install the gem locally" task :install => [:package] do - sh %{sudo gem install pkg/#{GEM}-#{GEM_VERSION}} + sh %{gem install pkg/#{spec.name}-#{spec.version}} end desc "create a gemspec file" task :make_spec do - File.open("#{GEM}.gemspec", "w") do |file| + File.open("#{spec.name}.gemspec", "w") do |file| file.puts spec.to_ruby end -end
\ No newline at end of file +end diff --git a/railties/lib/vendor/bundler/bin/gem_bundler b/railties/lib/vendor/bundler/bin/gem_bundler deleted file mode 100755 index 7a8771efee..0000000000 --- a/railties/lib/vendor/bundler/bin/gem_bundler +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env ruby -require "optparse" -require "bundler" - -options = {} - -parser = OptionParser.new do |op| - op.banner = "Usage: gem_bundler [OPTIONS] [PATH]" - - op.on("-m", "--manifest MANIFEST") do |manifest| - options[:manifest] = manifest - end - - op.on_tail("-h", "--help", "Show this message") do - puts op - exit - end -end -parser.parse! - -options[:path] = ARGV.shift - -unless options[:path] - puts parser - puts %( - [PATH] must be specified - ) - exit -end - -unless options[:manifest] && File.exist?(options[:manifest]) - puts parser - puts %( - MANIFEST must be a valid manifest file - ) - exit -end - - -Bundler.run(options)
\ No newline at end of file diff --git a/railties/lib/vendor/bundler/lib/bundler.rb b/railties/lib/vendor/bundler/lib/bundler.rb index 4dcab20da9..1ede3517dd 100644 --- a/railties/lib/vendor/bundler/lib/bundler.rb +++ b/railties/lib/vendor/bundler/lib/bundler.rb @@ -1,24 +1,34 @@ +require 'pathname' require 'logger' require 'set' +require 'erb' # Required elements of rubygems require "rubygems/remote_fetcher" require "rubygems/installer" require "bundler/gem_bundle" -require "bundler/installer" +require "bundler/source" require "bundler/finder" -require "bundler/gem_specification" +require "bundler/gem_ext" require "bundler/resolver" -require "bundler/manifest" -require "bundler/dependency" -require "bundler/runtime" +require "bundler/environment" +require "bundler/dsl" require "bundler/cli" +require "bundler/repository" +require "bundler/dependency" module Bundler VERSION = "0.5.0" - def self.run(options = {}) - manifest = ManifestBuilder.load(options[:path], options[:manifest]) - manifest.install + class << self + attr_writer :logger + + def logger + @logger ||= begin + logger = Logger.new(STDOUT, Logger::INFO) + logger.formatter = proc {|_,_,_,msg| "#{msg}\n" } + logger + end + end end -end
\ No newline at end of file +end diff --git a/railties/lib/vendor/bundler/lib/bundler/cli.rb b/railties/lib/vendor/bundler/lib/bundler/cli.rb index ed49ef88f0..df9181fbc4 100644 --- a/railties/lib/vendor/bundler/lib/bundler/cli.rb +++ b/railties/lib/vendor/bundler/lib/bundler/cli.rb @@ -1,24 +1,44 @@ -module Bundler - module CLI +require "optparse" - def default_manifest - current = Pathname.new(Dir.pwd) +module Bundler + class CLI + def self.run(command, options = {}) + new(options).run(command) + rescue DefaultManifestNotFound => e + Bundler.logger.error "Could not find a Gemfile to use" + exit 2 + rescue InvalidEnvironmentName => e + Bundler.logger.error "Gemfile error: #{e.message}" + exit + rescue InvalidRepository => e + Bundler.logger.error e.message + exit + rescue VersionConflict => e + Bundler.logger.error e.message + exit + rescue GemNotFound => e + Bundler.logger.error e.message + exit + end - begin - manifest = current.join("Gemfile") - return manifest.to_s if File.exist?(manifest) - current = current.parent - end until current.root? - nil + def initialize(options) + @options = options + @manifest = Bundler::Environment.load(@options[:manifest]) end - module_function :default_manifest + def bundle + @manifest.install(@options[:update]) + end - def default_path - Pathname.new(File.dirname(default_manifest)).join("vendor").join("gems").to_s + def exec + @manifest.setup_environment + # w0t? + super(*@options[:args]) end - module_function :default_path + def run(command) + send(command) + end end -end
\ No newline at end of file +end diff --git a/railties/lib/vendor/bundler/lib/bundler/commands/bundle_command.rb b/railties/lib/vendor/bundler/lib/bundler/commands/bundle_command.rb new file mode 100644 index 0000000000..a1f9590f75 --- /dev/null +++ b/railties/lib/vendor/bundler/lib/bundler/commands/bundle_command.rb @@ -0,0 +1,31 @@ +class Gem::Commands::BundleCommand < Gem::Command + + def initialize + super('bundle', 'Create a gem bundle based on your Gemfile', {:manifest => nil, :update => false}) + + add_option('-m', '--manifest MANIFEST', "Specify the path to the manifest file") do |manifest, options| + options[:manifest] = manifest + end + + add_option('-u', '--update', "Force a remote check for newer gems") do + options[:update] = true + end + end + + def usage + "#{program_name}" + end + + def description # :nodoc: + <<-EOF +Bundle stuff + EOF + end + + def execute + # Prevent the bundler from getting required unless it is actually being used + require 'bundler' + Bundler::CLI.run(:bundle, options) + end + +end
\ No newline at end of file diff --git a/railties/lib/vendor/bundler/lib/bundler/commands/exec_command.rb b/railties/lib/vendor/bundler/lib/bundler/commands/exec_command.rb new file mode 100644 index 0000000000..228aa60619 --- /dev/null +++ b/railties/lib/vendor/bundler/lib/bundler/commands/exec_command.rb @@ -0,0 +1,31 @@ +class Gem::Commands::ExecCommand < Gem::Command + + def initialize + super('exec', 'Run a command in context of a gem bundle', {:manifest => nil}) + + add_option('-m', '--manifest MANIFEST', "Specify the path to the manifest file") do |manifest, options| + options[:manifest] = manifest + end + end + + def usage + "#{program_name} COMMAND" + end + + def arguments # :nodoc: + "COMMAND command to run in context of the gem bundle" + end + + def description # :nodoc: + <<-EOF.gsub(' ', '') + Run in context of a bundle + EOF + end + + def execute + # Prevent the bundler from getting required unless it is actually being used + require 'bundler' + Bundler::CLI.run(:exec, options) + end + +end
\ No newline at end of file diff --git a/railties/lib/vendor/bundler/lib/bundler/dependency.rb b/railties/lib/vendor/bundler/lib/bundler/dependency.rb index 739a7a117d..b627b58662 100644 --- a/railties/lib/vendor/bundler/lib/bundler/dependency.rb +++ b/railties/lib/vendor/bundler/lib/bundler/dependency.rb @@ -1,9 +1,10 @@ module Bundler - class Dependency + class InvalidEnvironmentName < StandardError; end + class Dependency attr_reader :name, :version, :require_as, :only, :except - def initialize(name, options = {}) + def initialize(name, options = {}, &block) options.each do |k, v| options[k.to_s] = v end @@ -11,8 +12,13 @@ module Bundler @name = name @version = options["version"] || ">= 0" @require_as = Array(options["require_as"] || name) - @only = Array(options["only"]).map {|e| e.to_s } if options["only"] - @except = Array(options["except"]).map {|e| e.to_s } if options["except"] + @only = options["only"] + @except = options["except"] + @block = block + + if (@only && @only.include?("rubygems")) || (@except && @except.include?("rubygems")) + raise InvalidEnvironmentName, "'rubygems' is not a valid environment name" + end end def in?(environment) @@ -27,9 +33,24 @@ module Bundler to_gem_dependency.to_s end + def require(environment) + return unless in?(environment) + + @require_as.each do |file| + super(file) + end + + @block.call if @block + end + def to_gem_dependency @gem_dep ||= Gem::Dependency.new(name, version) end + def ==(o) + [name, version, require_as, only, except] == + [o.name, o.version, o.require_as, o.only, o.except] + end + end -end
\ No newline at end of file +end diff --git a/railties/lib/vendor/bundler/lib/bundler/dsl.rb b/railties/lib/vendor/bundler/lib/bundler/dsl.rb new file mode 100644 index 0000000000..d9a86ee1fd --- /dev/null +++ b/railties/lib/vendor/bundler/lib/bundler/dsl.rb @@ -0,0 +1,109 @@ +module Bundler + class ManifestFileNotFound < StandardError; end + + class Dsl + def initialize(environment) + @environment = environment + @sources = Hash.new { |h,k| h[k] = {} } + end + + def bundle_path(path) + path = Pathname.new(path) + @environment.gem_path = (path.relative? ? + @environment.root.join(path) : path).expand_path + end + + def bin_path(path) + path = Pathname.new(path) + @environment.bindir = (path.relative? ? + @environment.root.join(path) : path).expand_path + end + + def disable_rubygems + @environment.rubygems = false + end + + def disable_system_gems + @environment.system_gems = false + end + + def source(source) + source = GemSource.new(:uri => source) + unless @environment.sources.include?(source) + @environment.add_source(source) + end + end + + def only(env) + old, @only = @only, _combine_onlys(env) + yield + @only = old + end + + def except(env) + old, @except = @except, _combine_excepts(env) + yield + @except = old + end + + def clear_sources + @environment.clear_sources + end + + def gem(name, *args) + options = args.last.is_a?(Hash) ? args.pop : {} + version = args.last + + options[:only] = _combine_onlys(options[:only] || options["only"]) + options[:except] = _combine_excepts(options[:except] || options["except"]) + + dep = Dependency.new(name, options.merge(:version => version)) + + # OMG REFACTORZ. KTHX + if vendored_at = options[:vendored_at] + vendored_at = Pathname.new(vendored_at) + vendored_at = @environment.filename.dirname.join(vendored_at) if vendored_at.relative? + + @sources[:directory][vendored_at.to_s] ||= begin + source = DirectorySource.new( + :name => name, + :version => version, + :location => vendored_at + ) + @environment.add_priority_source(source) + true + end + elsif git = options[:git] + @sources[:git][git] ||= begin + source = GitSource.new( + :name => name, + :version => version, + :uri => git, + :ref => options[:commit] || options[:tag], + :branch => options[:branch] + ) + @environment.add_priority_source(source) + true + end + end + + @environment.dependencies << dep + end + + private + + def _combine_onlys(only) + return @only unless only + only = [only].flatten.compact.uniq.map { |o| o.to_s } + only &= @only if @only + only + end + + def _combine_excepts(except) + return @except unless except + except = [except].flatten.compact.uniq.map { |o| o.to_s } + except |= @except if @except + except + end + end +end diff --git a/railties/lib/vendor/bundler/lib/bundler/environment.rb b/railties/lib/vendor/bundler/lib/bundler/environment.rb new file mode 100644 index 0000000000..f07a9e2c6f --- /dev/null +++ b/railties/lib/vendor/bundler/lib/bundler/environment.rb @@ -0,0 +1,111 @@ +require "rubygems/source_index" + +module Bundler + class DefaultManifestNotFound < StandardError; end + + class Environment + attr_reader :filename, :dependencies + attr_accessor :rubygems, :system_gems, :gem_path, :bindir + + def self.load(gemfile = nil) + gemfile = gemfile ? Pathname.new(gemfile) : default_manifest_file + + unless gemfile.file? + raise ManifestFileNotFound, "#{filename.inspect} does not exist" + end + + new(gemfile) + end + + def self.default_manifest_file + current = Pathname.new(Dir.pwd) + + until current.root? + filename = current.join("Gemfile") + return filename if filename.exist? + current = current.parent + end + + raise DefaultManifestNotFound + end + + def initialize(filename) #, sources, dependencies, bindir, path, rubygems, system_gems) + @filename = filename + @default_sources = [GemSource.new(:uri => "http://gems.rubyforge.org")] + @sources = [] + @priority_sources = [] + @dependencies = [] + @rubygems = true + @system_gems = true + + # Evaluate the Gemfile + builder = Dsl.new(self) + builder.instance_eval(File.read(filename)) + end + + def install(update = false) + begin + tmp_path = filename.dirname.join(".tmp") + FileUtils.mkdir_p(tmp_path) + sources.each { |s| s.tmp_path = tmp_path } + repository.install(gem_dependencies, sources, + :rubygems => rubygems, + :system_gems => system_gems, + :manifest => filename, + :update => update + ) + ensure + FileUtils.rm_rf(tmp_path) + end + Bundler.logger.info "Done." + end + + def setup_environment + unless system_gems + ENV["GEM_HOME"] = gem_path + ENV["GEM_PATH"] = gem_path + end + ENV["PATH"] = "#{bindir}:#{ENV["PATH"]}" + ENV["RUBYOPT"] = "-r#{gem_path}/environment #{ENV["RUBYOPT"]}" + end + + def root + filename.parent + end + + def gem_path + @gem_path ||= root.join("vendor", "gems") + end + + def bindir + @bindir ||= root.join("bin") + end + + def sources + @priority_sources + @sources + @default_sources + end + + def add_source(source) + @sources << source + end + + def add_priority_source(source) + @priority_sources << source + end + + def clear_sources + @sources.clear + @default_sources.clear + end + + private + + def repository + @repository ||= Repository.new(gem_path, bindir) + end + + def gem_dependencies + @gem_dependencies ||= dependencies.map { |d| d.to_gem_dependency } + end + end +end diff --git a/railties/lib/vendor/bundler/lib/bundler/finder.rb b/railties/lib/vendor/bundler/lib/bundler/finder.rb index 43ff370ae4..b77ca65709 100644 --- a/railties/lib/vendor/bundler/lib/bundler/finder.rb +++ b/railties/lib/vendor/bundler/lib/bundler/finder.rb @@ -1,42 +1,51 @@ module Bundler + # Finder behaves like a rubygems source index in that it responds + # to #search. It also resolves a list of dependencies finding the + # best possible configuration of gems that satisifes all requirements + # without causing any gem activation errors. class Finder - def initialize(*sources) - @results = {} - @index = Hash.new { |h,k| h[k] = {} } - sources.each { |source| fetch(source) } + # Takes an array of gem sources and fetches the full index of + # gems from each one. It then combines the indexes together keeping + # track of the original source so that any resolved gem can be + # fetched from the correct source. + # + # ==== Parameters + # *sources<String>:: URI pointing to the gem repository + def initialize(*sources) + @cache = {} + @index = {} + @sources = sources end - def resolve(*dependencies) - resolved = Resolver.resolve(dependencies, self) - resolved && GemBundle.new(resolved.all_specs) + # Searches for a gem that matches the dependency + # + # ==== Parameters + # dependency<Gem::Dependency>:: The gem dependency to search for + # + # ==== Returns + # [Gem::Specification]:: A collection of gem specifications + # matching the search + def search(dependency) + @cache[dependency.hash] ||= begin + find_by_name(dependency.name).select do |spec| + dependency =~ spec + end.sort_by {|s| s.version } + end end - def fetch(source) - deflated = Gem::RemoteFetcher.fetcher.fetch_path("#{source}/Marshal.4.8.Z") - inflated = Gem.inflate deflated + private - append(Marshal.load(inflated), source) - rescue Gem::RemoteFetcher::FetchError => e - raise ArgumentError, "#{source} is not a valid source: #{e.message}" - end - - def append(index, source) - index.gems.values.each do |spec| - next unless Gem::Platform.match(spec.platform) - spec.source = source - @index[spec.name][spec.version] ||= spec + def find_by_name(name) + matches = @index[name] ||= begin + versions = {} + @sources.reverse_each do |source| + versions.merge! source.specs[name] || {} + end + versions end - self + matches.values end - def search(dependency) - @results[dependency.hash] ||= begin - possibilities = @index[dependency.name].values - possibilities.select do |spec| - dependency =~ spec - end.sort_by {|s| s.version } - end - end end end
\ No newline at end of file diff --git a/railties/lib/vendor/bundler/lib/bundler/gem_bundle.rb b/railties/lib/vendor/bundler/lib/bundler/gem_bundle.rb index b749720fd9..80d7710683 100644 --- a/railties/lib/vendor/bundler/lib/bundler/gem_bundle.rb +++ b/railties/lib/vendor/bundler/lib/bundler/gem_bundle.rb @@ -1,22 +1,10 @@ module Bundler class GemBundle < Array - def download(directory) - FileUtils.mkdir_p(directory) - - current = Dir[File.join(directory, "cache", "*.gem*")] - - each do |spec| - cached = File.join(directory, "cache", "#{spec.full_name}.gem") - - unless File.file?(cached) - Gem::RemoteFetcher.fetcher.download(spec, spec.source, directory) - end - - current.delete(cached) + def download(repository) + sort_by {|s| s.full_name.downcase }.each do |spec| + spec.source.download(spec, repository) end - current.each { |file| File.delete(file) } - self end end diff --git a/railties/lib/vendor/bundler/lib/bundler/gem_ext.rb b/railties/lib/vendor/bundler/lib/bundler/gem_ext.rb new file mode 100644 index 0000000000..155ad04c7e --- /dev/null +++ b/railties/lib/vendor/bundler/lib/bundler/gem_ext.rb @@ -0,0 +1,25 @@ +module Gem + class Installer + def app_script_text(bin_file_name) + path = @gem_home + template = File.read(File.join(File.dirname(__FILE__), "templates", "app_script.erb")) + erb = ERB.new(template, nil, '-') + erb.result(binding) + end + end + + class Specification + attr_accessor :source + attr_accessor :location + + # Hack to fix github's strange marshal file + def specification_version + @specification_version && @specification_version.to_i + end + + alias full_gem_path_without_location full_gem_path + def full_gem_path + @location ? @location : full_gem_path_without_location + end + end +end diff --git a/railties/lib/vendor/bundler/lib/bundler/gem_specification.rb b/railties/lib/vendor/bundler/lib/bundler/gem_specification.rb deleted file mode 100644 index 680b61fd69..0000000000 --- a/railties/lib/vendor/bundler/lib/bundler/gem_specification.rb +++ /dev/null @@ -1,10 +0,0 @@ -module Gem - class Specification - attribute :source - - def source=(source) - @source = source.is_a?(URI) ? source : URI.parse(source) - raise ArgumentError, "The source must be an absolute URI" unless @source.absolute? - end - end -end
\ No newline at end of file diff --git a/railties/lib/vendor/bundler/lib/bundler/installer.rb b/railties/lib/vendor/bundler/lib/bundler/installer.rb deleted file mode 100644 index 581d9d3c8e..0000000000 --- a/railties/lib/vendor/bundler/lib/bundler/installer.rb +++ /dev/null @@ -1,44 +0,0 @@ -module Bundler - class Installer - def initialize(path) - if !File.directory?(path) - raise ArgumentError, "#{path} is not a directory" - elsif !File.directory?(File.join(path, "cache")) - raise ArgumentError, "#{path} is not a valid environment (it does not contain a cache directory)" - end - - @path = path - @gems = Dir[(File.join(path, "cache", "*.gem"))] - end - - def install(options = {}) - bin_dir = options[:bin_dir] ||= File.join(@path, "bin") - - specs = Dir[File.join(@path, "specifications", "*.gemspec")] - gems = Dir[File.join(@path, "gems", "*")] - - @gems.each do |gem| - name = File.basename(gem).gsub(/\.gem$/, '') - installed = specs.any? { |g| File.basename(g) == "#{name}.gemspec" } && - gems.any? { |g| File.basename(g) == name } - - unless installed - installer = Gem::Installer.new(gem, :install_dir => @path, - :ignore_dependencies => true, - :env_shebang => true, - :wrappers => true, - :bin_dir => bin_dir) - installer.install - end - - # remove this spec - specs.delete_if { |g| File.basename(g) == "#{name}.gemspec"} - gems.delete_if { |g| File.basename(g) == name } - end - - (specs + gems).each do |path| - FileUtils.rm_rf(path) - end - end - end -end
\ No newline at end of file diff --git a/railties/lib/vendor/bundler/lib/bundler/manifest.rb b/railties/lib/vendor/bundler/lib/bundler/manifest.rb deleted file mode 100644 index 847a41940d..0000000000 --- a/railties/lib/vendor/bundler/lib/bundler/manifest.rb +++ /dev/null @@ -1,130 +0,0 @@ -require "rubygems/source_index" -require "pathname" - -module Bundler - class VersionConflict < StandardError; end - - class Manifest - attr_reader :sources, :dependencies, :path - - def initialize(sources, dependencies, path) - sources.map! {|s| s.is_a?(URI) ? s : URI.parse(s) } - @sources, @dependencies, @path = sources, dependencies, Pathname.new(path) - end - - def fetch - return if all_gems_installed? - - finder = Finder.new(*sources) - unless bundle = finder.resolve(*gem_dependencies) - gems = @dependencies.map {|d| " #{d.to_s}" }.join("\n") - raise VersionConflict, "No compatible versions could be found for:\n#{gems}" - end - - bundle.download(@path) - end - - def install(options = {}) - fetch - installer = Installer.new(@path) - installer.install # options come here - create_load_paths_files(File.join(@path, "environments")) - create_fake_rubygems(File.join(@path, "environments")) - end - - def activate(environment = "default") - require File.join(@path, "environments", "#{environment}.rb") - end - - def require_all - dependencies.each do |dep| - dep.require_as.each {|file| require file } - end - end - - def gems_for(environment) - deps = dependencies.select { |d| d.in?(environment) } - deps.map! { |d| d.to_gem_dependency } - index = Gem::SourceIndex.from_gems_in(File.join(@path, "specifications")) - Resolver.resolve(deps, index).all_specs - end - - def environments - envs = dependencies.map {|dep| Array(dep.only) + Array(dep.except) }.flatten - envs << "default" - end - - private - - def gem_dependencies - @gem_dependencies ||= dependencies.map { |d| d.to_gem_dependency } - end - - def all_gems_installed? - gem_versions = {} - - Dir[File.join(@path, "cache", "*.gem")].each do |file| - file =~ /\/([^\/]+)-([\d\.]+)\.gem$/ - name, version = $1, $2 - gem_versions[name] = Gem::Version.new(version) - end - - gem_dependencies.all? do |dep| - gem_versions[dep.name] && - dep.version_requirements.satisfied_by?(gem_versions[dep.name]) - end - end - - def create_load_paths_files(path) - FileUtils.mkdir_p(path) - environments.each do |environment| - gem_specs = gems_for(environment) - File.open(File.join(path, "#{environment}.rb"), "w") do |file| - file.puts <<-RUBY_EVAL - module Bundler - def self.rubygems_required - #{create_gem_stubs(path, gem_specs)} - end - end - RUBY_EVAL - file.puts "$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__))" - load_paths_for_specs(gem_specs).each do |load_path| - file.puts "$LOAD_PATH.unshift #{load_path.inspect}" - end - end - end - end - - def create_gem_stubs(path, gem_specs) - gem_specs.map do |spec| - path = File.expand_path(File.join(path, '..', 'specifications', "#{spec.full_name}.gemspec")) - %{ - Gem.loaded_specs["#{spec.name}"] = eval(File.read("#{path}")) - } - end.join("\n") - end - - def create_fake_rubygems(path) - File.open(File.join(path, "rubygems.rb"), "w") do |file| - file.puts <<-RUBY_EVAL - $:.delete File.expand_path(File.dirname(__FILE__)) - load "rubygems.rb" - if defined?(Bundler) && Bundler.respond_to?(:rubygems_required) - Bundler.rubygems_required - end - RUBY_EVAL - end - end - - def load_paths_for_specs(specs) - load_paths = [] - specs.each do |spec| - load_paths << File.join(spec.full_gem_path, spec.bindir) if spec.bindir - spec.require_paths.each do |path| - load_paths << File.join(spec.full_gem_path, path) - end - end - load_paths - end - end -end
\ No newline at end of file diff --git a/railties/lib/vendor/bundler/lib/bundler/repository.rb b/railties/lib/vendor/bundler/lib/bundler/repository.rb new file mode 100644 index 0000000000..1a1dc7497d --- /dev/null +++ b/railties/lib/vendor/bundler/lib/bundler/repository.rb @@ -0,0 +1,151 @@ +require "bundler/repository/gem_repository" +require "bundler/repository/directory_repository" + +module Bundler + class InvalidRepository < StandardError ; end + + class Repository + attr_reader :path + + def initialize(path, bindir) + FileUtils.mkdir_p(path) + + @path = Pathname.new(path) + @bindir = Pathname.new(bindir) + + @repos = { + :gem => Gems.new(@path, @bindir), + :directory => Directory.new(@path.join("dirs"), @bindir) + } + end + + def install(dependencies, sources, options = {}) + if options[:update] || !satisfies?(dependencies) + fetch(dependencies, sources) + expand(options) + else + # Remove any gems that are still around if the Gemfile changed without + # requiring new gems to be download (e.g. a line in the Gemfile was + # removed) + cleanup(Resolver.resolve(dependencies, [source_index])) + end + configure(options) + sync + end + + def gems + gems = [] + each_repo do |repo| + gems.concat repo.gems + end + gems + end + + def satisfies?(dependencies) + index = source_index + dependencies.all? { |dep| index.search(dep).size > 0 } + end + + def source_index + index = Gem::SourceIndex.new + + each_repo do |repo| + index.gems.merge!(repo.source_index.gems) + end + + index + end + + def add_spec(type, spec) + @repos[type].add_spec(spec) + end + + def download_path_for(type) + @repos[type].download_path_for + end + + private + + def cleanup(bundle) + each_repo do |repo| + repo.cleanup(bundle) + end + end + + def each_repo + @repos.each do |k, repo| + yield repo + end + end + + def fetch(dependencies, sources) + bundle = Resolver.resolve(dependencies, sources) + # Cleanup here to remove any gems that could cause problem in the expansion + # phase + # + # TODO: Try to avoid double cleanup + cleanup(bundle) + bundle.download(self) + end + + def sync + glob = gems.map { |g| g.executables }.flatten.join(',') + + (Dir[@bindir.join("*")] - Dir[@bindir.join("{#{glob}}")]).each do |file| + Bundler.logger.info "Deleting bin file: #{File.basename(file)}" + FileUtils.rm_rf(file) + end + end + + def expand(options) + each_repo do |repo| + repo.expand(options) + end + end + + def configure(options) + generate_environment(options) + end + + def generate_environment(options) + FileUtils.mkdir_p(path) + + specs = gems + load_paths = load_paths_for_specs(specs) + bindir = @bindir.relative_path_from(path).to_s + filename = options[:manifest].relative_path_from(path).to_s + spec_files = specs.inject({}) do |hash, spec| + relative = spec.loaded_from.relative_path_from(@path).to_s + hash.merge!(spec.name => relative) + end + + File.open(path.join("environment.rb"), "w") do |file| + template = File.read(File.join(File.dirname(__FILE__), "templates", "environment.erb")) + erb = ERB.new(template, nil, '-') + file.puts erb.result(binding) + end + end + + def load_paths_for_specs(specs) + load_paths = [] + specs.each do |spec| + gem_path = Pathname.new(spec.full_gem_path) + if spec.bindir + load_paths << gem_path.join(spec.bindir).relative_path_from(@path).to_s + end + spec.require_paths.each do |path| + load_paths << gem_path.join(path).relative_path_from(@path).to_s + end + end + load_paths + end + + def require_code(file, dep) + constraint = case + when dep.only then %{ if #{dep.only.inspect}.include?(env)} + when dep.except then %{ unless #{dep.except.inspect}.include?(env)} + end + "require #{file.inspect}#{constraint}" + end + end +end
\ No newline at end of file diff --git a/railties/lib/vendor/bundler/lib/bundler/repository/directory_repository.rb b/railties/lib/vendor/bundler/lib/bundler/repository/directory_repository.rb new file mode 100644 index 0000000000..e97dd38dd5 --- /dev/null +++ b/railties/lib/vendor/bundler/lib/bundler/repository/directory_repository.rb @@ -0,0 +1,46 @@ +module Bundler + class Repository + class Directory + attr_reader :path, :bindir + + def initialize(path, bindir) + @path = path + @bindir = bindir + + FileUtils.mkdir_p(path.to_s) + end + + def source_index + index = Gem::SourceIndex.from_gems_in(@path.join("specifications")) + index.each { |n, spec| spec.loaded_from = @path.join("specifications", "#{spec.full_name}.gemspec") } + index + end + + def gems + source_index.gems.values + end + + def add_spec(spec) + destination = path.join('specifications') + destination.mkdir unless destination.exist? + + File.open(destination.join("#{spec.full_name}.gemspec"), 'w') do |f| + f.puts spec.to_ruby + end + end + + def download_path_for + @path.join("dirs") + end + + # Checks whether a gem is installed + def expand(options) + # raise NotImplementedError + end + + def cleanup(gems) + # raise NotImplementedError + end + end + end +end
\ No newline at end of file diff --git a/railties/lib/vendor/bundler/lib/bundler/repository/gem_repository.rb b/railties/lib/vendor/bundler/lib/bundler/repository/gem_repository.rb new file mode 100644 index 0000000000..90de49d83d --- /dev/null +++ b/railties/lib/vendor/bundler/lib/bundler/repository/gem_repository.rb @@ -0,0 +1,108 @@ +module Bundler + class Repository + class Gems + attr_reader :path, :bindir + + def initialize(path, bindir) + @path = path + @bindir = bindir + end + + # Returns the source index for all gems installed in the + # repository + def source_index + index = Gem::SourceIndex.from_gems_in(@path.join("specifications")) + index.each { |n, spec| spec.loaded_from = @path.join("specifications", "#{spec.full_name}.gemspec") } + index + end + + def gems + source_index.gems.values + end + + # Checks whether a gem is installed + def expand(options) + cached_gems.each do |name, version| + unless installed?(name, version) + install_cached_gem(name, version, options) + end + end + end + + def cleanup(gems) + glob = gems.map { |g| g.full_name }.join(',') + base = path.join("{cache,specifications,gems}") + + (Dir[base.join("*")] - Dir[base.join("{#{glob}}{.gemspec,.gem,}")]).each do |file| + if File.basename(file) =~ /\.gem$/ + name = File.basename(file, '.gem') + Bundler.logger.info "Deleting gem: #{name}" + end + FileUtils.rm_rf(file) + end + end + + def add_spec(spec) + raise NotImplementedError + end + + def download_path_for + path + end + + private + + def cache_path + @path.join("cache") + end + + def cache_files + Dir[cache_path.join("*.gem")] + end + + def cached_gems + cache_files.map do |f| + full_name = File.basename(f).gsub(/\.gem$/, '') + full_name.split(/-(?=[^-]+$)/) + end + end + + def spec_path + @path.join("specifications") + end + + def spec_files + Dir[spec_path.join("*.gemspec")] + end + + def gem_path + @path.join("gems") + end + + def gem_paths + Dir[gem_path.join("*")] + end + + def installed?(name, version) + spec_files.any? { |g| File.basename(g) == "#{name}-#{version}.gemspec" } && + gem_paths.any? { |g| File.basename(g) == "#{name}-#{version}" } + end + + def install_cached_gem(name, version, options = {}) + cached_gem = cache_path.join("#{name}-#{version}.gem") + # TODO: Add a warning if cached_gem is not a file + if cached_gem.file? + Bundler.logger.info "Installing #{name}-#{version}.gem" + installer = Gem::Installer.new(cached_gem.to_s, options.merge( + :install_dir => @path, + :ignore_dependencies => true, + :env_shebang => true, + :wrappers => true, + :bin_dir => @bindir + )) + installer.install + end + end + end + end +end
\ No newline at end of file diff --git a/railties/lib/vendor/bundler/lib/bundler/resolver.rb b/railties/lib/vendor/bundler/lib/bundler/resolver.rb index 1ec89e53c4..2a6a6371c2 100644 --- a/railties/lib/vendor/bundler/lib/bundler/resolver.rb +++ b/railties/lib/vendor/bundler/lib/bundler/resolver.rb @@ -1,19 +1,189 @@ -require 'bundler/resolver/inspect' -require 'bundler/resolver/search' -require 'bundler/resolver/engine' -require 'bundler/resolver/stack' -require 'bundler/resolver/state' +# This is the latest iteration of the gem dependency resolving algorithm. As of now, +# it can resolve (as a success of failure) any set of gem dependencies we throw at it +# in a reasonable amount of time. The most iterations I've seen it take is about 150. +# The actual implementation of the algorithm is not as good as it could be yet, but that +# can come later. + +# Extending Gem classes to add necessary tracking information +module Gem + class Dependency + def required_by + @required_by ||= [] + end + end + class Specification + def required_by + @required_by ||= [] + end + end +end module Bundler - module Resolver - def self.resolve(deps, source_index = Gem.source_index, logger = nil) - unless logger - logger = Logger.new($stderr) - logger.datetime_format = "" - logger.level = ENV["GEM_RESOLVER_DEBUG"] ? Logger::DEBUG : Logger::ERROR + class GemNotFound < StandardError; end + class VersionConflict < StandardError; end + + class Resolver + + attr_reader :errors + + # Figures out the best possible configuration of gems that satisfies + # the list of passed dependencies and any child dependencies without + # causing any gem activation errors. + # + # ==== Parameters + # *dependencies<Gem::Dependency>:: The list of dependencies to resolve + # + # ==== Returns + # <GemBundle>,nil:: If the list of dependencies can be resolved, a + # collection of gemspecs is returned. Otherwise, nil is returned. + def self.resolve(requirements, sources) + Bundler.logger.info "Calculating dependencies..." + + resolver = new(sources) + result = catch(:success) do + resolver.resolve(requirements, {}) + output = resolver.errors.inject("") do |o, (conflict, (origin, requirement))| + o << " Conflict on: #{conflict.inspect}:\n" + o << " * #{conflict} (#{origin.version}) activated by #{origin.required_by.first}\n" + o << " * #{requirement} required by #{requirement.required_by.first}\n" + o << " All possible versions of origin requirements conflict." + end + raise VersionConflict, "No compatible versions could be found for required dependencies:\n #{output}" + nil + end + result && GemBundle.new(result.values) + end + + def initialize(sources) + @errors = {} + @stack = [] + @specs = Hash.new { |h,k| h[k] = {} } + @cache = {} + @index = {} + + sources.reverse_each do |source| + source.gems.values.each do |spec| + # TMP HAX FOR OPTZ + spec.source = source + next unless Gem::Platform.match(spec.platform) + @specs[spec.name][spec.version] = spec + end + end + end + + def resolve(reqs, activated) + # If the requirements are empty, then we are in a success state. Aka, all + # gem dependencies have been resolved. + throw :success, activated if reqs.empty? + + # Sort requirements so that the ones that are easiest to resolve are first. + # Easiest to resolve is defined by: Is this gem already activated? Otherwise, + # check the number of child dependencies this requirement has. + reqs = reqs.sort_by do |req| + activated[req.name] ? 0 : search(req).size + end + + activated = activated.dup + # Pull off the first requirement so that we can resolve it + current = reqs.shift + + # Check if the gem has already been activated, if it has, we will make sure + # that the currently activated gem satisfies the requirement. + if existing = activated[current.name] + if current.version_requirements.satisfied_by?(existing.version) + @errors.delete(existing.name) + # Since the current requirement is satisfied, we can continue resolving + # the remaining requirements. + resolve(reqs, activated) + else + @errors[existing.name] = [existing, current] + # Since the current requirement conflicts with an activated gem, we need + # to backtrack to the current requirement's parent and try another version + # of it (maybe the current requirement won't be present anymore). If the + # current requirement is a root level requirement, we need to jump back to + # where the conflicting gem was activated. + parent = current.required_by.last || existing.required_by.last + # We track the spot where the current gem was activated because we need + # to keep a list of every spot a failure happened. + throw parent.name, existing.required_by.last.name + end + else + # There are no activated gems for the current requirement, so we are going + # to find all gems that match the current requirement and try them in decending + # order. We also need to keep a set of all conflicts that happen while trying + # this gem. This is so that if no versions work, we can figure out the best + # place to backtrack to. + conflicts = Set.new + + # Fetch all gem versions matching the requirement + # + # TODO: Warn / error when no matching versions are found. + matching_versions = search(current) + + if matching_versions.empty? + if current.required_by.empty? + raise GemNotFound, "Could not find gem '#{current}' in any of the sources" + end + Bundler.logger.warn "Could not find gem '#{current}' (required by '#{current.required_by.last}') in any of the sources" + end + + matching_versions.reverse_each do |spec| + conflict = resolve_requirement(spec, current, reqs.dup, activated.dup) + conflicts << conflict if conflict + end + # If the current requirement is a root level gem and we have conflicts, we + # can figure out the best spot to backtrack to. + if current.required_by.empty? && !conflicts.empty? + # Check the current "catch" stack for the first one that is included in the + # conflicts set. That is where the parent of the conflicting gem was required. + # By jumping back to this spot, we can try other version of the parent of + # the conflicting gem, hopefully finding a combination that activates correctly. + @stack.reverse_each do |savepoint| + if conflicts.include?(savepoint) + throw savepoint + end + end + end + end + end + + def resolve_requirement(spec, requirement, reqs, activated) + # We are going to try activating the spec. We need to keep track of stack of + # requirements that got us to the point of activating this gem. + spec.required_by.replace requirement.required_by + spec.required_by << requirement + + activated[spec.name] = spec + + # Now, we have to loop through all child dependencies and add them to our + # array of requirements. + spec.dependencies.each do |dep| + next if dep.type == :development + dep.required_by << requirement + reqs << dep end - Engine.resolve(deps, source_index, logger) + # We create a savepoint and mark it by the name of the requirement that caused + # the gem to be activated. If the activated gem ever conflicts, we are able to + # jump back to this point and try another version of the gem. + length = @stack.length + @stack << requirement.name + retval = catch(requirement.name) do + resolve(reqs, activated) + end + # Since we're doing a lot of throw / catches. A push does not necessarily match + # up to a pop. So, we simply slice the stack back to what it was before the catch + # block. + @stack.slice!(length..-1) + retval + end + + def search(dependency) + @cache[dependency.hash] ||= begin + @specs[dependency.name].values.select do |spec| + dependency =~ spec + end.sort_by {|s| s.version } + end end end end
\ No newline at end of file diff --git a/railties/lib/vendor/bundler/lib/bundler/resolver/builders.rb b/railties/lib/vendor/bundler/lib/bundler/resolver/builders.rb deleted file mode 100644 index 2b7b48211c..0000000000 --- a/railties/lib/vendor/bundler/lib/bundler/resolver/builders.rb +++ /dev/null @@ -1,61 +0,0 @@ -module Bundler - module Resolver - module Builders - def build_index(&block) - index = Gem::SourceIndex.new - IndexBuilder.run(index, &block) if block_given? - index - end - - def build_spec(name, version, &block) - spec = Gem::Specification.new - spec.instance_variable_set(:@name, name) - spec.instance_variable_set(:@version, Gem::Version.new(version)) - DepBuilder.run(spec, &block) if block_given? - spec - end - - def build_dep(name, requirements, type = :runtime) - Gem::Dependency.new(name, requirements, type) - end - - class IndexBuilder - include Builders - - def self.run(index, &block) - new(index).run(&block) - end - - def initialize(index) - @index = index - end - - def run(&block) - instance_eval(&block) - end - - def add_spec(*args, &block) - @index.add_spec(build_spec(*args, &block)) - end - end - - class DepBuilder - def self.run(spec, &block) - new(spec).run(&block) - end - - def initialize(spec) - @spec = spec - end - - def run(&block) - instance_eval(&block) - end - - def runtime(name, requirements) - @spec.add_runtime_dependency(name, requirements) - end - end - end - end -end
\ No newline at end of file diff --git a/railties/lib/vendor/bundler/lib/bundler/resolver/engine.rb b/railties/lib/vendor/bundler/lib/bundler/resolver/engine.rb deleted file mode 100644 index 475ba516ff..0000000000 --- a/railties/lib/vendor/bundler/lib/bundler/resolver/engine.rb +++ /dev/null @@ -1,38 +0,0 @@ -module Bundler - module Resolver - class ClosedSet < Set - end - - class Engine - include Search, Inspect - - def self.resolve(deps, source_index, logger) - new(deps, source_index, logger).resolve - end - - def initialize(deps, source_index, logger) - @deps, @source_index, @logger = deps, source_index, logger - logger.debug "searching for #{gem_resolver_inspect(@deps)}" - end - attr_reader :deps, :source_index, :logger, :solution - - def resolve - state = State.initial(self, [], Stack.new, Stack.new([[[], @deps.dup]])) - if solution = search(state) - logger.info "got the solution with #{solution.all_specs.size} specs" - solution.dump(Logger::INFO) - solution - end - end - - def open - @open ||= [] - end - - def closed - @closed ||= ClosedSet.new - end - end - end - -end
\ No newline at end of file diff --git a/railties/lib/vendor/bundler/lib/bundler/resolver/inspect.rb b/railties/lib/vendor/bundler/lib/bundler/resolver/inspect.rb deleted file mode 100644 index 59640aa5f3..0000000000 --- a/railties/lib/vendor/bundler/lib/bundler/resolver/inspect.rb +++ /dev/null @@ -1,24 +0,0 @@ -module Bundler - module Resolver - module Inspect - def gem_resolver_inspect(o) - case o - when Gem::Specification - "#<Spec: #{o.full_name}>" - when Array - '[' + o.map {|x| gem_resolver_inspect(x)}.join(", ") + ']' - when Set - gem_resolver_inspect(o.to_a) - when Hash - '{' + o.map {|k,v| "#{gem_resolver_inspect(k)} => #{gem_resolver_inspect(v)}"}.join(", ") + '}' - when Stack - o.gem_resolver_inspect - else - o.inspect - end - end - - module_function :gem_resolver_inspect - end - end -end
\ No newline at end of file diff --git a/railties/lib/vendor/bundler/lib/bundler/resolver/search.rb b/railties/lib/vendor/bundler/lib/bundler/resolver/search.rb deleted file mode 100644 index 34102ff04c..0000000000 --- a/railties/lib/vendor/bundler/lib/bundler/resolver/search.rb +++ /dev/null @@ -1,71 +0,0 @@ -module Bundler - module Resolver - module Search - def search(initial, max_depth = (1.0 / 0.0)) - if initial.goal_met? - return initial - end - - open << initial - - while open.any? - current = open.pop - closed << current - - new = [] - current.each_possibility do |attempt| - unless closed.include?(attempt) - if attempt.goal_met? - return attempt - elsif attempt.depth < max_depth - new << attempt - end - end - end - new.reverse.each do |state| - open << state - end - end - - nil - end - - def open - raise "implement #open in #{self.class}" - end - - def closed - raise "implement #closed in #{self.class}" - end - - module Node - def self.included(base) - base.extend(ClassMethods) - end - - module ClassMethods - def initial(*data) - new(0, *data) - end - end - - def initialize(depth) - @depth = depth - end - attr_reader :depth - - def child(*data) - self.class.new(@depth + 1, *data) - end - - def each_possibility - raise "implement #each_possibility on #{self.class}" - end - - def goal_met? - raise "implement #goal_met? on #{self.class}" - end - end - end - end -end
\ No newline at end of file diff --git a/railties/lib/vendor/bundler/lib/bundler/resolver/stack.rb b/railties/lib/vendor/bundler/lib/bundler/resolver/stack.rb deleted file mode 100644 index 6e1ac67e1f..0000000000 --- a/railties/lib/vendor/bundler/lib/bundler/resolver/stack.rb +++ /dev/null @@ -1,72 +0,0 @@ -module Bundler - module Resolver - class Stack - def initialize(initial = []) - @data = [] - initial.each do |(path,value)| - self[path] = value - end - end - - def last - @data.last - end - - def []=(path, value) - raise ArgumentError, "#{path.inspect} already has a value" if key?(path) - @data << [path.dup, value] - end - - def [](path) - if key?(path) - _, value = @data.find do |(k,v)| - k == path - end - value - else - raise "No value for #{path.inspect}" - end - end - - def key?(path) - @data.any? do |(k,v)| - k == path - end - end - - def each - @data.each do |(k,v)| - yield k, v - end - end - - def map - @data.map do |(k,v)| - yield k, v - end - end - - def each_value - @data.each do |(k,v)| - yield v - end - end - - def dup - self.class.new(@data.dup) - end - - def to_s - @data.to_s - end - - def inspect - @data.inspect - end - - def gem_resolver_inspect - Inspect.gem_resolver_inspect(@data) - end - end - end -end
\ No newline at end of file diff --git a/railties/lib/vendor/bundler/lib/bundler/resolver/state.rb b/railties/lib/vendor/bundler/lib/bundler/resolver/state.rb deleted file mode 100644 index f13ecbbee7..0000000000 --- a/railties/lib/vendor/bundler/lib/bundler/resolver/state.rb +++ /dev/null @@ -1,172 +0,0 @@ -module Bundler - module Resolver - class State - include Search::Node, Inspect - - def initialize(depth, engine, path, spec_stack, dep_stack) - super(depth) - @engine, @path, @spec_stack, @dep_stack = engine, path, spec_stack, dep_stack - end - attr_reader :path - - def logger - @engine.logger - end - - def goal_met? - logger.info "checking if goal is met" - dump - no_duplicates? - all_deps.all? do |dep| - dependency_satisfied?(dep) - end - end - - def no_duplicates? - names = [] - all_specs.each do |s| - if names.include?(s.name) - raise "somehow got duplicates for #{s.name}" - end - names << s.name - end - end - - def dependency_satisfied?(dep) - all_specs.any? do |spec| - spec.satisfies_requirement?(dep) - end - end - - def each_possibility(&block) - index, dep = remaining_deps.first - if dep - logger.warn "working on #{dep} for #{spec_name}" - handle_dep(index, dep, &block) - else - logger.warn "no dependencies left for #{spec_name}" - jump_to_parent(&block) - end - end - - def handle_dep(index, dep) - specs = @engine.source_index.search(dep) - - specs.reverse.each do |s| - logger.info "attempting with spec: #{s.full_name}" - new_path = @path + [index] - new_spec_stack = @spec_stack.dup - new_dep_stack = @dep_stack.dup - - new_spec_stack[new_path] = s - new_dep_stack[new_path] = s.runtime_dependencies.sort_by do |dep| - @engine.source_index.search(dep).size - end - yield child(@engine, new_path, new_spec_stack, new_dep_stack) - end - end - - def jump_to_parent - if @path.empty? - dump - logger.warn "at the end" - return - end - - logger.info "jumping to parent for #{spec_name}" - new_path = @path[0..-2] - new_spec_stack = @spec_stack.dup - new_dep_stack = @dep_stack.dup - - yield child(@engine, new_path, new_spec_stack, new_dep_stack) - end - - def remaining_deps - remaining_deps_for(@path) - end - - def remaining_deps_for(path) - no_duplicates? - remaining = [] - @dep_stack[path].each_with_index do |dep,i| - remaining << [i, dep] unless all_specs.find {|s| s.name == dep.name} - end - remaining - end - - def deps - @dep_stack[@path] - end - - def spec - @spec_stack[@path] - end - - def spec_name - @path.empty? ? "<top>" : spec.full_name - end - - def all_deps - all_deps = Set.new - @dep_stack.each_value do |deps| - all_deps.merge(deps) - end - all_deps.to_a - end - - def all_specs - @spec_stack.map do |path,spec| - spec - end - end - - def dump(level = Logger::DEBUG) - logger.add level, "v" * 80 - logger.add level, "path: #{@path.inspect}" - logger.add level, "deps: (#{deps.size})" - deps.map do |dep| - logger.add level, gem_resolver_inspect(dep) - end - logger.add level, "remaining_deps: (#{remaining_deps.size})" - remaining_deps.each do |dep| - logger.add level, gem_resolver_inspect(dep) - end - logger.add level, "dep_stack: " - @dep_stack.each do |path,deps| - logger.add level, "#{path.inspect} (#{deps.size})" - deps.each do |dep| - logger.add level, "-> #{gem_resolver_inspect(dep)}" - end - end - logger.add level, "spec_stack: " - @spec_stack.each do |path,spec| - logger.add level, "#{path.inspect}: #{gem_resolver_inspect(spec)}" - end - logger.add level, "^" * 80 - end - - def to_dot - io = StringIO.new - io.puts 'digraph deps {' - io.puts ' fontname = "Courier";' - io.puts ' mincross = 4.0;' - io.puts ' ratio = "auto";' - dump_to_dot(io, "<top>", []) - io.puts '}' - io.string - end - - def dump_to_dot(io, name, path) - @dep_stack[path].each_with_index do |dep,i| - new_path = path + [i] - spec_name = all_specs.find {|x| x.name == dep.name}.full_name - io.puts ' "%s" -> "%s";' % [name, dep.to_s] - io.puts ' "%s" -> "%s";' % [dep.to_s, spec_name] - if @spec_stack.key?(new_path) - dump_to_dot(io, spec_name, new_path) - end - end - end - end - end -end
\ No newline at end of file diff --git a/railties/lib/vendor/bundler/lib/bundler/runtime.rb b/railties/lib/vendor/bundler/lib/bundler/runtime.rb index 2376deef28..27e0254966 100644 --- a/railties/lib/vendor/bundler/lib/bundler/runtime.rb +++ b/railties/lib/vendor/bundler/lib/bundler/runtime.rb @@ -1,39 +1,2 @@ -module Bundler - class ManifestBuilder - - attr_reader :sources - - def self.build(path, string) - builder = new(path) - builder.instance_eval(string) - builder.to_manifest - end - - def self.load(path, file) - string = File.read(file) - build(path, string) - end - - def initialize(path) - @path = path - @sources = %w(http://gems.rubyforge.org) - @dependencies = [] - end - - def to_manifest - Manifest.new(@sources, @dependencies, @path) - end - - def source(source) - @sources << source - end - - def gem(name, *args) - options = args.last.is_a?(Hash) ? args.pop : {} - version = args.last - - @dependencies << Dependency.new(name, options.merge(:version => version)) - end - - end -end
\ No newline at end of file +require File.join(File.dirname(__FILE__), "runtime", "dsl") +require File.join(File.dirname(__FILE__), "runtime", "dependency")
\ No newline at end of file diff --git a/railties/lib/vendor/bundler/lib/bundler/source.rb b/railties/lib/vendor/bundler/lib/bundler/source.rb new file mode 100644 index 0000000000..37828ca316 --- /dev/null +++ b/railties/lib/vendor/bundler/lib/bundler/source.rb @@ -0,0 +1,150 @@ +module Bundler + # Represents a source of rubygems. Initially, this is only gem repositories, but + # eventually, this will be git, svn, HTTP + class Source + attr_accessor :tmp_path + end + + class GemSource < Source + attr_reader :uri + + def initialize(options) + @uri = options[:uri] + @uri = URI.parse(@uri) unless @uri.is_a?(URI) + raise ArgumentError, "The source must be an absolute URI" unless @uri.absolute? + end + + def gems + @specs ||= fetch_specs + end + + def ==(other) + uri == other.uri + end + + def to_s + @uri.to_s + end + + class RubygemsRetardation < StandardError; end + + def download(spec, repository) + Bundler.logger.info "Downloading #{spec.full_name}.gem" + + destination = repository.download_path_for(:gem) + + unless destination.writable? + raise RubygemsRetardation + end + + Gem::RemoteFetcher.fetcher.download(spec, uri, repository.download_path_for(:gem)) + end + + private + + def fetch_specs + Bundler.logger.info "Updating source: #{to_s}" + + deflated = Gem::RemoteFetcher.fetcher.fetch_path("#{uri}/Marshal.4.8.Z") + inflated = Gem.inflate deflated + + index = Marshal.load(inflated) + index.gems + rescue Gem::RemoteFetcher::FetchError => e + raise ArgumentError, "#{to_s} is not a valid source: #{e.message}" + end + end + + class DirectorySource < Source + def initialize(options) + @name = options[:name] + @version = options[:version] + @location = options[:location] + @require_paths = options[:require_paths] || %w(lib) + end + + def gems + @gems ||= begin + specs = {} + + # Find any gemspec files in the directory and load those specs + Dir[@location.join('**', '*.gemspec')].each do |file| + path = Pathname.new(file).relative_path_from(@location).dirname + spec = eval(File.read(file)) + spec.require_paths.map! { |p| path.join(p) } + specs[spec.full_name] = spec + end + + # If a gemspec for the dependency was not found, add it to the list + if specs.keys.grep(/^#{Regexp.escape(@name)}/).empty? + case + when @version.nil? + raise ArgumentError, "If you use :at, you must specify the gem" \ + "and version you wish to stand in for" + when !Gem::Version.correct?(@version) + raise ArgumentError, "If you use :at, you must specify a gem and" \ + "version. You specified #{@version} for the version" + end + + default = Gem::Specification.new do |s| + s.name = @name + s.version = Gem::Version.new(@version) if @version + end + specs[default.full_name] = default + end + + specs + end + end + + def ==(other) + # TMP HAX + other.is_a?(DirectorySource) + end + + def to_s + "#{@name} (#{@version}) Located at: '#{@location}'" + end + + def download(spec, repository) + spec.require_paths.map! { |p| File.join(@location, p) } + repository.add_spec(:directory, spec) + end + end + + class GitSource < DirectorySource + def initialize(options) + super + @uri = options[:uri] + @ref = options[:ref] + @branch = options[:branch] + end + + def gems + FileUtils.mkdir_p(tmp_path.join("gitz")) + + # TMP HAX to get the *.gemspec reading to work + @location = tmp_path.join("gitz", @name) + + Bundler.logger.info "Cloning git repository at: #{@uri}" + `git clone #{@uri} #{@location} --no-hardlinks` + + if @ref + Dir.chdir(@location) { `git checkout #{@ref}` } + elsif @branch && @branch != "master" + Dir.chdir(@location) { `git checkout origin/#{@branch}` } + end + super + end + + def download(spec, repository) + dest = repository.download_path_for(:directory).join(@name) + spec.require_paths.map! { |p| File.join(dest, p) } + repository.add_spec(:directory, spec) + if spec.name == @name + FileUtils.mkdir_p(dest.dirname) + FileUtils.mv(tmp_path.join("gitz", spec.name), dest) + end + end + end +end
\ No newline at end of file diff --git a/railties/lib/vendor/bundler/lib/bundler/templates/app_script.erb b/railties/lib/vendor/bundler/lib/bundler/templates/app_script.erb new file mode 100644 index 0000000000..3e47a53ca8 --- /dev/null +++ b/railties/lib/vendor/bundler/lib/bundler/templates/app_script.erb @@ -0,0 +1,3 @@ +<%= shebang bin_file_name %> +require File.join(File.dirname(__FILE__), "<%= path.join("environment").relative_path_from(Pathname.new(bin_dir)) %>") +load File.join(File.dirname(__FILE__), "<%= path.join("gems", @spec.full_name, @spec.bindir, bin_file_name).relative_path_from(Pathname.new(bin_dir)) %>")
\ No newline at end of file diff --git a/railties/lib/vendor/bundler/lib/bundler/templates/environment.erb b/railties/lib/vendor/bundler/lib/bundler/templates/environment.erb new file mode 100644 index 0000000000..21f3de8854 --- /dev/null +++ b/railties/lib/vendor/bundler/lib/bundler/templates/environment.erb @@ -0,0 +1,127 @@ +# DO NOT MODIFY THIS FILE +module Bundler + dir = File.dirname(__FILE__) + +<% unless options[:system_gems] -%> + ENV["GEM_HOME"] = dir + ENV["GEM_PATH"] = dir +<% end -%> + ENV["PATH"] = "#{dir}/<%= bindir %>:#{ENV["PATH"]}" + ENV["RUBYOPT"] = "-r#{__FILE__} #{ENV["RUBYOPT"]}" + +<% load_paths.each do |load_path| -%> + $LOAD_PATH.unshift File.expand_path("#{dir}/<%= load_path %>") +<% end -%> + + @gemfile = "#{dir}/<%= filename %>" + +<% if options[:rubygems] -%> + require "rubygems" + + @bundled_specs = {} +<% spec_files.each do |name, path| -%> + @bundled_specs["<%= name %>"] = eval(File.read("#{dir}/<%= path %>")) + @bundled_specs["<%= name %>"].loaded_from = "#{dir}/<%= path %>" +<% end -%> + + def self.add_specs_to_loaded_specs + Gem.loaded_specs.merge! @bundled_specs + end + + def self.add_specs_to_index + @bundled_specs.each do |name, spec| + Gem.source_index.add_spec spec + end + end + + add_specs_to_loaded_specs + add_specs_to_index +<% end -%> + + def self.require_env(env = nil) + context = Class.new do + def initialize(env) @env = env && env.to_s ; end + def method_missing(*) ; end + def only(env) + old, @only = @only, _combine_onlys(env) + yield + @only = old + end + def except(env) + old, @except = @except, _combine_excepts(env) + yield + @except = old + end + def gem(name, *args) + opt = args.last || {} + only = _combine_onlys(opt[:only] || opt["only"]) + except = _combine_excepts(opt[:except] || opt["except"]) + files = opt[:require_as] || opt["require_as"] || name + + return unless !only || only.any? {|e| e == @env } + return if except && except.any? {|e| e == @env } + + files.each { |f| require f } + yield if block_given? + true + end + private + def _combine_onlys(only) + return @only unless only + only = [only].flatten.compact.uniq.map { |o| o.to_s } + only &= @only if @only + only + end + def _combine_excepts(except) + return @except unless except + except = [except].flatten.compact.uniq.map { |o| o.to_s } + except |= @except if @except + except + end + end + context.new(env && env.to_s).instance_eval(File.read(@gemfile)) + end +end + +<% if options[:rubygems] -%> +module Gem + def source_index.refresh! + super + Bundler.add_specs_to_index + end +end +<% else -%> +$" << "rubygems.rb" + +module Kernel + def gem(*) + # Silently ignore calls to gem, since, in theory, everything + # is activated correctly already. + end +end + +# Define all the Gem errors for gems that reference them. +module Gem + def self.ruby ; <%= Gem.ruby.inspect %> ; end + class LoadError < ::LoadError; end + class Exception < RuntimeError; end + class CommandLineError < Exception; end + class DependencyError < Exception; end + class DependencyRemovalException < Exception; end + class GemNotInHomeException < Exception ; end + class DocumentError < Exception; end + class EndOfYAMLException < Exception; end + class FilePermissionError < Exception; end + class FormatException < Exception; end + class GemNotFoundException < Exception; end + class InstallError < Exception; end + class InvalidSpecificationException < Exception; end + class OperationNotSupportedError < Exception; end + class RemoteError < Exception; end + class RemoteInstallationCancelled < Exception; end + class RemoteInstallationSkipped < Exception; end + class RemoteSourceException < Exception; end + class VerificationError < Exception; end + class SystemExitException < SystemExit; end +end +<% end -%>
\ No newline at end of file diff --git a/railties/rails.gemspec b/railties/rails.gemspec new file mode 100644 index 0000000000..67893e4347 --- /dev/null +++ b/railties/rails.gemspec @@ -0,0 +1,51 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{rails} + s.version = "3.0.pre" + + s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version= + s.authors = ["David Heinemeier Hansson"] + s.date = %q{2009-09-01} + s.default_executable = %q{rails} + s.description = %q{ Rails is a framework for building web-application using CGI, FCGI, mod_ruby, or WEBrick + on top of either MySQL, PostgreSQL, SQLite, DB2, SQL Server, or Oracle with eRuby- or Builder-based templates. +} + s.email = %q{david@loudthinking.com} + s.executables = ["rails"] + s.files = ["bin", "builtin", "CHANGELOG", "guides", "lib", "MIT-LICENSE", "pkg", "rails.gemspec", "Rakefile", "README", "bin/rails", "builtin/rails_info", "builtin/rails_info/rails", "builtin/rails_info/rails/info.rb", "builtin/rails_info/rails/info_controller.rb", "builtin/rails_info/rails/info_helper.rb", "builtin/rails_info/rails_info_controller.rb", "guides/files", "guides/files/javascripts", "guides/files/javascripts/code_highlighter.js", "guides/files/javascripts/guides.js", "guides/files/javascripts/highlighters.js", "guides/files/stylesheets", "guides/files/stylesheets/main.css", "guides/files/stylesheets/print.css", "guides/files/stylesheets/reset.css", "guides/files/stylesheets/style.css", "guides/files/stylesheets/syntax.css", "guides/images", "guides/images/belongs_to.png", "guides/images/book_icon.gif", "guides/images/bullet.gif", "guides/images/chapters_icon.gif", "guides/images/check_bullet.gif", "guides/images/credits_pic_blank.gif", "guides/images/csrf.png", "guides/images/customized_error_messages.png", "guides/images/error_messages.png", "guides/images/feature_tile.gif", "guides/images/footer_tile.gif", "guides/images/fxn.png", "guides/images/grey_bullet.gif", "guides/images/habtm.png", "guides/images/has_many.png", "guides/images/has_many_through.png", "guides/images/has_one.png", "guides/images/has_one_through.png", "guides/images/header_backdrop.png", "guides/images/header_tile.gif", "guides/images/i18n", "guides/images/i18n/demo_localized_pirate.png", "guides/images/i18n/demo_translated_en.png", "guides/images/i18n/demo_translated_pirate.png", "guides/images/i18n/demo_translation_missing.png", "guides/images/i18n/demo_untranslated.png", "guides/images/icons", "guides/images/icons/callouts", "guides/images/icons/callouts/1.png", "guides/images/icons/callouts/10.png", "guides/images/icons/callouts/11.png", "guides/images/icons/callouts/12.png", "guides/images/icons/callouts/13.png", "guides/images/icons/callouts/14.png", "guides/images/icons/callouts/15.png", "guides/images/icons/callouts/2.png", "guides/images/icons/callouts/3.png", "guides/images/icons/callouts/4.png", "guides/images/icons/callouts/5.png", "guides/images/icons/callouts/6.png", "guides/images/icons/callouts/7.png", "guides/images/icons/callouts/8.png", "guides/images/icons/callouts/9.png", "guides/images/icons/caution.png", "guides/images/icons/example.png", "guides/images/icons/home.png", "guides/images/icons/important.png", "guides/images/icons/next.png", "guides/images/icons/note.png", "guides/images/icons/prev.png", "guides/images/icons/README", "guides/images/icons/tip.png", "guides/images/icons/up.png", "guides/images/icons/warning.png", "guides/images/nav_arrow.gif", "guides/images/polymorphic.png", "guides/images/posts_index.png", "guides/images/rails_guides_logo.gif", "guides/images/rails_logo_remix.gif", "guides/images/rails_welcome.png", "guides/images/session_fixation.png", "guides/images/tab_grey.gif", "guides/images/tab_info.gif", "guides/images/tab_note.gif", "guides/images/tab_red.gif", "guides/images/tab_yellow.gif", "guides/images/tab_yellow.png", "guides/images/validation_error_messages.png", "guides/rails_guides", "guides/rails_guides/generator.rb", "guides/rails_guides/helpers.rb", "guides/rails_guides/indexer.rb", "guides/rails_guides/levenshtein.rb", "guides/rails_guides/textile_extensions.rb", "guides/rails_guides.rb", "guides/source", "guides/source/2_2_release_notes.textile", "guides/source/2_3_release_notes.textile", "guides/source/action_controller_overview.textile", "guides/source/action_mailer_basics.textile", "guides/source/action_view_overview.textile", "guides/source/active_record_basics.textile", "guides/source/active_record_querying.textile", "guides/source/active_support_overview.textile", "guides/source/activerecord_validations_callbacks.textile", "guides/source/ajax_on_rails.textile", "guides/source/association_basics.textile", "guides/source/caching_with_rails.textile", "guides/source/command_line.textile", "guides/source/configuring.textile", "guides/source/contribute.textile", "guides/source/contributing_to_rails.textile", "guides/source/credits.erb.textile", "guides/source/debugging_rails_applications.textile", "guides/source/form_helpers.textile", "guides/source/getting_started.textile", "guides/source/i18n.textile", "guides/source/index.erb.textile", "guides/source/layout.html.erb", "guides/source/layouts_and_rendering.textile", "guides/source/migrations.textile", "guides/source/nested_model_forms.textile", "guides/source/performance_testing.textile", "guides/source/plugins.textile", "guides/source/rails_application_templates.textile", "guides/source/rails_on_rack.textile", "guides/source/routing.textile", "guides/source/security.textile", "guides/source/testing.textile", "lib/code_statistics.rb", "lib/commands", "lib/commands/about.rb", "lib/commands/console.rb", "lib/commands/dbconsole.rb", "lib/commands/destroy.rb", "lib/commands/generate.rb", "lib/commands/ncgi", "lib/commands/ncgi/listener", "lib/commands/ncgi/tracker", "lib/commands/performance", "lib/commands/performance/benchmarker.rb", "lib/commands/performance/profiler.rb", "lib/commands/plugin.rb", "lib/commands/runner.rb", "lib/commands/server.rb", "lib/commands/update.rb", "lib/commands.rb", "lib/console_app.rb", "lib/console_sandbox.rb", "lib/console_with_helpers.rb", "lib/dispatcher.rb", "lib/fcgi_handler.rb", "lib/generators", "lib/generators/actions.rb", "lib/generators/active_model.rb", "lib/generators/active_record", "lib/generators/active_record/migration", "lib/generators/active_record/migration/migration_generator.rb", "lib/generators/active_record/migration/templates", "lib/generators/active_record/migration/templates/migration.rb", "lib/generators/active_record/model", "lib/generators/active_record/model/model_generator.rb", "lib/generators/active_record/model/templates", "lib/generators/active_record/model/templates/migration.rb", "lib/generators/active_record/model/templates/model.rb", "lib/generators/active_record/observer", "lib/generators/active_record/observer/observer_generator.rb", "lib/generators/active_record/observer/templates", "lib/generators/active_record/observer/templates/observer.rb", "lib/generators/active_record/session_migration", "lib/generators/active_record/session_migration/session_migration_generator.rb", "lib/generators/active_record/session_migration/templates", "lib/generators/active_record/session_migration/templates/migration.rb", "lib/generators/active_record.rb", "lib/generators/base.rb", "lib/generators/erb", "lib/generators/erb/controller", "lib/generators/erb/controller/controller_generator.rb", "lib/generators/erb/controller/templates", "lib/generators/erb/controller/templates/view.html.erb", "lib/generators/erb/mailer", "lib/generators/erb/mailer/mailer_generator.rb", "lib/generators/erb/mailer/templates", "lib/generators/erb/mailer/templates/view.erb", "lib/generators/erb/scaffold", "lib/generators/erb/scaffold/scaffold_generator.rb", "lib/generators/erb/scaffold/templates", "lib/generators/erb/scaffold/templates/_form.html.erb", "lib/generators/erb/scaffold/templates/edit.html.erb", "lib/generators/erb/scaffold/templates/index.html.erb", "lib/generators/erb/scaffold/templates/layout.html.erb", "lib/generators/erb/scaffold/templates/new.html.erb", "lib/generators/erb/scaffold/templates/show.html.erb", "lib/generators/erb.rb", "lib/generators/generated_attribute.rb", "lib/generators/migration.rb", "lib/generators/named_base.rb", "lib/generators/rails", "lib/generators/rails/app", "lib/generators/rails/app/app_generator.rb", "lib/generators/rails/app/templates", "lib/generators/rails/app/templates/app", "lib/generators/rails/app/templates/app/controllers", "lib/generators/rails/app/templates/app/controllers/application_controller.rb", "lib/generators/rails/app/templates/app/helpers", "lib/generators/rails/app/templates/app/helpers/application_helper.rb", "lib/generators/rails/app/templates/app/models", "lib/generators/rails/app/templates/app/views", "lib/generators/rails/app/templates/app/views/layouts", "lib/generators/rails/app/templates/config", "lib/generators/rails/app/templates/config/boot.rb", "lib/generators/rails/app/templates/config/databases", "lib/generators/rails/app/templates/config/databases/frontbase.yml", "lib/generators/rails/app/templates/config/databases/ibm_db.yml", "lib/generators/rails/app/templates/config/databases/mysql.yml", "lib/generators/rails/app/templates/config/databases/oracle.yml", "lib/generators/rails/app/templates/config/databases/postgresql.yml", "lib/generators/rails/app/templates/config/databases/sqlite3.yml", "lib/generators/rails/app/templates/config/environment.rb", "lib/generators/rails/app/templates/config/environments", "lib/generators/rails/app/templates/config/environments/development.rb", "lib/generators/rails/app/templates/config/environments/production.rb", "lib/generators/rails/app/templates/config/environments/test.rb", "lib/generators/rails/app/templates/config/initializers", "lib/generators/rails/app/templates/config/initializers/backtrace_silencers.rb", "lib/generators/rails/app/templates/config/initializers/inflections.rb", "lib/generators/rails/app/templates/config/initializers/mime_types.rb", "lib/generators/rails/app/templates/config/initializers/new_rails_defaults.rb", "lib/generators/rails/app/templates/config/initializers/session_store.rb.tt", "lib/generators/rails/app/templates/config/locales", "lib/generators/rails/app/templates/config/locales/en.yml", "lib/generators/rails/app/templates/config/routes.rb", "lib/generators/rails/app/templates/db", "lib/generators/rails/app/templates/db/seeds.rb", "lib/generators/rails/app/templates/dispatchers", "lib/generators/rails/app/templates/dispatchers/config.ru", "lib/generators/rails/app/templates/dispatchers/dispatch.fcgi", "lib/generators/rails/app/templates/dispatchers/dispatch.rb", "lib/generators/rails/app/templates/dispatchers/gateway.cgi", "lib/generators/rails/app/templates/doc", "lib/generators/rails/app/templates/doc/README_FOR_APP", "lib/generators/rails/app/templates/public", "lib/generators/rails/app/templates/public/404.html", "lib/generators/rails/app/templates/public/422.html", "lib/generators/rails/app/templates/public/500.html", "lib/generators/rails/app/templates/public/favicon.ico", "lib/generators/rails/app/templates/public/images", "lib/generators/rails/app/templates/public/images/rails.png", "lib/generators/rails/app/templates/public/index.html", "lib/generators/rails/app/templates/public/javascripts", "lib/generators/rails/app/templates/public/javascripts/application.js", "lib/generators/rails/app/templates/public/javascripts/controls.js", "lib/generators/rails/app/templates/public/javascripts/dragdrop.js", "lib/generators/rails/app/templates/public/javascripts/effects.js", "lib/generators/rails/app/templates/public/javascripts/prototype.js", "lib/generators/rails/app/templates/public/robots.txt", "lib/generators/rails/app/templates/public/stylesheets", "lib/generators/rails/app/templates/Rakefile", "lib/generators/rails/app/templates/README", "lib/generators/rails/app/templates/script", "lib/generators/rails/app/templates/script/about.tt", "lib/generators/rails/app/templates/script/console.tt", "lib/generators/rails/app/templates/script/dbconsole.tt", "lib/generators/rails/app/templates/script/destroy.tt", "lib/generators/rails/app/templates/script/generate.tt", "lib/generators/rails/app/templates/script/performance", "lib/generators/rails/app/templates/script/performance/benchmarker.tt", "lib/generators/rails/app/templates/script/performance/profiler.tt", "lib/generators/rails/app/templates/script/plugin.tt", "lib/generators/rails/app/templates/script/runner.tt", "lib/generators/rails/app/templates/script/server.tt", "lib/generators/rails/app/templates/test", "lib/generators/rails/app/templates/test/fixtures", "lib/generators/rails/app/templates/test/functional", "lib/generators/rails/app/templates/test/integration", "lib/generators/rails/app/templates/test/performance", "lib/generators/rails/app/templates/test/performance/browsing_test.rb", "lib/generators/rails/app/templates/test/test_helper.rb", "lib/generators/rails/app/templates/test/unit", "lib/generators/rails/app/USAGE", "lib/generators/rails/controller", "lib/generators/rails/controller/controller_generator.rb", "lib/generators/rails/controller/templates", "lib/generators/rails/controller/templates/controller.rb", "lib/generators/rails/controller/USAGE", "lib/generators/rails/generator", "lib/generators/rails/generator/generator_generator.rb", "lib/generators/rails/generator/templates", "lib/generators/rails/generator/templates/%file_name%_generator.rb.tt", "lib/generators/rails/generator/templates/templates", "lib/generators/rails/generator/templates/USAGE.tt", "lib/generators/rails/generator/USAGE", "lib/generators/rails/helper", "lib/generators/rails/helper/helper_generator.rb", "lib/generators/rails/helper/templates", "lib/generators/rails/helper/templates/helper.rb", "lib/generators/rails/helper/USAGE", "lib/generators/rails/integration_test", "lib/generators/rails/integration_test/integration_test_generator.rb", "lib/generators/rails/integration_test/USAGE", "lib/generators/rails/mailer", "lib/generators/rails/mailer/mailer_generator.rb", "lib/generators/rails/mailer/templates", "lib/generators/rails/mailer/templates/mailer.rb", "lib/generators/rails/mailer/USAGE", "lib/generators/rails/metal", "lib/generators/rails/metal/metal_generator.rb", "lib/generators/rails/metal/templates", "lib/generators/rails/metal/templates/metal.rb", "lib/generators/rails/metal/USAGE", "lib/generators/rails/migration", "lib/generators/rails/migration/migration_generator.rb", "lib/generators/rails/migration/USAGE", "lib/generators/rails/model", "lib/generators/rails/model/model_generator.rb", "lib/generators/rails/model/USAGE", "lib/generators/rails/model_subclass", "lib/generators/rails/model_subclass/model_subclass_generator.rb", "lib/generators/rails/observer", "lib/generators/rails/observer/observer_generator.rb", "lib/generators/rails/observer/USAGE", "lib/generators/rails/performance_test", "lib/generators/rails/performance_test/performance_test_generator.rb", "lib/generators/rails/performance_test/USAGE", "lib/generators/rails/plugin", "lib/generators/rails/plugin/plugin_generator.rb", "lib/generators/rails/plugin/templates", "lib/generators/rails/plugin/templates/init.rb", "lib/generators/rails/plugin/templates/install.rb", "lib/generators/rails/plugin/templates/lib", "lib/generators/rails/plugin/templates/lib/%file_name%.rb.tt", "lib/generators/rails/plugin/templates/MIT-LICENSE", "lib/generators/rails/plugin/templates/Rakefile", "lib/generators/rails/plugin/templates/README", "lib/generators/rails/plugin/templates/tasks", "lib/generators/rails/plugin/templates/tasks/%file_name%_tasks.rake.tt", "lib/generators/rails/plugin/templates/uninstall.rb", "lib/generators/rails/plugin/USAGE", "lib/generators/rails/resource", "lib/generators/rails/resource/resource_generator.rb", "lib/generators/rails/resource/USAGE", "lib/generators/rails/scaffold", "lib/generators/rails/scaffold/scaffold_generator.rb", "lib/generators/rails/scaffold/USAGE", "lib/generators/rails/scaffold_controller", "lib/generators/rails/scaffold_controller/scaffold_controller_generator.rb", "lib/generators/rails/scaffold_controller/templates", "lib/generators/rails/scaffold_controller/templates/controller.rb", "lib/generators/rails/scaffold_controller/USAGE", "lib/generators/rails/session_migration", "lib/generators/rails/session_migration/session_migration_generator.rb", "lib/generators/rails/session_migration/USAGE", "lib/generators/rails/stylesheets", "lib/generators/rails/stylesheets/stylesheets_generator.rb", "lib/generators/rails/stylesheets/templates", "lib/generators/rails/stylesheets/templates/scaffold.css", "lib/generators/rails/stylesheets/USAGE", "lib/generators/resource_helpers.rb", "lib/generators/test_unit", "lib/generators/test_unit/controller", "lib/generators/test_unit/controller/controller_generator.rb", "lib/generators/test_unit/controller/templates", "lib/generators/test_unit/controller/templates/functional_test.rb", "lib/generators/test_unit/helper", "lib/generators/test_unit/helper/helper_generator.rb", "lib/generators/test_unit/helper/templates", "lib/generators/test_unit/helper/templates/helper_test.rb", "lib/generators/test_unit/integration", "lib/generators/test_unit/integration/integration_generator.rb", "lib/generators/test_unit/integration/templates", "lib/generators/test_unit/integration/templates/integration_test.rb", "lib/generators/test_unit/mailer", "lib/generators/test_unit/mailer/mailer_generator.rb", "lib/generators/test_unit/mailer/templates", "lib/generators/test_unit/mailer/templates/fixture", "lib/generators/test_unit/mailer/templates/unit_test.rb", "lib/generators/test_unit/model", "lib/generators/test_unit/model/model_generator.rb", "lib/generators/test_unit/model/templates", "lib/generators/test_unit/model/templates/fixtures.yml", "lib/generators/test_unit/model/templates/unit_test.rb", "lib/generators/test_unit/observer", "lib/generators/test_unit/observer/observer_generator.rb", "lib/generators/test_unit/observer/templates", "lib/generators/test_unit/observer/templates/unit_test.rb", "lib/generators/test_unit/performance", "lib/generators/test_unit/performance/performance_generator.rb", "lib/generators/test_unit/performance/templates", "lib/generators/test_unit/performance/templates/performance_test.rb", "lib/generators/test_unit/plugin", "lib/generators/test_unit/plugin/plugin_generator.rb", "lib/generators/test_unit/plugin/templates", "lib/generators/test_unit/plugin/templates/%file_name%_test.rb.tt", "lib/generators/test_unit/plugin/templates/test_helper.rb", "lib/generators/test_unit/scaffold", "lib/generators/test_unit/scaffold/scaffold_generator.rb", "lib/generators/test_unit/scaffold/templates", "lib/generators/test_unit/scaffold/templates/functional_test.rb", "lib/generators/test_unit.rb", "lib/generators.rb", "lib/initializer.rb", "lib/initializer_old.rb", "lib/performance_test_help.rb", "lib/rails", "lib/rails/backtrace_cleaner.rb", "lib/rails/configuration.rb", "lib/rails/core.rb", "lib/rails/gem_builder.rb", "lib/rails/gem_dependency.rb", "lib/rails/paths.rb", "lib/rails/plugin", "lib/rails/plugin/loader.rb", "lib/rails/plugin/locator.rb", "lib/rails/plugin.rb", "lib/rails/rack", "lib/rails/rack/debugger.rb", "lib/rails/rack/log_tailer.rb", "lib/rails/rack/metal.rb", "lib/rails/rack/static.rb", "lib/rails/rack.rb", "lib/rails/vendor_gem_source_index.rb", "lib/rails/version.rb", "lib/railties_path.rb", "lib/ruby_version_check.rb", "lib/rubyprof_ext.rb", "lib/source_annotation_extractor.rb", "lib/tasks", "lib/tasks/annotations.rake", "lib/tasks/databases.rake", "lib/tasks/documentation.rake", "lib/tasks/framework.rake", "lib/tasks/gems.rake", "lib/tasks/log.rake", "lib/tasks/middleware.rake", "lib/tasks/misc.rake", "lib/tasks/rails.rb", "lib/tasks/routes.rake", "lib/tasks/statistics.rake", "lib/tasks/testing.rake", "lib/tasks/tmp.rake", "lib/test_help.rb", "lib/vendor", "lib/vendor/bundler", "lib/vendor/bundler/bin", "lib/vendor/bundler/bin/gem_bundler", "lib/vendor/bundler/lib", "lib/vendor/bundler/lib/bundler", "lib/vendor/bundler/lib/bundler/cli.rb", "lib/vendor/bundler/lib/bundler/dependency.rb", "lib/vendor/bundler/lib/bundler/finder.rb", "lib/vendor/bundler/lib/bundler/gem_bundle.rb", "lib/vendor/bundler/lib/bundler/gem_specification.rb", "lib/vendor/bundler/lib/bundler/installer.rb", "lib/vendor/bundler/lib/bundler/manifest.rb", "lib/vendor/bundler/lib/bundler/resolver", "lib/vendor/bundler/lib/bundler/resolver/builders.rb", "lib/vendor/bundler/lib/bundler/resolver/engine.rb", "lib/vendor/bundler/lib/bundler/resolver/inspect.rb", "lib/vendor/bundler/lib/bundler/resolver/search.rb", "lib/vendor/bundler/lib/bundler/resolver/stack.rb", "lib/vendor/bundler/lib/bundler/resolver/state.rb", "lib/vendor/bundler/lib/bundler/resolver.rb", "lib/vendor/bundler/lib/bundler/runtime.rb", "lib/vendor/bundler/lib/bundler.rb", "lib/vendor/bundler/LICENSE", "lib/vendor/bundler/Rakefile", "lib/vendor/thor-0.11.5", "lib/vendor/thor-0.11.5/lib", "lib/vendor/thor-0.11.6", "lib/vendor/thor-0.11.6/bin", "lib/vendor/thor-0.11.6/bin/rake2thor", "lib/vendor/thor-0.11.6/bin/thor", "lib/vendor/thor-0.11.6/CHANGELOG.rdoc", "lib/vendor/thor-0.11.6/lib", "lib/vendor/thor-0.11.6/lib/thor", "lib/vendor/thor-0.11.6/lib/thor/actions", "lib/vendor/thor-0.11.6/lib/thor/actions/create_file.rb", "lib/vendor/thor-0.11.6/lib/thor/actions/directory.rb", "lib/vendor/thor-0.11.6/lib/thor/actions/empty_directory.rb", "lib/vendor/thor-0.11.6/lib/thor/actions/file_manipulation.rb", "lib/vendor/thor-0.11.6/lib/thor/actions/inject_into_file.rb", "lib/vendor/thor-0.11.6/lib/thor/actions.rb", "lib/vendor/thor-0.11.6/lib/thor/base.rb", "lib/vendor/thor-0.11.6/lib/thor/core_ext", "lib/vendor/thor-0.11.6/lib/thor/core_ext/hash_with_indifferent_access.rb", "lib/vendor/thor-0.11.6/lib/thor/core_ext/ordered_hash.rb", "lib/vendor/thor-0.11.6/lib/thor/error.rb", "lib/vendor/thor-0.11.6/lib/thor/group.rb", "lib/vendor/thor-0.11.6/lib/thor/invocation.rb", "lib/vendor/thor-0.11.6/lib/thor/parser", "lib/vendor/thor-0.11.6/lib/thor/parser/argument.rb", "lib/vendor/thor-0.11.6/lib/thor/parser/arguments.rb", "lib/vendor/thor-0.11.6/lib/thor/parser/option.rb", "lib/vendor/thor-0.11.6/lib/thor/parser/options.rb", "lib/vendor/thor-0.11.6/lib/thor/parser.rb", "lib/vendor/thor-0.11.6/lib/thor/rake_compat.rb", "lib/vendor/thor-0.11.6/lib/thor/runner.rb", "lib/vendor/thor-0.11.6/lib/thor/shell", "lib/vendor/thor-0.11.6/lib/thor/shell/basic.rb", "lib/vendor/thor-0.11.6/lib/thor/shell/color.rb", "lib/vendor/thor-0.11.6/lib/thor/shell.rb", "lib/vendor/thor-0.11.6/lib/thor/task.rb", "lib/vendor/thor-0.11.6/lib/thor/util.rb", "lib/vendor/thor-0.11.6/lib/thor.rb", "lib/vendor/thor-0.11.6/LICENSE", "lib/vendor/thor-0.11.6/README.rdoc", "lib/webrick_server.rb", "lib/generators/rails/app/templates/app/models/.empty_directory", "lib/generators/rails/app/templates/app/views/layouts/.empty_directory", "lib/generators/rails/app/templates/public/stylesheets/.empty_directory", "lib/generators/rails/app/templates/test/fixtures/.empty_directory", "lib/generators/rails/app/templates/test/functional/.empty_directory", "lib/generators/rails/app/templates/test/integration/.empty_directory", "lib/generators/rails/app/templates/test/unit/.empty_directory", "lib/generators/rails/generator/templates/templates/.empty_directory"] + s.homepage = %q{http://www.rubyonrails.org} + s.rdoc_options = ["--exclude", "."] + s.require_paths = ["lib"] + s.rubyforge_project = %q{rails} + s.rubygems_version = %q{1.3.5} + s.summary = %q{Web-application framework with template engine, control-flow layer, and ORM.} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 3 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q<rake>, [">= 0.8.3"]) + s.add_runtime_dependency(%q<activesupport>, ["= 3.0.pre"]) + s.add_runtime_dependency(%q<activerecord>, ["= 3.0.pre"]) + s.add_runtime_dependency(%q<actionpack>, ["= 3.0.pre"]) + s.add_runtime_dependency(%q<actionmailer>, ["= 3.0.pre"]) + s.add_runtime_dependency(%q<activeresource>, ["= 3.0.pre"]) + else + s.add_dependency(%q<rake>, [">= 0.8.3"]) + s.add_dependency(%q<activesupport>, ["= 3.0.pre"]) + s.add_dependency(%q<activerecord>, ["= 3.0.pre"]) + s.add_dependency(%q<actionpack>, ["= 3.0.pre"]) + s.add_dependency(%q<actionmailer>, ["= 3.0.pre"]) + s.add_dependency(%q<activeresource>, ["= 3.0.pre"]) + end + else + s.add_dependency(%q<rake>, [">= 0.8.3"]) + s.add_dependency(%q<activesupport>, ["= 3.0.pre"]) + s.add_dependency(%q<activerecord>, ["= 3.0.pre"]) + s.add_dependency(%q<actionpack>, ["= 3.0.pre"]) + s.add_dependency(%q<actionmailer>, ["= 3.0.pre"]) + s.add_dependency(%q<activeresource>, ["= 3.0.pre"]) + end +end diff --git a/railties/test/abstract_unit.rb b/railties/test/abstract_unit.rb index 9a640bdbc5..ea6ed01c7d 100644 --- a/railties/test/abstract_unit.rb +++ b/railties/test/abstract_unit.rb @@ -1,5 +1,9 @@ ORIG_ARGV = ARGV.dup +require 'rubygems' +gem 'rack', '~> 1.0.0' +gem 'rack-test', '~> 0.4.2' + $:.unshift File.dirname(__FILE__) + "/../../activesupport/lib" $:.unshift File.dirname(__FILE__) + "/../../activerecord/lib" $:.unshift File.dirname(__FILE__) + "/../../actionpack/lib" @@ -9,7 +13,6 @@ $:.unshift File.dirname(__FILE__) + "/../lib" $:.unshift File.dirname(__FILE__) + "/../builtin/rails_info" require 'stringio' -require 'rubygems' require 'test/unit' require 'active_support' diff --git a/railties/test/generators/generators_test_helper.rb b/railties/test/generators/generators_test_helper.rb index a258574dce..2a9d680c6a 100644 --- a/railties/test/generators/generators_test_helper.rb +++ b/railties/test/generators/generators_test_helper.rb @@ -9,10 +9,12 @@ else end $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../lib" +require 'generators' + +require 'rubygems' $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../../activerecord/lib" $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../../actionpack/lib" -require 'generators' -require 'activerecord' +require 'active_record' require 'action_dispatch' CURRENT_PATH = File.expand_path(Dir.pwd) diff --git a/railties/test/initializer/test_helper.rb b/railties/test/initializer/test_helper.rb index 9d7dfff1c0..f6a2547efc 100644 --- a/railties/test/initializer/test_helper.rb +++ b/railties/test/initializer/test_helper.rb @@ -2,13 +2,16 @@ # boot from scratch in vendored mode. This file should really only be # required in test cases that use the isolation helper so that requires # can be reset correctly. -RAILS_ROOT = File.join(File.dirname(__FILE__), "root") -RAILS_FRAMEWORK_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..')) +RAILS_ROOT = "#{File.dirname(__FILE__)}/root" +RAILS_FRAMEWORK_ROOT = File.expand_path("#{File.dirname(__FILE__)}/../../..") + +require 'rubygems' +gem 'rack', '~> 1.0.0' require "test/unit" # We are purposely avoiding adding things to the load path to catch bugs that only happen in the genuine article -require File.join(RAILS_FRAMEWORK_ROOT, 'activesupport', 'lib', 'active_support', 'testing', 'isolation') -require File.join(RAILS_FRAMEWORK_ROOT, 'activesupport', 'lib', 'active_support', 'testing', 'declarative') +require "#{RAILS_FRAMEWORK_ROOT}/activesupport/lib/active_support/testing/isolation" +require "#{RAILS_FRAMEWORK_ROOT}/activesupport/lib/active_support/testing/declarative" class Test::Unit::TestCase extend ActiveSupport::Testing::Declarative @@ -35,7 +38,7 @@ module Rails def boot! # Require the initializer - require File.join(RAILS_FRAMEWORK_ROOT, 'railties', 'lib', 'initializer') + require "#{RAILS_FRAMEWORK_ROOT}/railties/lib/initializer" # Run the initializer the same way boot.rb does it Rails::Initializer.run(:install_gem_spec_stubs) Rails::GemDependency.add_frozen_gem_path @@ -45,4 +48,4 @@ module Rails end # All that for this: -Rails.boot!
\ No newline at end of file +Rails.boot! diff --git a/railties/test/rails_info_test.rb b/railties/test/rails_info_test.rb index fdcc7a1ef6..568e2a9972 100644 --- a/railties/test/rails_info_test.rb +++ b/railties/test/rails_info_test.rb @@ -3,6 +3,9 @@ $:.unshift File.dirname(__FILE__) + "/../builtin/rails_info" $:.unshift File.dirname(__FILE__) + "/../../activesupport/lib" $:.unshift File.dirname(__FILE__) + "/../../actionpack/lib" +require 'rubygems' +gem 'rack', '~> 1.0.0' + require 'test/unit' require 'active_support' require 'active_support/test_case' |