diff options
108 files changed, 804 insertions, 574 deletions
@@ -1,17 +1,20 @@ -gem "rake", ">= 0.8.7" +path File.expand_path('..', __FILE__) +source :gemcutter + +gem "rails", "3.0.pre" + +gem "rake", ">= 0.8.7" gem "mocha", ">= 0.9.8" -gem "ruby-debug", ">= 0.10.3" if RUBY_VERSION < '1.9' -gem "rails", "3.0.pre", :path => "railties" -%w(activesupport activemodel actionpack actionmailer activerecord activeresource).each do |lib| - gem lib, '3.0.pre', :path => lib +if RUBY_VERSION < '1.9' + gem "ruby-debug", ">= 0.10.3" end # AR -gem "arel", "0.2.pre", :git => "git://github.com/rails/arel.git" +gem "arel", ">= 0.2.0" gem "sqlite3-ruby", ">= 1.2.5" -only :test do +group :test do gem "pg", ">= 0.8.0" gem "mysql", ">= 2.8.1" end @@ -21,8 +24,6 @@ gem "rack-test", "0.5.3" gem "RedCloth", ">= 4.2.2" if ENV['CI'] - disable_system_gems - gem "nokogiri", ">= 1.4.0" gem "memcache-client", ">= 1.7.6" @@ -34,5 +35,3 @@ if ENV['CI'] gem "test-unit", ">= 2.0.5" end end - -disable_system_gems @@ -38,7 +38,6 @@ Rake::GemPackageTask.new(spec) do |pkg| end task :install => :gem do - system %(cd arel && gem build arel.gemspec && gem install arel-0.2.pre.gem --no-ri --no-rdoc --ignore-dependencies) system %(cd rack && rake gem VERSION=1.0.2.pre && gem install rack-1.0.2.pre.gem --no-ri --no-rdoc --ignore-dependencies) (PROJECTS - ["railties"]).each do |project| puts "INSTALLING #{project}" diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index aa9822c6ab..ec85a20f70 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -268,13 +268,13 @@ module ActionMailer #:nodoc: private_class_method :new #:nodoc: - extlib_inheritable_accessor :default_params + class_attribute :default_params self.default_params = { :mime_version => "1.0", :charset => "utf-8", :content_type => "text/plain", :parts_order => [ "text/plain", "text/enriched", "text/html" ] - } + }.freeze class << self @@ -284,9 +284,9 @@ module ActionMailer #:nodoc: attr_writer :mailer_name alias :controller_path :mailer_name - def default(value=nil) - self.default_params.merge!(value) if value - self.default_params + def default(value = nil) + self.default_params = default_params.merge(value).freeze if value + default_params end # Receives a raw email, parses it into an email object, decodes it, diff --git a/actionmailer/lib/action_mailer/delivery_methods.rb b/actionmailer/lib/action_mailer/delivery_methods.rb index 7e92aea8fd..043794bb12 100644 --- a/actionmailer/lib/action_mailer/delivery_methods.rb +++ b/actionmailer/lib/action_mailer/delivery_methods.rb @@ -7,8 +7,7 @@ module ActionMailer extend ActiveSupport::Concern included do - extlib_inheritable_accessor :delivery_methods, :delivery_method, - :instance_writer => false + class_attribute :delivery_methods, :delivery_method # Do not make this inheritable, because we always want it to propagate cattr_accessor :raise_delivery_errors @@ -17,7 +16,7 @@ module ActionMailer cattr_accessor :perform_deliveries self.perform_deliveries = true - self.delivery_methods = {} + self.delivery_methods = {}.freeze self.delivery_method = :smtp add_delivery_method :smtp, Mail::SMTP, @@ -53,12 +52,9 @@ module ActionMailer # :arguments => '-i -t' # def add_delivery_method(symbol, klass, default_options={}) - unless respond_to?(:"#{symbol}_settings") - extlib_inheritable_accessor(:"#{symbol}_settings", :instance_writer => false) - end - + class_attribute(:"#{symbol}_settings") unless respond_to?(:"#{symbol}_settings") send(:"#{symbol}_settings=", default_options) - self.delivery_methods[symbol.to_sym] = klass + self.delivery_methods = delivery_methods.merge(symbol.to_sym => klass).freeze end def wrap_delivery_behavior(mail, method=nil) #:nodoc: @@ -87,4 +83,4 @@ module ActionMailer self.class.wrap_delivery_behavior(message, *args) end end -end
\ No newline at end of file +end diff --git a/actionmailer/lib/action_mailer/deprecated_api.rb b/actionmailer/lib/action_mailer/deprecated_api.rb index 54ad18f796..c08ab4164e 100644 --- a/actionmailer/lib/action_mailer/deprecated_api.rb +++ b/actionmailer/lib/action_mailer/deprecated_api.rb @@ -47,7 +47,7 @@ module ActionMailer end def template_root=(root) - ActiveSupport::Deprecation.warn "template_root= is deprecated, use view_paths.unshift instead", caller[0,2] + ActiveSupport::Deprecation.warn "template_root= is deprecated, use prepend_view_path instead", caller[0,2] self.view_paths = ActionView::Base.process_view_paths(root) end diff --git a/actionmailer/test/abstract_unit.rb b/actionmailer/test/abstract_unit.rb index ce09bb5d61..f6baa4a9e8 100644 --- a/actionmailer/test/abstract_unit.rb +++ b/actionmailer/test/abstract_unit.rb @@ -1,14 +1,8 @@ -begin - require File.expand_path('../../../vendor/gems/environment', __FILE__) -rescue LoadError -end - -lib = File.expand_path('../../lib', __FILE__) -$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib) +require File.expand_path('../../../load_paths', __FILE__) -require 'rubygems' require 'test/unit' require 'action_mailer' +require 'action_mailer/test_case' # Show backtraces for deprecated behavior for quicker cleanup. ActiveSupport::Deprecation.debug = true diff --git a/actionmailer/test/base_test.rb b/actionmailer/test/base_test.rb index 57bfe2375e..7e794e10e8 100644 --- a/actionmailer/test/base_test.rb +++ b/actionmailer/test/base_test.rb @@ -81,8 +81,8 @@ class BaseTest < ActiveSupport::TestCase def different_template(template_name='') mail do |format| - format.text { render :template => template_name } - format.html { render :template => template_name } + format.text { render :template => "#{mailer_name}/#{template_name}" } + format.html { render :template => "#{mailer_name}/#{template_name}" } end end @@ -254,7 +254,7 @@ class BaseTest < ActiveSupport::TestCase end test "subject gets default from I18n" do - BaseMailer.default[:subject] = nil + BaseMailer.default :subject => nil email = BaseMailer.welcome(:subject => nil) assert_equal "Welcome", email.subject @@ -331,22 +331,24 @@ class BaseTest < ActiveSupport::TestCase end test "implicit multipart with several view paths uses the first one with template" do + old = BaseMailer.view_paths begin - BaseMailer.view_paths.unshift(File.join(FIXTURE_LOAD_PATH, "another.path")) + BaseMailer.view_paths = [File.join(FIXTURE_LOAD_PATH, "another.path")] + old.dup email = BaseMailer.welcome assert_equal("Welcome from another path", email.body.encoded) ensure - BaseMailer.view_paths.shift + BaseMailer.view_paths = old end end test "implicit multipart with inexistent templates uses the next view path" do + old = BaseMailer.view_paths begin - BaseMailer.view_paths.unshift(File.join(FIXTURE_LOAD_PATH, "unknown")) + BaseMailer.view_paths = [File.join(FIXTURE_LOAD_PATH, "unknown")] + old.dup email = BaseMailer.welcome assert_equal("Welcome", email.body.encoded) ensure - BaseMailer.view_paths.shift + BaseMailer.view_paths = old end end @@ -503,16 +505,10 @@ class BaseTest < ActiveSupport::TestCase end def with_default(klass, new_values) - hash = klass.default - old_values = {} - new_values.each do |key, value| - old_values[key] = hash[key] - hash[key] = value - end + old = klass.default_params + klass.default(new_values) yield ensure - old_values.each do |key, value| - hash[key] = value - end + klass.default_params = old end end diff --git a/actionmailer/test/delivery_methods_test.rb b/actionmailer/test/delivery_methods_test.rb index 4907ca0903..22a7d19bc2 100644 --- a/actionmailer/test/delivery_methods_test.rb +++ b/actionmailer/test/delivery_methods_test.rb @@ -45,7 +45,9 @@ class CustomDeliveryMethodsTest < ActiveSupport::TestCase def teardown ActionMailer::Base.delivery_method = @old_delivery_method - ActionMailer::Base.delivery_methods.delete(:custom) + new = ActionMailer::Base.delivery_methods.dup + new.delete(:custom) + ActionMailer::Base.delivery_methods = new end test "allow to add custom delivery method" do @@ -167,4 +169,4 @@ class MailDeliveryTest < ActiveSupport::TestCase assert_equal(0, DeliveryMailer.deliveries.length) end -end
\ No newline at end of file +end diff --git a/actionpack/lib/abstract_controller/helpers.rb b/actionpack/lib/abstract_controller/helpers.rb index eb621c0865..578b884a4d 100644 --- a/actionpack/lib/abstract_controller/helpers.rb +++ b/actionpack/lib/abstract_controller/helpers.rb @@ -1,4 +1,6 @@ require 'active_support/dependencies' +require 'active_support/core_ext/class/attribute' +require 'active_support/core_ext/module/delegation' module AbstractController module Helpers @@ -12,10 +14,10 @@ module AbstractController end included do - extlib_inheritable_accessor(:_helpers) { Module.new } - extlib_inheritable_accessor(:_helper_serial) do - AbstractController::Helpers.next_serial - end + class_attribute :_helpers, :_helper_serial + delegate :_helpers, :to => :'self.class' + self._helpers = Module.new + self._helper_serial = ::AbstractController::Helpers.next_serial end module ClassMethods diff --git a/actionpack/lib/abstract_controller/layouts.rb b/actionpack/lib/abstract_controller/layouts.rb index 56ddf9bf01..0d214396aa 100644 --- a/actionpack/lib/abstract_controller/layouts.rb +++ b/actionpack/lib/abstract_controller/layouts.rb @@ -1,3 +1,6 @@ +require 'active_support/core_ext/class/attribute' +require 'active_support/core_ext/module/delegation' + module AbstractController # Layouts reverse the common pattern of including shared headers and footers in many templates to isolate changes in # repeated setups. The inclusion pattern has pages that look like this: @@ -161,8 +164,9 @@ module AbstractController include Rendering included do - extlib_inheritable_accessor(:_layout_conditions) { Hash.new } - extlib_inheritable_accessor(:_action_has_layout) { Hash.new } + class_attribute :_layout_conditions + delegate :_layout_conditions, :to => :'self.class' + self._layout_conditions = {} _write_layout_method end diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb index ac407bda5e..619a49571b 100644 --- a/actionpack/lib/abstract_controller/rendering.rb +++ b/actionpack/lib/abstract_controller/rendering.rb @@ -1,4 +1,7 @@ require "abstract_controller/base" +require 'active_support/core_ext/class/attribute' +require 'active_support/core_ext/module/delegation' +require 'active_support/core_ext/array/wrap' module AbstractController class DoubleRenderError < Error @@ -13,8 +16,9 @@ module AbstractController extend ActiveSupport::Concern included do - extlib_inheritable_accessor :_view_paths - self._view_paths ||= ActionView::PathSet.new + class_attribute :_view_paths + delegate :_view_paths, :to => :'self.class' + self._view_paths = ActionView::PathSet.new end # An instance of a view class. The default view class is ActionView::Base @@ -156,7 +160,6 @@ module AbstractController elsif options.key?(:file) options[:_template_name] = options[:file] end - name = (options[:_template_name] || options[:action] || action_name).to_s options[:_prefix] ||= _prefix if (options.keys & [:partial, :file, :template]).empty? @@ -201,7 +204,7 @@ module AbstractController # the default view path. You may also provide a custom view path # (see ActionView::ViewPathSet for more information) def append_view_path(path) - self.view_paths << path + self.view_paths = view_paths.dup + Array.wrap(path) end # Prepend a path to the list of view paths for this controller. @@ -212,12 +215,12 @@ module AbstractController # (see ActionView::ViewPathSet for more information) def prepend_view_path(path) clear_template_caches! - self.view_paths.unshift(path) + self.view_paths = Array.wrap(path) + view_paths.dup end # A list of all of the default view paths for this controller. def view_paths - self._view_paths + _view_paths end # Set the view paths. @@ -228,7 +231,8 @@ module AbstractController def view_paths=(paths) clear_template_caches! self._view_paths = paths.is_a?(ActionView::PathSet) ? paths : ActionView::Base.process_view_paths(paths) + _view_paths.freeze end end end -end
\ No newline at end of file +end diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb index 57627a6f0b..2b35e111ec 100644 --- a/actionpack/lib/action_controller/metal.rb +++ b/actionpack/lib/action_controller/metal.rb @@ -1,4 +1,4 @@ -require 'active_support/core_ext/class/inheritable_attributes' +require 'active_support/core_ext/class/attribute' module ActionController # ActionController::Metal provides a way to get a valid Rack application from a controller. @@ -90,7 +90,12 @@ module ActionController end end - extlib_inheritable_accessor(:middleware_stack) { ActionDispatch::MiddlewareStack.new } + class_attribute :middleware_stack + self.middleware_stack = ActionDispatch::MiddlewareStack.new + + def self.inherited(base) + self.middleware_stack = base.middleware_stack.dup + end def self.use(*args) middleware_stack.use(*args) diff --git a/actionpack/lib/action_controller/metal/compatibility.rb b/actionpack/lib/action_controller/metal/compatibility.rb index 2be0fa097e..1d4a719aa6 100644 --- a/actionpack/lib/action_controller/metal/compatibility.rb +++ b/actionpack/lib/action_controller/metal/compatibility.rb @@ -15,9 +15,6 @@ module ActionController cattr_accessor :session_options self.session_options = {} - cattr_accessor :allow_concurrency - self.allow_concurrency = false - cattr_accessor :relative_url_root self.relative_url_root = ENV['RAILS_RELATIVE_URL_ROOT'] @@ -44,9 +41,6 @@ module ActionController self.page_cache_directory = defined?(Rails.public_path) ? Rails.public_path : "" - cattr_accessor :consider_all_requests_local - self.consider_all_requests_local = true - # Prepends all the URL-generating helpers from AssetHelper. This makes it possible to easily move javascripts, stylesheets, # and images to a dedicated asset server away from the main web server. Example: # ActionController::Base.asset_host = "http://assets.example.com" @@ -74,6 +68,25 @@ module ActionController module ClassMethods def consider_all_requests_local + ActiveSupport::Deprecation.warn "ActionController::Base.consider_all_requests_local is deprecated, " << + "use Rails.application.config.consider_all_requests_local instead" + Rails.application.config.consider_all_requests_local + end + + def consider_all_requests_local=(value) + ActiveSupport::Deprecation.warn "ActionController::Base.consider_all_requests_local= is no longer effective. " << + "Please configure it on your application with config.consider_all_requests_local=" + end + + def allow_concurrency + ActiveSupport::Deprecation.warn "ActionController::Base.allow_concurrency is deprecated, " << + "use Rails.application.config.allow_concurrency instead" + Rails.application.config.allow_concurrency + end + + def allow_concurrency=(value) + ActiveSupport::Deprecation.warn "ActionController::Base.allow_concurrency= is no longer effective. " << + "Please configure it on your application with config.allow_concurrency=" end def rescue_action(env) @@ -86,6 +99,9 @@ module ActionController end end + delegate :consider_all_requests_local, :consider_all_requests_local=, + :allow_concurrency, :allow_concurrency=, :to => :"self.class" + def render_to_body(options) if options.is_a?(Hash) && options.key?(:template) options[:template].sub!(/^\//, '') diff --git a/actionpack/lib/action_controller/metal/helpers.rb b/actionpack/lib/action_controller/metal/helpers.rb index 05843a061b..1b5a4c3080 100644 --- a/actionpack/lib/action_controller/metal/helpers.rb +++ b/actionpack/lib/action_controller/metal/helpers.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/class/attribute' + module ActionController # The Rails framework provides a large number of helpers for working with +assets+, +dates+, +forms+, # +numbers+ and model objects, to name a few. These helpers are available to all templates @@ -50,7 +52,7 @@ module ActionController include AbstractController::Helpers included do - extlib_inheritable_accessor(:helpers_path) + class_attribute :helpers_path self.helpers_path = [] end diff --git a/actionpack/lib/action_controller/metal/hide_actions.rb b/actionpack/lib/action_controller/metal/hide_actions.rb index cdacdc40a6..e893acffdf 100644 --- a/actionpack/lib/action_controller/metal/hide_actions.rb +++ b/actionpack/lib/action_controller/metal/hide_actions.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/class/attribute' + module ActionController # ActionController::HideActions adds the ability to prevent public methods on a controller # to be called as actions. @@ -5,7 +7,8 @@ module ActionController extend ActiveSupport::Concern included do - extlib_inheritable_accessor(:hidden_actions) { Set.new } + class_attribute :hidden_actions + self.hidden_actions = Set.new end private @@ -14,7 +17,7 @@ module ActionController # action name is in the list of hidden actions. def action_method?(action_name) self.class.visible_action?(action_name) do - !hidden_actions.include?(action_name) && super + !self.class.hidden_actions.include?(action_name) && super end end @@ -24,7 +27,7 @@ module ActionController # ==== Parameters # *args<#to_s>:: A list of actions def hide_action(*args) - hidden_actions.merge(args.map! {|a| a.to_s }) + self.hidden_actions = hidden_actions.dup.merge(args.map(&:to_s)) end def inherited(klass) diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb index 08599d660e..e70a20b2be 100644 --- a/actionpack/lib/action_controller/metal/mime_responds.rb +++ b/actionpack/lib/action_controller/metal/mime_responds.rb @@ -1,11 +1,12 @@ require 'abstract_controller/collector' +require 'active_support/core_ext/class/attribute' module ActionController #:nodoc: module MimeResponds #:nodoc: extend ActiveSupport::Concern included do - extlib_inheritable_accessor :responder, :mimes_for_respond_to, :instance_writer => false + class_attribute :responder, :mimes_for_respond_to self.responder = ActionController::Responder clear_respond_to end @@ -38,18 +39,20 @@ module ActionController #:nodoc: only_actions = Array(options.delete(:only)) except_actions = Array(options.delete(:except)) + new = mimes_for_respond_to.dup mimes.each do |mime| mime = mime.to_sym - mimes_for_respond_to[mime] = {} - mimes_for_respond_to[mime][:only] = only_actions unless only_actions.empty? - mimes_for_respond_to[mime][:except] = except_actions unless except_actions.empty? + new[mime] = {} + new[mime][:only] = only_actions unless only_actions.empty? + new[mime][:except] = except_actions unless except_actions.empty? end + self.mimes_for_respond_to = new.freeze end # Clear all mimes in respond_to. # def clear_respond_to - self.mimes_for_respond_to = ActiveSupport::OrderedHash.new + self.mimes_for_respond_to = ActiveSupport::OrderedHash.new.freeze end end @@ -218,12 +221,12 @@ module ActionController #:nodoc: # def respond_with(*resources, &block) raise "In order to use respond_with, first you need to declare the formats your " << - "controller responds to in the class level" if mimes_for_respond_to.empty? + "controller responds to in the class level" if self.class.mimes_for_respond_to.empty? if response = retrieve_response_from_mimes(&block) options = resources.extract_options! options.merge!(:default_response => response) - (options.delete(:responder) || responder).call(self, resources, options) + (options.delete(:responder) || self.class.responder).call(self, resources, options) end end @@ -235,8 +238,8 @@ module ActionController #:nodoc: def collect_mimes_from_class_level #:nodoc: action = action_name.to_sym - mimes_for_respond_to.keys.select do |mime| - config = mimes_for_respond_to[mime] + self.class.mimes_for_respond_to.keys.select do |mime| + config = self.class.mimes_for_respond_to[mime] if config[:except] !config[:except].include?(action) diff --git a/actionpack/lib/action_controller/metal/renderers.rb b/actionpack/lib/action_controller/metal/renderers.rb index c1ba47927a..639b508746 100644 --- a/actionpack/lib/action_controller/metal/renderers.rb +++ b/actionpack/lib/action_controller/metal/renderers.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/class/attribute' + module ActionController def self.add_renderer(key, &block) Renderers.add(key, &block) @@ -7,8 +9,8 @@ module ActionController extend ActiveSupport::Concern included do - extlib_inheritable_accessor :_renderers - self._renderers = {} + class_attribute :_renderers + self._renderers = {}.freeze end module ClassMethods @@ -30,9 +32,11 @@ module ActionController end def use_renderers(*args) + new = _renderers.dup args.each do |key| - _renderers[key] = RENDERERS[key] + new[key] = RENDERERS[key] end + self._renderers = new.freeze _write_render_options end alias use_renderer use_renderers diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb index f1fb4d7ce5..276c703307 100644 --- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb +++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/class/attribute' + module ActionController #:nodoc: class InvalidAuthenticityToken < ActionControllerError #:nodoc: end @@ -13,7 +15,7 @@ module ActionController #:nodoc: cattr_accessor :request_forgery_protection_token # Controls whether request forgergy protection is turned on or not. Turned off by default only in test mode. - extlib_inheritable_accessor :allow_forgery_protection + class_attribute :allow_forgery_protection self.allow_forgery_protection = true helper_method :form_authenticity_token @@ -107,7 +109,7 @@ module ActionController #:nodoc: end def protect_against_forgery? - allow_forgery_protection + self.class.allow_forgery_protection end end end diff --git a/actionpack/lib/action_controller/metal/testing.rb b/actionpack/lib/action_controller/metal/testing.rb index d62269b9af..707ad968f4 100644 --- a/actionpack/lib/action_controller/metal/testing.rb +++ b/actionpack/lib/action_controller/metal/testing.rb @@ -4,7 +4,7 @@ module ActionController include RackDelegation - # OMG MEGA HAX + # TODO: Clean this up def process_with_new_base_test(request, response) @_request = request @_response = response diff --git a/actionpack/lib/action_controller/metal/url_for.rb b/actionpack/lib/action_controller/metal/url_for.rb index 387e6a554b..51702368c1 100644 --- a/actionpack/lib/action_controller/metal/url_for.rb +++ b/actionpack/lib/action_controller/metal/url_for.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/class/attribute' + module ActionController # In <b>routes.rb</b> one defines URL-to-controller mappings, but the reverse # is also possible: an URL can be generated from one of your routing definitions. @@ -85,9 +87,8 @@ module ActionController included do ActionController::Routing::Routes.install_helpers(self) - extlib_inheritable_accessor :default_url_options, - :instance_writer => false, :instance_reader => false - self.default_url_options ||= {} + class_attribute :default_url_options + self.default_url_options = {} end # Overwrite to implement a number of default options that all url_for-based methods will use. The default options should come in diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index 93aa69c060..483be47adf 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -35,7 +35,6 @@ module ActionView autoload :Context autoload :Template autoload :Helpers - autoload :SafeBuffer autoload_under "render" do autoload :Partials @@ -56,7 +55,7 @@ module ActionView autoload :TestCase, 'action_view/test_case' end -require 'action_view/erb/util' +require 'active_support/core_ext/string/output_safety' require 'action_view/base' I18n.load_path << "#{File.dirname(__FILE__)}/action_view/locale/en.yml" diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 07ef3f2140..4096c296c3 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -1,5 +1,6 @@ require 'active_support/core_ext/module/attr_internal' require 'active_support/core_ext/module/delegation' +require 'active_support/core_ext/class/attribute' module ActionView #:nodoc: class ActionViewError < StandardError #:nodoc: @@ -244,7 +245,7 @@ module ActionView #:nodoc: ActionView::PathSet.new(Array(value)) end - extlib_inheritable_accessor :helpers + class_attribute :helpers attr_reader :helpers def self.for_controller(controller) @@ -284,7 +285,7 @@ module ActionView #:nodoc: @helpers = self.class.helpers || Module.new @_controller = controller - @_content_for = Hash.new {|h,k| h[k] = ActionView::SafeBuffer.new } + @_content_for = Hash.new {|h,k| h[k] = ActiveSupport::SafeBuffer.new } @_virtual_path = nil self.view_paths = view_paths end diff --git a/actionpack/lib/action_view/erb/util.rb b/actionpack/lib/action_view/erb/util.rb deleted file mode 100644 index aef859b3ac..0000000000 --- a/actionpack/lib/action_view/erb/util.rb +++ /dev/null @@ -1,49 +0,0 @@ -require 'erb' - -class ERB - module Util - HTML_ESCAPE = { '&' => '&', '>' => '>', '<' => '<', '"' => '"' } - JSON_ESCAPE = { '&' => '\u0026', '>' => '\u003E', '<' => '\u003C' } - - # A utility method for escaping HTML tag characters. - # This method is also aliased as <tt>h</tt>. - # - # In your ERb templates, use this method to escape any unsafe content. For example: - # <%=h @person.name %> - # - # ==== Example: - # puts html_escape("is a > 0 & a < 10?") - # # => is a > 0 & a < 10? - def html_escape(s) - s = s.to_s - if s.html_safe? - s - else - s.gsub(/[&"><]/) { |special| HTML_ESCAPE[special] }.html_safe! - end - end - - undef :h - alias h html_escape - - module_function :html_escape - module_function :h - - # A utility method for escaping HTML entities in JSON strings. - # This method is also aliased as <tt>j</tt>. - # - # In your ERb templates, use this method to escape any HTML entities: - # <%=j @person.to_json %> - # - # ==== Example: - # puts json_escape("is a > 0 & a < 10?") - # # => is a \u003E 0 \u0026 a \u003C 10? - def json_escape(s) - s.to_s.gsub(/[&"><]/) { |special| JSON_ESCAPE[special] } - end - - alias j json_escape - module_function :j - module_function :json_escape - end -end diff --git a/actionpack/lib/action_view/helpers/active_model_helper.rb b/actionpack/lib/action_view/helpers/active_model_helper.rb index 87b7adf6c4..e106bb0897 100644 --- a/actionpack/lib/action_view/helpers/active_model_helper.rb +++ b/actionpack/lib/action_view/helpers/active_model_helper.rb @@ -6,7 +6,7 @@ require 'active_support/core_ext/kernel/reporting' module ActionView class Base - @@field_error_proc = Proc.new{ |html_tag, instance| "<div class=\"fieldWithErrors\">#{html_tag}</div>".html_safe! } + @@field_error_proc = Proc.new{ |html_tag, instance| "<div class=\"fieldWithErrors\">#{html_tag}</div>".html_safe } cattr_accessor :field_error_proc end @@ -86,12 +86,11 @@ module ActionView submit_value = options[:submit_value] || options[:action].gsub(/[^\w]/, '').capitalize contents = form_tag({:action => action}, :method =>(options[:method] || 'post'), :enctype => options[:multipart] ? 'multipart/form-data': nil) - contents << hidden_field(record_name, :id) unless record.new_record? - contents << all_input_tags(record, record_name, options) + contents.safe_concat hidden_field(record_name, :id) unless record.new_record? + contents.safe_concat all_input_tags(record, record_name, options) yield contents if block_given? - contents << submit_tag(submit_value) - contents << '</form>' - contents.html_safe! + contents.safe_concat submit_tag(submit_value) + contents.safe_concat('</form>') end # Returns a string containing the error message attached to the +method+ on the +object+ if one exists. diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb index 4df99f8293..96976ce45f 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb @@ -293,7 +293,7 @@ module ActionView else sources = expand_javascript_sources(sources, recursive) ensure_javascript_sources!(sources) if cache - sources.collect { |source| javascript_src_tag(source, options) }.join("\n").html_safe! + sources.collect { |source| javascript_src_tag(source, options) }.join("\n").html_safe end end @@ -444,7 +444,7 @@ module ActionView else sources = expand_stylesheet_sources(sources, recursive) ensure_stylesheet_sources!(sources) if cache - sources.collect { |source| stylesheet_tag(source, options) }.join("\n").html_safe! + sources.collect { |source| stylesheet_tag(source, options) }.join("\n").html_safe end end @@ -588,7 +588,7 @@ module ActionView if sources.is_a?(Array) content_tag("video", options) do - sources.map { |source| tag("source", :src => source) }.join.html_safe! + sources.map { |source| tag("source", :src => source) }.join.html_safe end else options[:src] = path_to_video(sources) diff --git a/actionpack/lib/action_view/helpers/capture_helper.rb b/actionpack/lib/action_view/helpers/capture_helper.rb index b62df75dbb..8c48300ed3 100644 --- a/actionpack/lib/action_view/helpers/capture_helper.rb +++ b/actionpack/lib/action_view/helpers/capture_helper.rb @@ -143,7 +143,7 @@ module ActionView # Defaults to a new empty string. def with_output_buffer(buf = nil) #:nodoc: unless buf - buf = ActionView::SafeBuffer.new + buf = ActiveSupport::SafeBuffer.new buf.force_encoding(output_buffer.encoding) if buf.respond_to?(:force_encoding) end self.output_buffer, old_buffer = buf, output_buffer diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb index 34f38b0a8a..8be2f76bd6 100644 --- a/actionpack/lib/action_view/helpers/date_helper.rb +++ b/actionpack/lib/action_view/helpers/date_helper.rb @@ -616,7 +616,7 @@ module ActionView build_selects_from_types(order) else - "#{select_date}#{@options[:datetime_separator]}#{select_time}".html_safe! + "#{select_date}#{@options[:datetime_separator]}#{select_time}".html_safe end end @@ -835,7 +835,7 @@ module ActionView select_html << prompt_option_tag(type, @options[:prompt]) + "\n" if @options[:prompt] select_html << select_options_as_html.to_s - (content_tag(:select, select_html, select_options) + "\n").html_safe! + (content_tag(:select, select_html, select_options) + "\n").html_safe end # Builds a prompt option tag with supplied options or from default options @@ -865,7 +865,7 @@ module ActionView :id => input_id_from_type(type), :name => input_name_from_type(type), :value => value - }) + "\n").html_safe! + }) + "\n").html_safe end # Returns the name attribute for the input tag @@ -896,7 +896,7 @@ module ActionView separator = separator(type) unless type == order.first # don't add on last field select.insert(0, separator.to_s + send("select_#{type}").to_s) end - select.html_safe! + select.html_safe end # Returns the separator for a given datetime component @@ -916,15 +916,15 @@ module ActionView class InstanceTag #:nodoc: def to_date_select_tag(options = {}, html_options = {}) - datetime_selector(options, html_options).select_date.html_safe! + datetime_selector(options, html_options).select_date.html_safe end def to_time_select_tag(options = {}, html_options = {}) - datetime_selector(options, html_options).select_time.html_safe! + datetime_selector(options, html_options).select_time.html_safe end def to_datetime_select_tag(options = {}, html_options = {}) - datetime_selector(options, html_options).select_datetime.html_safe! + datetime_selector(options, html_options).select_datetime.html_safe end private diff --git a/actionpack/lib/action_view/helpers/debug_helper.rb b/actionpack/lib/action_view/helpers/debug_helper.rb index 885945fde3..e637dc1474 100644 --- a/actionpack/lib/action_view/helpers/debug_helper.rb +++ b/actionpack/lib/action_view/helpers/debug_helper.rb @@ -27,10 +27,10 @@ module ActionView def debug(object) begin Marshal::dump(object) - "<pre class='debug_dump'>#{h(object.to_yaml).gsub(" ", " ")}</pre>".html_safe! + "<pre class='debug_dump'>#{h(object.to_yaml).gsub(" ", " ")}</pre>".html_safe rescue Exception => e # errors from Marshal or YAML # Object couldn't be dumped, perhaps because of singleton methods -- this is the fallback - "<code class='debug_dump'>#{h(object.inspect)}</code>".html_safe! + "<code class='debug_dump'>#{h(object.inspect)}</code>".html_safe end end end diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 157deebe40..1d91b6957a 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -225,6 +225,33 @@ module ActionView # ... # <% end %> # + # === Unobtrusive JavaScript + # + # Specifying: + # + # :remote => true + # + # in the options hash creates a form that will allow the unobtrusive JavaScript drivers to modify its + # behaviour. The expected default behaviour is an XMLHttpRequest in the background instead of the regular + # POST arrangement, but ultimately the behaviour is the choice of the JavaScript driver implementor. + # Even though it's using JavaScript to serialize the form elements, the form submission will work just like + # a regular submission as viewed by the receiving side (all elements available in <tt>params</tt>). + # + # Example: + # + # <% form_for(:post, @post, :remote => true, :html => { :id => 'create-post', :method => :put }) do |f| %> + # ... + # <% end %> + # + # The HTML generated for this would be: + # + # <form action='http://www.example.com' id='create-post' method='post' data-remote='true'> + # <div style='margin:0;padding:0;display:inline'> + # <input name='_method' type='hidden' value='put' /> + # </div> + # ... + # </form> + # # === Customized form builders # # You can also build forms using a customized FormBuilder class. Subclass @@ -280,9 +307,11 @@ module ActionView args.unshift object end + options[:html][:remote] = true if options.delete(:remote) + concat(form_tag(options.delete(:url) || {}, options.delete(:html) || {})) fields_for(object_name, *(args << options), &proc) - concat('</form>'.html_safe!) + safe_concat('</form>') end def apply_form_for_options!(object_or_array, options) #:nodoc: @@ -850,7 +879,7 @@ module ActionView end hidden = tag("input", "name" => options["name"], "type" => "hidden", "value" => options['disabled'] && checked ? checked_value : unchecked_value) checkbox = tag("input", options) - (hidden + checkbox).html_safe! + (hidden + checkbox).html_safe end def to_boolean_select_tag(options = {}) diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb index d3e614b98f..21acfbbee8 100644 --- a/actionpack/lib/action_view/helpers/form_options_helper.rb +++ b/actionpack/lib/action_view/helpers/form_options_helper.rb @@ -296,7 +296,7 @@ module ActionView options << %(<option value="#{html_escape(value.to_s)}"#{selected_attribute}#{disabled_attribute}>#{html_escape(text.to_s)}</option>) end - options_for_select.join("\n").html_safe! + options_for_select.join("\n").html_safe end # Returns a string of option tags that have been compiled by iterating over the +collection+ and assigning the diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb index fb32f78e5b..9b8471c6c6 100644 --- a/actionpack/lib/action_view/helpers/form_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb @@ -19,6 +19,8 @@ module ActionView # If "put", "delete", or another verb is used, a hidden input with name <tt>_method</tt> # is added to simulate the verb over post. # * A list of parameters to feed to the URL the form will be posted to. + # * <tt>:remote</tt> - If set to true, will allow the Unobtrusive JavaScript drivers to control the + # submit behaviour. By default this behaviour is an ajax submit. # # ==== Examples # form_tag('/posts') @@ -30,10 +32,14 @@ module ActionView # form_tag('/upload', :multipart => true) # # => <form action="/upload" method="post" enctype="multipart/form-data"> # - # <% form_tag '/posts' do -%> + # <% form_tag('/posts')do -%> # <div><%= submit_tag 'Save' %></div> # <% end -%> # # => <form action="/posts" method="post"><div><input type="submit" name="submit" value="Save" /></div></form> + # + # <% form_tag('/posts', :remote => true) %> + # # => <form action="/posts" method="post" data-remote="true"> + # def form_tag(url_for_options = {}, options = {}, *parameters_for_url, &block) html_options = html_options_for_form(url_for_options, options, *parameters_for_url) if block_given? @@ -333,12 +339,13 @@ module ActionView # Creates a submit button with the text <tt>value</tt> as the caption. # # ==== Options - # * <tt>:confirm => 'question?'</tt> - This will add a JavaScript confirm - # prompt with the question specified. If the user accepts, the form is - # processed normally, otherwise no action is taken. + # * <tt>:confirm => 'question?'</tt> - If present the unobtrusive JavaScript + # drivers will provide a prompt with the question specified. If the user accepts, + # the form is processed normally, otherwise no action is taken. # * <tt>:disabled</tt> - If true, the user will not be able to use this input. - # * <tt>:disable_with</tt> - Value of this parameter will be used as the value for a disabled version - # of the submit button when the form is submitted. + # * <tt>:disable_with</tt> - Value of this parameter will be used as the value for a + # disabled version of the submit button when the form is submitted. This feature is + # provided by the unobtrusive JavaScript driver. # * Any other key creates standard HTML options for the tag. # # ==== Examples @@ -351,16 +358,22 @@ module ActionView # submit_tag "Save edits", :disabled => true # # => <input disabled="disabled" name="commit" type="submit" value="Save edits" /> # + # # submit_tag "Complete sale", :disable_with => "Please wait..." - # # => <input name="commit" onclick="this.disabled=true;this.value='Please wait...';this.form.submit();" + # # => <input name="commit" data-disable-with="Please wait..." # # type="submit" value="Complete sale" /> # # submit_tag nil, :class => "form_submit" # # => <input class="form_submit" name="commit" type="submit" /> # # submit_tag "Edit", :disable_with => "Editing...", :class => "edit-button" - # # => <input class="edit-button" onclick="this.disabled=true;this.value='Editing...';this.form.submit();" + # # => <input class="edit-button" data-disable_with="Editing..." # # name="commit" type="submit" value="Edit" /> + # + # submit_tag "Save", :confirm => "Are you sure?" + # # => <input name='commit' type='submit' value='Save' + # data-confirm="Are you sure?" /> + # def submit_tag(value = "Save changes", options = {}) options.stringify_keys! @@ -433,7 +446,7 @@ module ActionView concat(tag(:fieldset, options, true)) concat(content_tag(:legend, legend)) unless legend.blank? concat(content) - concat("</fieldset>".html_safe!) + safe_concat("</fieldset>") end private @@ -441,6 +454,7 @@ module ActionView returning options.stringify_keys do |html_options| html_options["enctype"] = "multipart/form-data" if html_options.delete("multipart") html_options["action"] = url_for(url_for_options, *parameters_for_url) + html_options["data-remote"] = true if html_options.delete("remote") end end @@ -460,14 +474,14 @@ module ActionView def form_tag_html(html_options) extra_tags = extra_tags_for_form(html_options) - (tag(:form, html_options, true) + extra_tags).html_safe! + (tag(:form, html_options, true) + extra_tags).html_safe end def form_tag_in_block(html_options, &block) content = capture(&block) concat(form_tag_html(html_options)) concat(content) - concat("</form>".html_safe!) + safe_concat("</form>") end def token_tag diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb index 64b71663c3..3d3502a08b 100644 --- a/actionpack/lib/action_view/helpers/number_helper.rb +++ b/actionpack/lib/action_view/helpers/number_helper.rb @@ -92,7 +92,7 @@ module ActionView :precision => precision, :delimiter => delimiter, :separator => separator) - ).gsub(/%u/, unit).html_safe! + ).gsub(/%u/, unit).html_safe rescue number end diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb index d335d89274..7eb6bceca0 100644 --- a/actionpack/lib/action_view/helpers/prototype_helper.rb +++ b/actionpack/lib/action_view/helpers/prototype_helper.rb @@ -610,7 +610,7 @@ module ActionView # page.hide 'spinner' # end def update_page(&block) - JavaScriptGenerator.new(@template, &block).to_s.html_safe! + JavaScriptGenerator.new(@template, &block).to_s.html_safe end # Works like update_page but wraps the generated JavaScript in a <script> diff --git a/actionpack/lib/action_view/helpers/raw_output_helper.rb b/actionpack/lib/action_view/helpers/raw_output_helper.rb index 79b0e4ee75..8c7f41177d 100644 --- a/actionpack/lib/action_view/helpers/raw_output_helper.rb +++ b/actionpack/lib/action_view/helpers/raw_output_helper.rb @@ -2,7 +2,7 @@ module ActionView #:nodoc: module Helpers #:nodoc: module RawOutputHelper def raw(stringish) - stringish.to_s.html_safe! + stringish.to_s.html_safe end end end diff --git a/actionpack/lib/action_view/helpers/sanitize_helper.rb b/actionpack/lib/action_view/helpers/sanitize_helper.rb index 657d26f0a2..28e40f8560 100644 --- a/actionpack/lib/action_view/helpers/sanitize_helper.rb +++ b/actionpack/lib/action_view/helpers/sanitize_helper.rb @@ -50,11 +50,7 @@ module ActionView # confuse browsers. # def sanitize(html, options = {}) - returning self.class.white_list_sanitizer.sanitize(html, options) do |sanitized| - if sanitized - sanitized.html_safe! - end - end + self.class.white_list_sanitizer.sanitize(html, options).try(:html_safe) end # Sanitizes a block of CSS code. Used by +sanitize+ when it comes across a style attribute. @@ -77,11 +73,7 @@ module ActionView # strip_tags("<div id='top-bar'>Welcome to my website!</div>") # # => Welcome to my website! def strip_tags(html) - returning self.class.full_sanitizer.sanitize(html) do |sanitized| - if sanitized - sanitized.html_safe! - end - end + self.class.full_sanitizer.sanitize(html).try(:html_safe) end # Strips all link tags from +text+ leaving just the link text. diff --git a/actionpack/lib/action_view/helpers/tag_helper.rb b/actionpack/lib/action_view/helpers/tag_helper.rb index ceddbd8cc1..ed80e07c78 100644 --- a/actionpack/lib/action_view/helpers/tag_helper.rb +++ b/actionpack/lib/action_view/helpers/tag_helper.rb @@ -1,4 +1,3 @@ -require 'action_view/erb/util' require 'set' module ActionView @@ -41,7 +40,7 @@ module ActionView # tag("img", { :src => "open & shut.png" }, false, false) # # => <img src="open & shut.png" /> def tag(name, options = nil, open = false, escape = true) - "<#{name}#{tag_options(options, escape) if options}#{open ? ">" : " />"}".html_safe! + "<#{name}#{tag_options(options, escape) if options}#{open ? ">" : " />"}".html_safe end # Returns an HTML block tag of type +name+ surrounding the +content+. Add @@ -94,7 +93,7 @@ module ActionView # cdata_section(File.read("hello_world.txt")) # # => <![CDATA[<hello from a text file]]> def cdata_section(content) - "<![CDATA[#{content}]]>".html_safe! + "<![CDATA[#{content}]]>".html_safe end # Returns an escaped version of +html+ without affecting existing escaped entities. @@ -128,7 +127,7 @@ module ActionView def content_tag_string(name, content, options, escape = true) tag_options = tag_options(options, escape) if options - "<#{name}#{tag_options}>#{content}</#{name}>".html_safe! + "<#{name}#{tag_options}>#{content}</#{name}>".html_safe end def tag_options(options, escape = true) @@ -143,7 +142,7 @@ module ActionView attrs << %(#{key}="#{final_value}") end end - " #{attrs.sort * ' '}".html_safe! unless attrs.empty? + " #{attrs.sort * ' '}".html_safe unless attrs.empty? end end end diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index 814d86812d..412e0c82cb 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -24,14 +24,14 @@ module ActionView # end # # will either display "Logged in!" or a login link # %> - def concat(string, unused_binding = nil) - if unused_binding - ActiveSupport::Deprecation.warn("The binding argument of #concat is no longer needed. Please remove it from your views and helpers.", caller) - end - + def concat(string) output_buffer << string end + def safe_concat(string) + output_buffer.safe_concat(string) + end + # Truncates a given +text+ after a given <tt>:length</tt> if +text+ is longer than <tt>:length</tt> # (defaults to 30). The last characters will be replaced with the <tt>:omission</tt> (defaults to "...") # for a total length not exceeding <tt>:length</tt>. diff --git a/actionpack/lib/action_view/helpers/translation_helper.rb b/actionpack/lib/action_view/helpers/translation_helper.rb index ad18339c60..c348ea7a0d 100644 --- a/actionpack/lib/action_view/helpers/translation_helper.rb +++ b/actionpack/lib/action_view/helpers/translation_helper.rb @@ -12,7 +12,7 @@ module ActionView # prepend the key with a period, nothing is converted. def translate(key, options = {}) options[:raise] = true - I18n.translate(scope_key_by_partial(key), options).html_safe! + I18n.translate(scope_key_by_partial(key), options).html_safe rescue I18n::MissingTranslationData => e keys = I18n.send(:normalize_translation_keys, e.locale, e.key, e.options[:scope]) content_tag('span', keys.join(', '), :class => 'translation_missing') diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb index bd179ef0b3..168a3bdbc0 100644 --- a/actionpack/lib/action_view/helpers/url_helper.rb +++ b/actionpack/lib/action_view/helpers/url_helper.rb @@ -98,7 +98,7 @@ module ActionView polymorphic_path(options) end - escape ? escape_once(url).html_safe! : url + escape ? escape_once(url).html_safe : url end # Creates a link tag of the given +name+ using a URL created by the set @@ -117,8 +117,8 @@ module ActionView # end # # ==== Options - # * <tt>:confirm => 'question?'</tt> - This will add a JavaScript confirm - # prompt with the question specified. If the user accepts, the link is + # * <tt>:confirm => 'question?'</tt> - This will allow the unobtrusive JavaScript + # driver to prompt with the question specified. If the user accepts, the link is # processed normally, otherwise no action is taken. # * <tt>:method => symbol of HTTP verb</tt> - This modifier will dynamically # create an HTML form and immediately submit the form for processing using @@ -195,23 +195,20 @@ module ActionView # link_to "Nonsense search", searches_path(:foo => "bar", :baz => "quux") # # => <a href="/searches?foo=bar&baz=quux">Nonsense search</a> # - # The three options specific to +link_to+ (<tt>:confirm</tt> and <tt>:method</tt>) are used as follows: + # The two options specific to +link_to+ (<tt>:confirm</tt> and <tt>:method</tt>) are used as follows: # # link_to "Visit Other Site", "http://www.rubyonrails.org/", :confirm => "Are you sure?" - # # => <a href="http://www.rubyonrails.org/" onclick="return confirm('Are you sure?');">Visit Other Site</a> - # - # link_to "Delete Image", @image, :confirm => "Are you sure?", :method => :delete - # # => <a href="/images/9" onclick="if (confirm('Are you sure?')) { var f = document.createElement('form'); - # f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href; - # var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); - # m.setAttribute('value', 'delete');var s = document.createElement('input'); s.setAttribute('type', 'hidden'); - # s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', 'Q/ttlxPYZ6R77B+vZ1sBkhj21G2isO9dpE6UtOHBApg='); - # f.appendChild(s)f.appendChild(m);f.submit(); };return false;">Delete Image</a> + # # => <a href="http://www.rubyonrails.org/" data-confirm="Are you sure?"">Visit Other Site</a> + # + # link_to("Destroy", "http://www.example.com", :method => :delete, :confirm => "Are you sure?") + # # => <a href='http://www.example.com' rel="nofollow" data-method="delete" data-confirm="Are you sure?">Destroy</a> + + # def link_to(*args, &block) if block_given? options = args.first || {} html_options = args.second - concat(link_to(capture(&block), options, html_options).html_safe!) + safe_concat(link_to(capture(&block), options, html_options)) else name = args[0] options = args[1] || {} @@ -229,7 +226,7 @@ module ActionView end href_attr = "href=\"#{url}\"" unless href - "<a #{href_attr}#{tag_options}>#{ERB::Util.h(name || url)}</a>".html_safe! + "<a #{href_attr}#{tag_options}>#{ERB::Util.h(name || url)}</a>".html_safe end end @@ -256,9 +253,11 @@ module ActionView # There are a few special +html_options+: # * <tt>:method</tt> - Specifies the anchor name to be appended to the path. # * <tt>:disabled</tt> - Specifies the anchor name to be appended to the path. - # * <tt>:confirm</tt> - This will add a JavaScript confirm + # * <tt>:confirm</tt> - This will use the unobtrusive JavaScript driver to # prompt with the question specified. If the user accepts, the link is # processed normally, otherwise no action is taken. + # * <tt>:remote</tt> - If set to true, will allow the Unobtrusive JavaScript drivers to control the + # submit behaviour. By default this behaviour is an ajax submit. # # ==== Examples # <%= button_to "New", :action => "new" %> @@ -266,15 +265,27 @@ module ActionView # # <div><input value="New" type="submit" /></div> # # </form>" # - # button_to "Delete Image", { :action => "delete", :id => @image.id }, - # :confirm => "Are you sure?", :method => :delete + # + # <%= button_to "Delete Image", { :action => "delete", :id => @image.id }, + # :confirm => "Are you sure?", :method => :delete %> # # => "<form method="post" action="/images/delete/1" class="button-to"> # # <div> # # <input type="hidden" name="_method" value="delete" /> - # # <input onclick="return confirm('Are you sure?');" - # # value="Delete" type="submit" /> + # # <input data-confirm='Are you sure?' value="Delete" type="submit" /> # # </div> # # </form>" + # + # + # <%= button_to('Destroy', 'http://www.example.com', :confirm => 'Are you sure?', + # :method => "delete", :remote => true, :disable_with => 'loading...') %> + # # => "<form class='button-to' method='post' action='http://www.example.com' data-remote='true'> + # # <div> + # # <input name='_method' value='delete' type='hidden' /> + # # <input value='Destroy' type='submit' disable_with='loading...' data-confirm='Are you sure?' /> + # # </div> + # # </form>" + # # + def button_to(name, options = {}, html_options = {}) html_options = html_options.stringify_keys convert_boolean_attributes!(html_options, %w( disabled )) @@ -286,6 +297,8 @@ module ActionView form_method = method.to_s == 'get' ? 'get' : 'post' + remote = html_options.delete('remote') + request_token_tag = '' if form_method == 'post' && protect_against_forgery? request_token_tag = tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token) @@ -298,8 +311,8 @@ module ActionView html_options.merge!("type" => "submit", "value" => name) - ("<form method=\"#{form_method}\" action=\"#{escape_once url}\" class=\"button-to\"><div>" + - method_tag + tag("input", html_options) + request_token_tag + "</div></form>").html_safe! + ("<form method=\"#{form_method}\" action=\"#{escape_once url}\" #{"data-remote=\"true\"" if remote} class=\"button-to\"><div>" + + method_tag + tag("input", html_options) + request_token_tag + "</div></form>").html_safe end @@ -565,14 +578,8 @@ module ActionView method, href = html_options.delete("method"), html_options['href'] - if confirm && method - add_confirm_to_attributes!(html_options, confirm) - add_method_to_attributes!(html_options, method) - elsif confirm - add_confirm_to_attributes!(html_options, confirm) - elsif method - add_method_to_attributes!(html_options, method) - end + add_confirm_to_attributes!(html_options, confirm) if confirm + add_method_to_attributes!(html_options, method) if method html_options["data-url"] = options[:url] if options.is_a?(Hash) && options[:url] diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb index 8c936ae09e..8b6dce0c1c 100644 --- a/actionpack/lib/action_view/render/partials.rb +++ b/actionpack/lib/action_view/render/partials.rb @@ -240,7 +240,7 @@ module ActionView end result = @template ? collection_with_template : collection_without_template - result.join(spacer).html_safe! + result.join(spacer).html_safe end def collection_with_template(template = @template) diff --git a/actionpack/lib/action_view/safe_buffer.rb b/actionpack/lib/action_view/safe_buffer.rb deleted file mode 100644 index 6be05b9e1e..0000000000 --- a/actionpack/lib/action_view/safe_buffer.rb +++ /dev/null @@ -1,27 +0,0 @@ -module ActionView #:nodoc: - class SafeBuffer < String - def <<(value) - if value.html_safe? - super(value) - else - super(ERB::Util.h(value)) - end - end - - def concat(value) - self << value - end - - def html_safe? - true - end - - def html_safe! - self - end - - def to_s - self - end - end -end
\ No newline at end of file diff --git a/actionpack/lib/action_view/template/handler.rb b/actionpack/lib/action_view/template/handler.rb index 221d1bd5c5..8ecc911519 100644 --- a/actionpack/lib/action_view/template/handler.rb +++ b/actionpack/lib/action_view/template/handler.rb @@ -1,5 +1,5 @@ -require "active_support/core_ext/class/inheritable_attributes" require "action_dispatch/http/mime_type" +require 'active_support/core_ext/class/attribute' # Legacy TemplateHandler stub module ActionView @@ -23,7 +23,7 @@ module ActionView end class Template::Handler - extlib_inheritable_accessor :default_format + class_attribute :default_format self.default_format = Mime::HTML def self.call(template) diff --git a/actionpack/lib/action_view/template/handlers/erb.rb b/actionpack/lib/action_view/template/handlers/erb.rb index 93a4315108..4573a440d1 100644 --- a/actionpack/lib/action_view/template/handlers/erb.rb +++ b/actionpack/lib/action_view/template/handlers/erb.rb @@ -6,7 +6,7 @@ module ActionView module Template::Handlers class Erubis < ::Erubis::Eruby def add_preamble(src) - src << "@output_buffer = ActionView::SafeBuffer.new;" + src << "@output_buffer = ActiveSupport::SafeBuffer.new;" end def add_text(src, text) @@ -15,7 +15,11 @@ module ActionView end def add_expr_literal(src, code) - src << '@output_buffer << ((' << code << ').to_s);' + if code =~ /\s*raw\s+(.*)/ + src << "@output_buffer.safe_concat((" << $1 << ").to_s);" + else + src << '@output_buffer << ((' << code << ').to_s);' + end end def add_expr_escaped(src, code) diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb index 340a6afe5e..6878067f7c 100644 --- a/actionpack/lib/action_view/template/resolver.rb +++ b/actionpack/lib/action_view/template/resolver.rb @@ -1,5 +1,6 @@ require "pathname" require "active_support/core_ext/class" +require "active_support/core_ext/array/wrap" require "action_view/template" module ActionView @@ -11,7 +12,7 @@ module ActionView def self.register_detail(name, options = {}) registered_details[name] = lambda do |val| - val ||= yield + val = Array.wrap(val || yield) val |= [nil] unless options[:allow_nil] == false val end @@ -141,8 +142,7 @@ module ActionView end end - # OMG HAX - # TODO: remove hax + # TODO: remove hack class FileSystemResolverWithFallback < Resolver def initialize(path, options = {}) super(options) diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb index 16d66b6eca..fc29acea6d 100644 --- a/actionpack/lib/action_view/test_case.rb +++ b/actionpack/lib/action_view/test_case.rb @@ -1,3 +1,5 @@ +require 'action_controller/test_case' + module ActionView class Base alias_method :initialize_without_template_tracking, :initialize @@ -51,7 +53,7 @@ module ActionView setup :setup_with_controller def setup_with_controller @controller = TestController.new - @output_buffer = ActionView::SafeBuffer.new + @output_buffer = ActiveSupport::SafeBuffer.new @rendered = '' self.class.send(:include_helper_modules!) diff --git a/actionpack/test/abstract/layouts_test.rb b/actionpack/test/abstract/layouts_test.rb index bf02e5a864..b6d89ea489 100644 --- a/actionpack/test/abstract/layouts_test.rb +++ b/actionpack/test/abstract/layouts_test.rb @@ -13,7 +13,7 @@ module AbstractControllerTests "layouts/hello_override.erb" => "With Override <%= yield %>", "layouts/abstract_controller_tests/layouts/with_string_implied_child.erb" => "With Implied <%= yield %>", - "layouts/omg.erb" => "OMGHI2U <%= yield %>", + "layouts/overwrite.erb" => "Overwrite <%= yield %>", "layouts/with_false_layout.erb" => "False Layout <%= yield %>" )] end @@ -42,7 +42,7 @@ module AbstractControllerTests end def overwrite_string - render :_template => ActionView::Template::Text.new("Hello string!"), :layout => "omg" + render :_template => ActionView::Template::Text.new("Hello string!"), :layout => "overwrite" end def overwrite_skip @@ -68,7 +68,7 @@ module AbstractControllerTests end class WithProc < Base - layout proc { |c| "omg" } + layout proc { |c| "overwrite" } def index render :_template => ActionView::Template::Text.new("Hello proc!") @@ -83,7 +83,7 @@ module AbstractControllerTests end private def hello - "omg" + "overwrite" end end @@ -122,7 +122,7 @@ module AbstractControllerTests end class WithSymbolAndNoMethod < Base - layout :omg_no_method + layout :no_method def index render :_template => ActionView::Template::Text.new("Hello boom!") @@ -175,7 +175,7 @@ module AbstractControllerTests test "when layout is overwriten by string in render, render new layout" do controller = WithString.new controller.process(:overwrite_string) - assert_equal "OMGHI2U Hello string!", controller.response_body + assert_equal "Overwrite Hello string!", controller.response_body end test "when layout is overwriten by false in render, render no layout" do @@ -209,13 +209,13 @@ module AbstractControllerTests test "when layout is specified as a proc, call it and use the layout returned" do controller = WithProc.new controller.process(:index) - assert_equal "OMGHI2U Hello proc!", controller.response_body + assert_equal "Overwrite Hello proc!", controller.response_body end test "when layout is specified as a symbol, call the requested method and use the layout returned" do controller = WithSymbol.new controller.process(:index) - assert_equal "OMGHI2U Hello symbol!", controller.response_body + assert_equal "Overwrite Hello symbol!", controller.response_body end test "when layout is specified as a symbol and the method returns nil, don't use a layout" do @@ -266,7 +266,7 @@ module AbstractControllerTests test "raises an exception when specifying layout true" do assert_raises ArgumentError do Object.class_eval do - class ::BadOmgFailLolLayout < AbstractControllerTests::Layouts::Base + class ::BadFailLayout < AbstractControllerTests::Layouts::Base layout true end end diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index 7b04638ccc..867e50d5b9 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -1,10 +1,4 @@ -begin - require File.expand_path('../../../vendor/gems/environment', __FILE__) -rescue LoadError -end - -lib = File.expand_path('../../lib', __FILE__) -$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib) +require File.expand_path('../../../load_paths', __FILE__) $:.unshift(File.dirname(__FILE__) + '/lib') $:.unshift(File.dirname(__FILE__) + '/fixtures/helpers') @@ -20,9 +14,6 @@ require 'action_view/base' require 'action_dispatch' require 'fixture_template' require 'active_support/dependencies' - -activemodel_path = File.expand_path('../../../activemodel/lib', __FILE__) -$:.unshift(activemodel_path) if File.directory?(activemodel_path) && !$:.include?(activemodel_path) require 'active_model' begin diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb index 8a13d1e5f1..de92fc56fd 100644 --- a/actionpack/test/controller/caching_test.rb +++ b/actionpack/test/controller/caching_test.rb @@ -611,7 +611,7 @@ class FragmentCachingTest < ActionController::TestCase @store.write('views/expensive', 'fragment content') fragment_computed = false - buffer = 'generated till now -> ' + buffer = 'generated till now -> '.html_safe @controller.fragment_for(buffer, 'expensive') { fragment_computed = true } assert fragment_computed @@ -622,7 +622,7 @@ class FragmentCachingTest < ActionController::TestCase @store.write('views/expensive', 'fragment content') fragment_computed = false - buffer = 'generated till now -> ' + buffer = 'generated till now -> '.html_safe @controller.fragment_for(buffer, 'expensive') { fragment_computed = true } assert !fragment_computed diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb index 8445428e8f..004e1369d3 100644 --- a/actionpack/test/controller/filters_test.rb +++ b/actionpack/test/controller/filters_test.rb @@ -435,7 +435,7 @@ class FilterTest < ActionController::TestCase end def non_yielding_filter - @filters << "zomg it didn't yield" + @filters << "it didn't yield" @filter_return_value end @@ -465,14 +465,14 @@ class FilterTest < ActionController::TestCase controller = NonYieldingAroundFilterController.new controller.instance_variable_set "@filter_return_value", false test_process(controller, "index") - assert_equal ["filter_one", "zomg it didn't yield"], controller.assigns['filters'] + assert_equal ["filter_one", "it didn't yield"], controller.assigns['filters'] end def test_after_filters_are_not_run_if_around_filter_does_not_yield controller = NonYieldingAroundFilterController.new controller.instance_variable_set "@filter_return_value", true test_process(controller, "index") - assert_equal ["filter_one", "zomg it didn't yield"], controller.assigns['filters'] + assert_equal ["filter_one", "it didn't yield"], controller.assigns['filters'] end def test_added_filter_to_inheritance_graph diff --git a/actionpack/test/controller/new_base/render_action_test.rb b/actionpack/test/controller/new_base/render_action_test.rb index 239f68659c..0804d7b09d 100644 --- a/actionpack/test/controller/new_base/render_action_test.rb +++ b/actionpack/test/controller/new_base/render_action_test.rb @@ -119,9 +119,9 @@ module RenderActionWithApplicationLayout # Set the view path to an application view structure with layouts self.view_paths = self.view_paths = [ActionView::FixtureResolver.new( "render_action_with_application_layout/basic/hello_world.html.erb" => "Hello World!", - "render_action_with_application_layout/basic/hello.html.builder" => "xml.p 'Omg'", - "layouts/application.html.erb" => "OHAI <%= yield %> KTHXBAI", - "layouts/greetings.html.erb" => "Greetings <%= yield %> Bai", + "render_action_with_application_layout/basic/hello.html.builder" => "xml.p 'Hello'", + "layouts/application.html.erb" => "Hi <%= yield %> OK, Bye", + "layouts/greetings.html.erb" => "Greetings <%= yield %> Bye", "layouts/builder.html.builder" => "xml.html do\n xml << yield\nend" )] @@ -156,14 +156,14 @@ module RenderActionWithApplicationLayout test "rendering implicit application.html.erb as layout" do get "/render_action_with_application_layout/basic/hello_world" - assert_body "OHAI Hello World! KTHXBAI" + assert_body "Hi Hello World! OK, Bye" assert_status 200 end test "rendering with layout => true" do get "/render_action_with_application_layout/basic/hello_world_with_layout" - assert_body "OHAI Hello World! KTHXBAI" + assert_body "Hi Hello World! OK, Bye" assert_status 200 end @@ -184,7 +184,7 @@ module RenderActionWithApplicationLayout test "rendering with layout => 'greetings'" do get "/render_action_with_application_layout/basic/hello_world_with_custom_layout" - assert_body "Greetings Hello World! Bai" + assert_body "Greetings Hello World! Bye" assert_status 200 end end @@ -194,7 +194,7 @@ module RenderActionWithApplicationLayout test "builder works with layouts" do get :with_builder_and_layout - assert_response "<html>\n<p>Omg</p>\n</html>\n" + assert_response "<html>\n<p>Hello</p>\n</html>\n" end end @@ -204,7 +204,7 @@ module RenderActionWithControllerLayout class BasicController < ActionController::Base self.view_paths = self.view_paths = [ActionView::FixtureResolver.new( "render_action_with_controller_layout/basic/hello_world.html.erb" => "Hello World!", - "layouts/render_action_with_controller_layout/basic.html.erb" => "With Controller Layout! <%= yield %> KTHXBAI" + "layouts/render_action_with_controller_layout/basic.html.erb" => "With Controller Layout! <%= yield %> Bye" )] def hello_world @@ -234,14 +234,14 @@ module RenderActionWithControllerLayout test "render hello_world and implicitly use <controller_path>.html.erb as a layout." do get "/render_action_with_controller_layout/basic/hello_world" - assert_body "With Controller Layout! Hello World! KTHXBAI" + assert_body "With Controller Layout! Hello World! Bye" assert_status 200 end test "rendering with layout => true" do get "/render_action_with_controller_layout/basic/hello_world_with_layout" - assert_body "With Controller Layout! Hello World! KTHXBAI" + assert_body "With Controller Layout! Hello World! Bye" assert_status 200 end @@ -265,8 +265,8 @@ module RenderActionWithBothLayouts class BasicController < ActionController::Base self.view_paths = [ActionView::FixtureResolver.new({ "render_action_with_both_layouts/basic/hello_world.html.erb" => "Hello World!", - "layouts/application.html.erb" => "OHAI <%= yield %> KTHXBAI", - "layouts/render_action_with_both_layouts/basic.html.erb" => "With Controller Layout! <%= yield %> KTHXBAI" + "layouts/application.html.erb" => "Oh Hi <%= yield %> Bye", + "layouts/render_action_with_both_layouts/basic.html.erb" => "With Controller Layout! <%= yield %> Bye" })] def hello_world @@ -292,14 +292,14 @@ module RenderActionWithBothLayouts test "rendering implicitly use <controller_path>.html.erb over application.html.erb as a layout" do get "/render_action_with_both_layouts/basic/hello_world" - assert_body "With Controller Layout! Hello World! KTHXBAI" + assert_body "With Controller Layout! Hello World! Bye" assert_status 200 end test "rendering with layout => true" do get "/render_action_with_both_layouts/basic/hello_world_with_layout" - assert_body "With Controller Layout! Hello World! KTHXBAI" + assert_body "With Controller Layout! Hello World! Bye" assert_status 200 end diff --git a/actionpack/test/controller/new_base/render_layout_test.rb b/actionpack/test/controller/new_base/render_layout_test.rb index 6a9668b81a..372fb66b88 100644 --- a/actionpack/test/controller/new_base/render_layout_test.rb +++ b/actionpack/test/controller/new_base/render_layout_test.rb @@ -3,10 +3,10 @@ require 'abstract_unit' module ControllerLayouts class ImplicitController < ::ApplicationController self.view_paths = [ActionView::FixtureResolver.new( - "layouts/application.html.erb" => "OMG <%= yield %> KTHXBAI", + "layouts/application.html.erb" => "Main <%= yield %> Layout", "layouts/override.html.erb" => "Override! <%= yield %>", "basic.html.erb" => "Hello world!", - "controller_layouts/implicit/layout_false.html.erb" => "hai(layout_false.html.erb)" + "controller_layouts/implicit/layout_false.html.erb" => "hi(layout_false.html.erb)" )] def index @@ -27,7 +27,7 @@ module ControllerLayouts class ImplicitNameController < ::ApplicationController self.view_paths = [ActionView::FixtureResolver.new( - "layouts/controller_layouts/implicit_name.html.erb" => "OMGIMPLICIT <%= yield %> KTHXBAI", + "layouts/controller_layouts/implicit_name.html.erb" => "Implicit <%= yield %> Layout", "basic.html.erb" => "Hello world!" )] @@ -40,14 +40,14 @@ module ControllerLayouts test "rendering a normal template, but using the implicit layout" do get "/controller_layouts/implicit/index" - assert_body "OMG Hello world! KTHXBAI" + assert_body "Main Hello world! Layout" assert_status 200 end test "rendering a normal template, but using an implicit NAMED layout" do get "/controller_layouts/implicit_name/index" - assert_body "OMGIMPLICIT Hello world! KTHXBAI" + assert_body "Implicit Hello world! Layout" assert_status 200 end @@ -63,15 +63,15 @@ module ControllerLayouts test "rendering with :layout => false leaves out the implicit layout" do get :layout_false - assert_response "hai(layout_false.html.erb)" + assert_response "hi(layout_false.html.erb)" end end class MismatchFormatController < ::ApplicationController self.view_paths = [ActionView::FixtureResolver.new( "layouts/application.html.erb" => "<html><%= yield %></html>", - "controller_layouts/mismatch_format/index.js.rjs" => "page[:test].omg", - "controller_layouts/mismatch_format/implicit.rjs" => "page[:test].omg" + "controller_layouts/mismatch_format/index.js.rjs" => "page[:test].ext", + "controller_layouts/mismatch_format/implicit.rjs" => "page[:test].ext" )] def explicit @@ -84,12 +84,12 @@ module ControllerLayouts test "if JS is selected, an HTML template is not also selected" do get :index, "format" => "js" - assert_response "$(\"test\").omg();" + assert_response "$(\"test\").ext();" end test "if JS is implicitly selected, an HTML template is not also selected" do get :implicit - assert_response "$(\"test\").omg();" + assert_response "$(\"test\").ext();" end test "if an HTML template is explicitly provides for a JS template, an error is raised" do diff --git a/actionpack/test/controller/new_base/render_partial_test.rb b/actionpack/test/controller/new_base/render_partial_test.rb index 8fddcbcd57..1a1b36a65e 100644 --- a/actionpack/test/controller/new_base/render_partial_test.rb +++ b/actionpack/test/controller/new_base/render_partial_test.rb @@ -5,7 +5,7 @@ module RenderPartial class BasicController < ActionController::Base self.view_paths = [ActionView::FixtureResolver.new( - "render_partial/basic/_basic.html.erb" => "OMG!", + "render_partial/basic/_basic.html.erb" => "BasicPartial!", "render_partial/basic/basic.html.erb" => "<%= @test_unchanged = 'goodbye' %><%= render :partial => 'basic' %><%= @test_unchanged %>" )] @@ -20,7 +20,7 @@ module RenderPartial test "rendering a partial in ActionView doesn't pull the ivars again from the controller" do get :changing - assert_response("goodbyeOMG!goodbye") + assert_response("goodbyeBasicPartial!goodbye") end end diff --git a/actionpack/test/controller/new_base/render_template_test.rb b/actionpack/test/controller/new_base/render_template_test.rb index c81b951c0d..70cebbfd89 100644 --- a/actionpack/test/controller/new_base/render_template_test.rb +++ b/actionpack/test/controller/new_base/render_template_test.rb @@ -2,18 +2,19 @@ require 'abstract_unit' module RenderTemplate class WithoutLayoutController < ActionController::Base - + self.view_paths = [ActionView::FixtureResolver.new( "test/basic.html.erb" => "Hello from basic.html.erb", "shared.html.erb" => "Elastica", "locals.html.erb" => "The secret is <%= secret %>", - "xml_template.xml.builder" => "xml.html do\n xml.p 'Hello'\nend" + "xml_template.xml.builder" => "xml.html do\n xml.p 'Hello'\nend", + "with_raw.html.erb" => "Hello <%=raw '<strong>this is raw</strong>' %>" )] - + def index render :template => "test/basic" end - + def index_without_key render "test/basic" end @@ -25,59 +26,70 @@ module RenderTemplate def in_top_directory_with_slash render :template => '/shared' end - + def in_top_directory_with_slash_without_key render '/shared' end - + def with_locals render :template => "locals", :locals => { :secret => 'area51' } end - + def builder_template render :template => "xml_template" end + + def with_raw + render :template => "with_raw" + end end - + class TestWithoutLayout < Rack::TestCase testing RenderTemplate::WithoutLayoutController - + test "rendering a normal template with full path without layout" do get :index assert_response "Hello from basic.html.erb" end - + test "rendering a normal template with full path without layout without key" do get :index_without_key assert_response "Hello from basic.html.erb" end - + test "rendering a template not in a subdirectory" do get :in_top_directory assert_response "Elastica" end - + test "rendering a template not in a subdirectory with a leading slash" do get :in_top_directory_with_slash assert_response "Elastica" end - + test "rendering a template not in a subdirectory with a leading slash without key" do get :in_top_directory_with_slash_without_key assert_response "Elastica" end - + test "rendering a template with local variables" do get :with_locals assert_response "The secret is area51" end - + test "rendering a builder template" do get :builder_template, "format" => "xml" assert_response "<html>\n <p>Hello</p>\n</html>\n" end + + test "rendering a template with <%=raw stuff %>" do + get :with_raw + + assert_body "Hello <strong>this is raw</strong>" + assert_status 200 + end end - + class WithLayoutController < ::ApplicationController self.view_paths = [ActionView::FixtureResolver.new( "test/basic.html.erb" => "Hello from basic.html.erb", @@ -85,28 +97,28 @@ module RenderTemplate "layouts/application.html.erb" => "<%= yield %>, I'm here!", "layouts/greetings.html.erb" => "<%= yield %>, I wish thee well." )] - + def index render :template => "test/basic" end - + def with_layout render :template => "test/basic", :layout => true end - + def with_layout_false render :template => "test/basic", :layout => false end - + def with_layout_nil render :template => "test/basic", :layout => nil end - + def with_custom_layout render :template => "test/basic", :layout => "greetings" end end - + class TestWithLayout < Rack::TestCase describe "Rendering with :template using implicit or explicit layout" diff --git a/actionpack/test/controller/output_escaping_test.rb b/actionpack/test/controller/output_escaping_test.rb index 7332f3f1e3..43a8c05cda 100644 --- a/actionpack/test/controller/output_escaping_test.rb +++ b/actionpack/test/controller/output_escaping_test.rb @@ -13,7 +13,7 @@ class OutputEscapingTest < ActiveSupport::TestCase test "escapeHTML shouldn't touch explicitly safe strings" do # TODO this seems easier to compose and reason about, but # this should be verified - assert_equal "<", ERB::Util.h("<".html_safe!) + assert_equal "<", ERB::Util.h("<".html_safe) end end diff --git a/actionpack/test/controller/subscriber_test.rb b/actionpack/test/controller/subscriber_test.rb index 152a0d0c04..119a18ebc5 100644 --- a/actionpack/test/controller/subscriber_test.rb +++ b/actionpack/test/controller/subscriber_test.rb @@ -13,7 +13,7 @@ module Another end def data_sender - send_data "cool data", :filename => "omg.txt" + send_data "cool data", :filename => "file.txt" end def xfile_sender @@ -121,7 +121,7 @@ class ACSubscriberTest < ActionController::TestCase wait assert_equal 3, logs.size - assert_match /Sent data omg\.txt/, logs[1] + assert_match /Sent data file\.txt/, logs[1] end def test_send_file diff --git a/actionpack/test/controller/view_paths_test.rb b/actionpack/test/controller/view_paths_test.rb index 05d2c8407c..56821332c5 100644 --- a/actionpack/test/controller/view_paths_test.rb +++ b/actionpack/test/controller/view_paths_test.rb @@ -142,9 +142,9 @@ class ViewLoadPathsTest < ActionController::TestCase assert_paths A, "a/path" assert_paths A, *B.view_paths assert_paths C, *original_load_paths - + C.view_paths = [] - assert_nothing_raised { C.view_paths << 'c/path' } + assert_nothing_raised { C.append_view_path 'c/path' } assert_paths C, "c/path" end end diff --git a/actionpack/test/dispatch/mime_type_test.rb b/actionpack/test/dispatch/mime_type_test.rb index 0832943d4c..369212e2d0 100644 --- a/actionpack/test/dispatch/mime_type_test.rb +++ b/actionpack/test/dispatch/mime_type_test.rb @@ -23,7 +23,7 @@ class MimeTypeTest < ActiveSupport::TestCase end # Accept header send with user HTTP_USER_AGENT: Sunrise/0.42j (Windows XP) - test "parse crappy broken acceptlines" do + test "parse broken acceptlines" do accept = "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/*,,*/*;q=0.5" expect = [Mime::HTML, Mime::XML, "image/*", Mime::TEXT, Mime::ALL] assert_equal expect, Mime::Type.parse(accept).collect { |c| c.to_s } @@ -31,7 +31,7 @@ class MimeTypeTest < ActiveSupport::TestCase # Accept header send with user HTTP_USER_AGENT: Mozilla/4.0 # (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; InfoPath.1) - test "parse crappy broken acceptlines2" do + test "parse other broken acceptlines" do accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, , pronto/1.00.00, sslvpn/1.00.00.00, */*" expect = ['image/gif', 'image/x-xbitmap', 'image/jpeg','image/pjpeg', 'application/x-shockwave-flash', 'application/vnd.ms-excel', 'application/vnd.ms-powerpoint', 'application/msword', 'pronto/1.00.00', 'sslvpn/1.00.00.00', Mime::ALL ] assert_equal expect, Mime::Type.parse(accept).collect { |c| c.to_s } diff --git a/actionpack/test/template/erb_util_test.rb b/actionpack/test/template/erb_util_test.rb index fa6b263965..06155b1f30 100644 --- a/actionpack/test/template/erb_util_test.rb +++ b/actionpack/test/template/erb_util_test.rb @@ -22,7 +22,7 @@ class ErbUtilTest < Test::Unit::TestCase end def test_html_escape_passes_html_escpe_unmodified - escaped = h("<p>".html_safe!) + escaped = h("<p>".html_safe) assert_equal "<p>", escaped assert escaped.html_safe? end diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb index c97343fbe5..aafc318b76 100644 --- a/actionpack/test/template/form_helper_test.rb +++ b/actionpack/test/template/form_helper_test.rb @@ -451,6 +451,25 @@ class FormHelperTest < ActionView::TestCase assert_dom_equal expected, output_buffer end + def test_form_for_with_remote + form_for(:post, @post, :remote => true, :html => { :id => 'create-post', :method => :put }) do |f| + concat f.text_field(:title) + concat f.text_area(:body) + concat f.check_box(:secret) + end + + expected = + "<form action='http://www.example.com' id='create-post' method='post' data-remote='true'>" + + "<div style='margin:0;padding:0;display:inline'><input name='_method' type='hidden' value='put' /></div>" + + "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + + "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<input name='post[secret]' type='hidden' value='0' />" + + "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" + + "</form>" + + assert_dom_equal expected, output_buffer + end + def test_form_for_without_object form_for(:post, :html => { :id => 'create-post' }) do |f| concat f.text_field(:title) @@ -1151,7 +1170,7 @@ class FormHelperTest < ActionView::TestCase (field_helpers - %w(hidden_field)).each do |selector| src = <<-END_SRC def #{selector}(field, *args, &proc) - ("<label for='\#{field}'>\#{field.to_s.humanize}:</label> " + super + "<br/>").html_safe! + ("<label for='\#{field}'>\#{field.to_s.humanize}:</label> " + super + "<br/>").html_safe end END_SRC class_eval src, __FILE__, __LINE__ diff --git a/actionpack/test/template/form_tag_helper_test.rb b/actionpack/test/template/form_tag_helper_test.rb index 01bde8ea04..3635c7548e 100644 --- a/actionpack/test/template/form_tag_helper_test.rb +++ b/actionpack/test/template/form_tag_helper_test.rb @@ -53,6 +53,12 @@ class FormTagHelperTest < ActionView::TestCase assert_dom_equal expected, actual end + def test_form_tag_with_remote + actual = form_tag({}, :remote => true) + expected = %(<form action="http://www.example.com" method="post" data-remote="true">) + assert_dom_equal expected, actual + end + def test_form_tag_with_block_in_erb __in_erb_template = '' form_tag("http://example.com") { concat "Hello world!" } @@ -329,19 +335,19 @@ class FormTagHelperTest < ActionView::TestCase expected = %(<fieldset><legend>Your details</legend>Hello world!</fieldset>) assert_dom_equal expected, output_buffer - self.output_buffer = '' + self.output_buffer = ''.html_safe field_set_tag { concat "Hello world!" } expected = %(<fieldset>Hello world!</fieldset>) assert_dom_equal expected, output_buffer - self.output_buffer = '' + self.output_buffer = ''.html_safe field_set_tag('') { concat "Hello world!" } expected = %(<fieldset>Hello world!</fieldset>) assert_dom_equal expected, output_buffer - self.output_buffer = '' + self.output_buffer = ''.html_safe field_set_tag('', :class => 'format') { concat "Hello world!" } expected = %(<fieldset class="format">Hello world!</fieldset>) diff --git a/actionpack/test/template/html-scanner/sanitizer_test.rb b/actionpack/test/template/html-scanner/sanitizer_test.rb index e85a5c7abf..a6e760b0b6 100644 --- a/actionpack/test/template/html-scanner/sanitizer_test.rb +++ b/actionpack/test/template/html-scanner/sanitizer_test.rb @@ -48,7 +48,7 @@ class SanitizerTest < ActionController::TestCase assert_sanitized "a b c<script language=\"Javascript\">blah blah blah</script>d e f", "a b cd e f" end - # fucked + # TODO: Clean up def test_sanitize_js_handlers raw = %{onthis="do that" <a href="#" onclick="hello" name="foo" onbogus="remove me">hello</a>} assert_sanitized raw, %{onthis="do that" <a name="foo" href="#">hello</a>} @@ -193,7 +193,7 @@ class SanitizerTest < ActionController::TestCase assert_sanitized img_hack, "<img>" end - # fucked + # TODO: Clean up def test_should_sanitize_attributes assert_sanitized %(<SPAN title="'><script>alert()</script>">blah</SPAN>), %(<span title="'><script>alert()</script>">blah</span>) end diff --git a/actionpack/test/template/subscriber_test.rb b/actionpack/test/template/subscriber_test.rb index 5db2b16ac1..8bacab7088 100644 --- a/actionpack/test/template/subscriber_test.rb +++ b/actionpack/test/template/subscriber_test.rb @@ -33,7 +33,7 @@ class AVSubscriberTest < ActiveSupport::TestCase end def test_render_text_template - @view.render(:text => "OMG") + @view.render(:text => "TEXT") wait assert_equal 1, @logger.logged(:info).size @@ -41,7 +41,7 @@ class AVSubscriberTest < ActiveSupport::TestCase end def test_render_inline_template - @view.render(:inline => "<%= 'OMG' %>") + @view.render(:inline => "<%= 'TEXT' %>") wait assert_equal 1, @logger.logged(:info).size diff --git a/actionpack/test/template/test_case_test.rb b/actionpack/test/template/test_case_test.rb index 9a448ce328..be2c6b3108 100644 --- a/actionpack/test/template/test_case_test.rb +++ b/actionpack/test/template/test_case_test.rb @@ -160,7 +160,7 @@ module ActionView class AssertionsTest < ActionView::TestCase def render_from_helper form_tag('/foo') do - concat render(:text => '<ul><li>foo</li></ul>').html_safe! + safe_concat render(:text => '<ul><li>foo</li></ul>') end end helper_method :render_from_helper diff --git a/actionpack/test/template/url_helper_test.rb b/actionpack/test/template/url_helper_test.rb index b498ec8429..e904e88f49 100644 --- a/actionpack/test/template/url_helper_test.rb +++ b/actionpack/test/template/url_helper_test.rb @@ -81,6 +81,13 @@ class UrlHelperTest < ActionView::TestCase ) end + def test_button_to_with_remote_and_javascript_confirm + assert_dom_equal( + "<form method=\"post\" action=\"http://www.example.com\" class=\"button-to\" data-remote=\"true\"><div><input data-confirm=\"Are you sure?\" type=\"submit\" value=\"Hello\" /></div></form>", + button_to("Hello", "http://www.example.com", :remote => true, :confirm => "Are you sure?") + ) + end + def test_button_to_enabled_disabled assert_dom_equal( "<form method=\"post\" action=\"http://www.example.com\" class=\"button-to\"><div><input type=\"submit\" value=\"Hello\" /></div></form>", diff --git a/activemodel/test/cases/helper.rb b/activemodel/test/cases/helper.rb index 917bb720d0..8bcbe54651 100644 --- a/activemodel/test/cases/helper.rb +++ b/activemodel/test/cases/helper.rb @@ -1,10 +1,4 @@ -begin - require File.expand_path('../../../../vendor/gems/environment', __FILE__) -rescue LoadError -end - -lib = File.expand_path('../../../lib', __FILE__) -$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib) +require File.expand_path('../../../../load_paths', __FILE__) require 'config' require 'active_model' diff --git a/activerecord/activerecord.gemspec b/activerecord/activerecord.gemspec index c84a3ac5a9..4fd1a0213c 100644 --- a/activerecord/activerecord.gemspec +++ b/activerecord/activerecord.gemspec @@ -9,7 +9,7 @@ Gem::Specification.new do |s| s.add_dependency('activesupport', '= 3.0.pre') s.add_dependency('activemodel', '= 3.0.pre') - s.add_dependency('arel', '= 0.2.pre') + s.add_dependency('arel', '~> 0.2.0') s.require_path = 'lib' s.autorequire = 'active_record' diff --git a/activerecord/lib/active_record/observer.rb b/activerecord/lib/active_record/observer.rb index 4e05b819b5..0fbb1f0261 100644 --- a/activerecord/lib/active_record/observer.rb +++ b/activerecord/lib/active_record/observer.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/class/attribute' + 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 @@ -85,7 +87,8 @@ module ActiveRecord # singletons and that call instantiates and registers them. # class Observer < ActiveModel::Observer - extlib_inheritable_accessor(:observed_methods){ [] } + class_attribute :observed_methods + self.observed_methods = [] def initialize super @@ -93,7 +96,7 @@ module ActiveRecord end def self.method_added(method) - observed_methods << method if ActiveRecord::Callbacks::CALLBACKS.include?(method.to_sym) + self.observed_methods += [method] if ActiveRecord::Callbacks::CALLBACKS.include?(method.to_sym) end protected @@ -106,7 +109,7 @@ module ActiveRecord # Check if a notifier callback was already added to the given class. If # it was not, add it. - self.observed_methods.each do |method| + self.class.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" diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb index fa76e2d57a..9e8bfbbee8 100644 --- a/activerecord/test/cases/helper.rb +++ b/activerecord/test/cases/helper.rb @@ -1,14 +1,7 @@ -begin - require File.expand_path('../../../../vendor/gems/environment', __FILE__) -rescue LoadError -end - -lib = File.expand_path('../../../lib', __FILE__) -$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib) +require File.expand_path('../../../../load_paths', __FILE__) require 'config' -require 'rubygems' require 'test/unit' require 'stringio' diff --git a/activeresource/test/abstract_unit.rb b/activeresource/test/abstract_unit.rb index 1e71d5d0dd..2f43916521 100644 --- a/activeresource/test/abstract_unit.rb +++ b/activeresource/test/abstract_unit.rb @@ -1,10 +1,4 @@ -begin - require File.expand_path('../../../vendor/gems/environment', __FILE__) -rescue LoadError -end - -lib = File.expand_path('../../lib', __FILE__) -$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib) +require File.expand_path('../../../load_paths', __FILE__) require 'rubygems' require 'test/unit' diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 787fa26e44..431607f4e0 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,5 +1,7 @@ *Rails 3.0 (pending)* +* Introduce class_attribute to declare inheritable class attributes. Writing an attribute on a subclass behaves just like overriding the superclass reader method. Unifies and replaces most usage of cattr_accessor, class_inheritable_attribute, superclass_delegating_attribute, and extlib_inheritable_attribute. [Jeremy Kemper, Yehuda Katz] + * Time#- with a DateTime argument behaves the same as with a Time argument, i.e. returns the difference between self and arg as a Float #3476 [Geoff Buesing] * YAML serialization for OrderedHash. #3608 [Gregor Schmidt] diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb index 833ae351b9..ae31d191c0 100644 --- a/activesupport/lib/active_support.rb +++ b/activesupport/lib/active_support.rb @@ -67,5 +67,6 @@ module ActiveSupport autoload :XmlMini end + autoload :SafeBuffer, "active_support/core_ext/string/output_safety" autoload :TestCase end diff --git a/activesupport/lib/active_support/core_ext/class/attribute.rb b/activesupport/lib/active_support/core_ext/class/attribute.rb new file mode 100644 index 0000000000..d74219cb93 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/class/attribute.rb @@ -0,0 +1,36 @@ +require 'active_support/core_ext/object/metaclass' +require 'active_support/core_ext/module/delegation' + +class Class + # Declare a class-level attribute whose value is inheritable and + # overwritable by subclasses: + # + # class Base + # class_attribute :setting + # end + # + # class Subclass < Base + # end + # + # Base.setting = true + # Subclass.setting # => true + # Subclass.setting = false + # Subclass.setting # => false + # Base.setting # => true + # + # This matches normal Ruby method inheritance: think of writing an attribute + # on a subclass as overriding the reader method. + # + # For convenience, a query method is defined as well: + # + # Subclass.setting? # => false + def class_attribute(*attrs) + attrs.each do |attr| + metaclass.send(:define_method, attr) { } + metaclass.send(:define_method, "#{attr}?") { !!send(attr) } + metaclass.send(:define_method, "#{attr}=") do |value| + metaclass.send(:define_method, attr) { value } + end + end + end +end diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb index ceed90ce79..3977971e8d 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -1,3 +1,53 @@ +require "erb" + +class ERB + module Util + HTML_ESCAPE = { '&' => '&', '>' => '>', '<' => '<', '"' => '"' } + JSON_ESCAPE = { '&' => '\u0026', '>' => '\u003E', '<' => '\u003C' } + + # A utility method for escaping HTML tag characters. + # This method is also aliased as <tt>h</tt>. + # + # In your ERb templates, use this method to escape any unsafe content. For example: + # <%=h @person.name %> + # + # ==== Example: + # puts html_escape("is a > 0 & a < 10?") + # # => is a > 0 & a < 10? + def html_escape(s) + s = s.to_s + if s.html_safe? + s + else + s.gsub(/[&"><]/) { |special| HTML_ESCAPE[special] }.html_safe + end + end + + undef :h + alias h html_escape + + module_function :html_escape + module_function :h + + # A utility method for escaping HTML entities in JSON strings. + # This method is also aliased as <tt>j</tt>. + # + # In your ERb templates, use this method to escape any HTML entities: + # <%=j @person.to_json %> + # + # ==== Example: + # puts json_escape("is a > 0 & a < 10?") + # # => is a \u003E 0 \u0026 a \u003C 10? + def json_escape(s) + s.to_s.gsub(/[&"><]/) { |special| JSON_ESCAPE[special] } + end + + alias j json_escape + module_function :j + module_function :json_escape + end +end + class Object def html_safe? false @@ -10,32 +60,46 @@ class Fixnum end end -class String - attr_accessor :_rails_html_safe - alias html_safe? _rails_html_safe +module ActiveSupport #:nodoc: + class SafeBuffer < String + alias safe_concat concat - def html_safe! - @_rails_html_safe = true - self - end + def concat(value) + if value.html_safe? + super(value) + else + super(ERB::Util.h(value)) + end + end - def html_safe - dup.html_safe! - end + def +(other) + dup.concat(other) + end + + def <<(value) + self.concat(value) + end + + def html_safe? + true + end + + def html_safe + self + end - alias original_plus + - def +(other) - result = original_plus(other) - result._rails_html_safe = html_safe? && other.html_safe? - result + def to_s + self + end end +end - alias original_concat << - alias safe_concat << - def <<(other) - @_rails_html_safe = false unless other.html_safe? - result = original_concat(other) +class String + def html_safe! + raise "You can't call html_safe! on a String" end - alias concat << + def html_safe + ActiveSupport::SafeBuffer.new(self) + end end
\ No newline at end of file diff --git a/activesupport/lib/active_support/rescuable.rb b/activesupport/lib/active_support/rescuable.rb index 6e660f8647..e4c1651acf 100644 --- a/activesupport/lib/active_support/rescuable.rb +++ b/activesupport/lib/active_support/rescuable.rb @@ -1,4 +1,4 @@ -require 'active_support/core_ext/class/inheritable_attributes' +require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/proc' require 'active_support/core_ext/string/inflections' require 'active_support/core_ext/array/extract_options' @@ -9,7 +9,7 @@ module ActiveSupport extend Concern included do - class_inheritable_accessor :rescue_handlers + class_attribute :rescue_handlers self.rescue_handlers = [] end @@ -67,7 +67,7 @@ module ActiveSupport end # put the new handler at the end because the list is read in reverse - rescue_handlers << [key, options[:with]] + self.rescue_handlers += [[key, options[:with]]] end end end @@ -83,7 +83,7 @@ module ActiveSupport def handler_for_rescue(exception) # We go from right to left because pairs are pushed onto rescue_handlers # as rescue_from declarations are found. - _, rescuer = rescue_handlers.reverse.detect do |klass_name, handler| + _, rescuer = self.class.rescue_handlers.reverse.detect do |klass_name, handler| # The purpose of allowing strings in rescue_from is to support the # declaration of handler associations for exception classes whose # definition is yet unknown. diff --git a/activesupport/test/abstract_unit.rb b/activesupport/test/abstract_unit.rb index d91e0415c4..33be6f65bf 100644 --- a/activesupport/test/abstract_unit.rb +++ b/activesupport/test/abstract_unit.rb @@ -1,12 +1,4 @@ -ORIG_ARGV = ARGV.dup - -begin - require File.expand_path('../../../vendor/gems/environment', __FILE__) -rescue LoadError -end - -lib = File.expand_path("#{File.dirname(__FILE__)}/../lib") -$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib) +require File.expand_path('../../../load_paths', __FILE__) require 'test/unit' require 'mocha' diff --git a/activesupport/test/callbacks_test.rb b/activesupport/test/callbacks_test.rb index df98644436..11494e951e 100644 --- a/activesupport/test/callbacks_test.rb +++ b/activesupport/test/callbacks_test.rb @@ -264,12 +264,12 @@ module CallbacksTest define_callbacks :save attr_reader :stuff - set_callback :save, :before, :omg, :per_key => {:if => :yes} + set_callback :save, :before, :action, :per_key => {:if => :yes} def yes() true end - def omg - @stuff = "OMG" + def action + @stuff = "ACTION" end def save @@ -522,7 +522,7 @@ module CallbacksTest def test_save obj = HyphenatedCallbacks.new obj.save - assert_equal obj.stuff, "OMG" + assert_equal obj.stuff, "ACTION" end end end diff --git a/activesupport/test/core_ext/class/attribute_test.rb b/activesupport/test/core_ext/class/attribute_test.rb new file mode 100644 index 0000000000..ef84b9f255 --- /dev/null +++ b/activesupport/test/core_ext/class/attribute_test.rb @@ -0,0 +1,47 @@ +require 'abstract_unit' +require 'active_support/core_ext/class/attribute' + +class ClassAttributeTest < ActiveSupport::TestCase + class Base + class_attribute :setting + end + + class Subclass < Base + end + + def setup + @klass = Class.new { class_attribute :setting } + @sub = Class.new(@klass) + end + + test 'defaults to nil' do + assert_nil @klass.setting + assert_nil @sub.setting + end + + test 'inheritable' do + @klass.setting = 1 + assert_equal 1, @sub.setting + end + + test 'overridable' do + @sub.setting = 1 + assert_nil @klass.setting + + @klass.setting = 2 + assert_equal 1, @sub.setting + + assert_equal 1, Class.new(@sub).setting + end + + test 'query method' do + assert_equal false, @klass.setting? + @klass.setting = 1 + assert_equal true, @klass.setting? + end + + test 'no instance delegates' do + assert_raise(NoMethodError) { @klass.new.setting } + assert_raise(NoMethodError) { @klass.new.setting? } + end +end diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb index 9a805bc010..ca26f91e8c 100644 --- a/activesupport/test/core_ext/string_ext_test.rb +++ b/activesupport/test/core_ext/string_ext_test.rb @@ -342,12 +342,12 @@ class OutputSafetyTest < ActiveSupport::TestCase end test "A string can be marked safe" do - @string.html_safe! - assert @string.html_safe? + string = @string.html_safe + assert string.html_safe? end test "Marking a string safe returns the string" do - assert_equal @string, @string.html_safe! + assert_equal @string, @string.html_safe end test "A fixnum is safe by default" do @@ -361,7 +361,7 @@ class OutputSafetyTest < ActiveSupport::TestCase end end - @string.html_safe! + @string.html_safe @string << klass.new assert_equal "helloother", @string @@ -369,44 +369,44 @@ class OutputSafetyTest < ActiveSupport::TestCase end test "Adding a safe string to another safe string returns a safe string" do - @other_string = "other".html_safe! - @string.html_safe! - @combination = @other_string + @string + @other_string = "other".html_safe + string = @string.html_safe + @combination = @other_string + string assert_equal "otherhello", @combination assert @combination.html_safe? end - test "Adding an unsafe string to a safe string returns an unsafe string" do - @other_string = "other".html_safe! - @combination = @other_string + @string - @other_combination = @string + @other_string + test "Adding an unsafe string to a safe string escapes it and returns a safe string" do + @other_string = "other".html_safe + @combination = @other_string + "<foo>" + @other_combination = @string + "<foo>" - assert_equal "otherhello", @combination - assert_equal "helloother", @other_combination + assert_equal "other<foo>", @combination + assert_equal "hello<foo>", @other_combination - assert !@combination.html_safe? + assert @combination.html_safe? assert !@other_combination.html_safe? end test "Concatting safe onto unsafe yields unsafe" do @other_string = "other" - @string.html_safe! + @string.html_safe @other_string.concat(@string) assert !@other_string.html_safe? end - test "Concatting unsafe onto safe yields unsafe" do - @other_string = "other".html_safe! - - @other_string.concat(@string) - assert !@other_string.html_safe? + test "Concatting unsafe onto safe yields escaped safe" do + @other_string = "other".html_safe + string = @other_string.concat("<foo>") + assert_equal "other<foo>", string + assert string.html_safe? end test "Concatting safe onto safe yields safe" do - @other_string = "other".html_safe! - @string.html_safe! + @other_string = "other".html_safe + @string.html_safe @other_string.concat(@string) assert @other_string.html_safe? @@ -414,31 +414,32 @@ class OutputSafetyTest < ActiveSupport::TestCase test "Concatting safe onto unsafe with << yields unsafe" do @other_string = "other" - @string.html_safe! + @string.html_safe @other_string << @string assert !@other_string.html_safe? end - test "Concatting unsafe onto safe with << yields unsafe" do - @other_string = "other".html_safe! - - @other_string << @string - assert !@other_string.html_safe? + test "Concatting unsafe onto safe with << yields escaped safe" do + @other_string = "other".html_safe + string = @other_string << "<foo>" + assert_equal "other<foo>", string + assert string.html_safe? end test "Concatting safe onto safe with << yields safe" do - @other_string = "other".html_safe! - @string.html_safe! + @other_string = "other".html_safe + @string.html_safe @other_string << @string assert @other_string.html_safe? end test "Concatting a fixnum to safe always yields safe" do - @string.html_safe! - @string.concat(13) - assert @string.html_safe? + string = @string.html_safe + string = string.concat(13) + assert_equal "hello".concat(13), string + assert string.html_safe? end end diff --git a/activesupport/test/fixtures/custom.rb b/activesupport/test/fixtures/custom.rb new file mode 100644 index 0000000000..0eefce0c25 --- /dev/null +++ b/activesupport/test/fixtures/custom.rb @@ -0,0 +1,2 @@ +class Custom +end
\ No newline at end of file diff --git a/activesupport/test/fixtures/omgomg.rb b/activesupport/test/fixtures/omgomg.rb deleted file mode 100644 index a512a93ae4..0000000000 --- a/activesupport/test/fixtures/omgomg.rb +++ /dev/null @@ -1,2 +0,0 @@ -class OmgOmg -end
\ No newline at end of file diff --git a/activesupport/test/isolation_test.rb b/activesupport/test/isolation_test.rb index a7af5e96f6..2c2986ea28 100644 --- a/activesupport/test/isolation_test.rb +++ b/activesupport/test/isolation_test.rb @@ -59,15 +59,15 @@ elsif ENV['CHILD'] 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")) + assert !defined?(Custom) + assert_equal 0, $LOADED_FEATURES.grep(/fixtures\/custom/).size + require File.expand_path(File.join(File.dirname(__FILE__), "fixtures", "custom")) 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")) + assert !defined?(Custom) + assert_equal 0, $LOADED_FEATURES.grep(/fixtures\/custom/).size + require File.expand_path(File.join(File.dirname(__FILE__), "fixtures", "custom")) end end else diff --git a/activesupport/test/multibyte_chars_test.rb b/activesupport/test/multibyte_chars_test.rb index 0e489c10e1..0f68dcfe23 100644 --- a/activesupport/test/multibyte_chars_test.rb +++ b/activesupport/test/multibyte_chars_test.rb @@ -301,10 +301,10 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase assert_equal " #{UNICODE_STRING}", @chars.rjust(5) assert_equal " #{UNICODE_STRING}", @chars.rjust(7) assert_equal "---#{UNICODE_STRING}", @chars.rjust(7, '-') - assert_equal "ααα#{UNICODE_STRING}", @chars.rjust(7, 'α') + assert_equal "αα#{UNICODE_STRING}", @chars.rjust(7, 'α') assert_equal "aba#{UNICODE_STRING}", @chars.rjust(7, 'ab') assert_equal "αηα#{UNICODE_STRING}", @chars.rjust(7, 'αη') - assert_equal "αηαη#{UNICODE_STRING}", @chars.rjust(8, 'αη') + assert_equal "αη#{UNICODE_STRING}", @chars.rjust(8, 'αη') end def test_ljust_should_raise_argument_errors_on_bad_arguments @@ -319,10 +319,10 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase assert_equal "#{UNICODE_STRING} ", @chars.ljust(5) assert_equal "#{UNICODE_STRING} ", @chars.ljust(7) assert_equal "#{UNICODE_STRING}---", @chars.ljust(7, '-') - assert_equal "#{UNICODE_STRING}ααα", @chars.ljust(7, 'α') + assert_equal "#{UNICODE_STRING}αα", @chars.ljust(7, 'α') assert_equal "#{UNICODE_STRING}aba", @chars.ljust(7, 'ab') assert_equal "#{UNICODE_STRING}αηα", @chars.ljust(7, 'αη') - assert_equal "#{UNICODE_STRING}αηαη", @chars.ljust(8, 'αη') + assert_equal "#{UNICODE_STRING}αη", @chars.ljust(8, 'αη') end def test_center_should_raise_argument_errors_on_bad_arguments @@ -339,13 +339,13 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase assert_equal " #{UNICODE_STRING} ", @chars.center(7) assert_equal "--#{UNICODE_STRING}--", @chars.center(8, '-') assert_equal "--#{UNICODE_STRING}---", @chars.center(9, '-') - assert_equal "αα#{UNICODE_STRING}αα", @chars.center(8, 'α') - assert_equal "αα#{UNICODE_STRING}ααα", @chars.center(9, 'α') - assert_equal "a#{UNICODE_STRING}ab", @chars.center(7, 'ab') - assert_equal "ab#{UNICODE_STRING}ab", @chars.center(8, 'ab') - assert_equal "abab#{UNICODE_STRING}abab", @chars.center(12, 'ab') - assert_equal "α#{UNICODE_STRING}αη", @chars.center(7, 'αη') - assert_equal "αη#{UNICODE_STRING}αη", @chars.center(8, 'αη') + assert_equal "α#{UNICODE_STRING}α", @chars.center(8, 'α') + assert_equal "α#{UNICODE_STRING}αα", @chars.center(9, 'α') + assert_equal "a#{UNICODE_STRING}", @chars.center(7, 'ab') + assert_equal UNICODE_STRING, @chars.center(8, 'ab') + assert_equal "ab#{UNICODE_STRING}ab", @chars.center(12, 'ab') + assert_equal "α#{UNICODE_STRING}", @chars.center(7, 'αη') + assert_equal UNICODE_STRING, @chars.center(8, 'αη') end def test_lstrip_strips_whitespace_from_the_left_of_the_string diff --git a/activesupport/test/notifications_test.rb b/activesupport/test/notifications_test.rb index d3af535c26..0b78b53c73 100644 --- a/activesupport/test/notifications_test.rb +++ b/activesupport/test/notifications_test.rb @@ -77,7 +77,7 @@ module Notifications def test_instrument_with_bang_returns_result_even_on_failure begin instrument!(:awesome, :payload => "notifications") do - raise "OMG" + raise "FAIL" end flunk rescue @@ -126,10 +126,10 @@ module Notifications def test_instrument_does_not_publish_when_exception_is_raised begin instrument(:awesome, :payload => "notifications") do - raise "OMG" + raise "FAIL" end rescue RuntimeError => e - assert_equal "OMG", e.message + assert_equal "FAIL", e.message end drain diff --git a/actionpack/test/template/safe_buffer_test.rb b/activesupport/test/safe_buffer_test.rb index 6a18201d16..bf61f9e58c 100644 --- a/actionpack/test/template/safe_buffer_test.rb +++ b/activesupport/test/safe_buffer_test.rb @@ -1,8 +1,8 @@ require 'abstract_unit' -class SafeBufferTest < ActionView::TestCase +class SafeBufferTest < ActiveSupport::TestCase def setup - @buffer = ActionView::SafeBuffer.new + @buffer = ActiveSupport::SafeBuffer.new end test "Should look like a string" do @@ -16,7 +16,7 @@ class SafeBufferTest < ActionView::TestCase end test "Should NOT escape a safe value passed to it" do - @buffer << "<script>".html_safe! + @buffer << "<script>".html_safe assert_equal "<script>", @buffer end @@ -36,6 +36,6 @@ class SafeBufferTest < ActionView::TestCase test "Should return a safe buffer when calling to_s" do new_buffer = @buffer.to_s - assert_equal ActionView::SafeBuffer, new_buffer.class + assert_equal ActiveSupport::SafeBuffer, new_buffer.class end end diff --git a/ci/ci_build.rb b/ci/ci_build.rb index 7ae660fb7d..5b6d066c2f 100755 --- a/ci/ci_build.rb +++ b/ci/ci_build.rb @@ -7,26 +7,25 @@ def root_dir end def rake(*tasks) - tasks.each { |task| return false unless system("#{root_dir}/bin/rake", task) } + tasks.each { |task| return false unless system("bundle exec rake", task) } true end puts "[CruiseControl] Rails build" build_results = {} -# Requires gem home and path to be writeable and/or overridden to be ~/.gem, -# Will enable when RubyGems supports this properly (in a coming release) -# build_results[:geminstaller] = system 'geminstaller --exceptions' +# Install rubygems-update, so 'gem update --system' in cruise_config.rb auto-installs it on next build. +# This is how you can auto-update rubygems without logging in to CI system +build_results[:geminstaller] = system "sudo gem install rubygems-update -v 1.3.5 --no-ri --no-rdoc" -# for now, use the no-passwd sudoers approach (documented in ci_setup_notes.txt) -# A security hole, but there is nothing valuable on rails CI box anyway. -build_results[:geminstaller] = system "sudo geminstaller --config=#{root_dir}/ci/geminstaller.yml --exceptions" +# Install required version of bundler. +build_results[:geminstaller] = system "sudo gem install bundler -v 0.9.0.pre3 --prerelease --no-ri --no-rdoc" cd root_dir do puts puts "[CruiseControl] Bundling RubyGems" puts - build_results[:bundle] = system 'rm -rf vendor && env CI=1 gem bundle --update && chmod 755 bin vendor vendor/gems' + build_results[:bundle] = system 'env CI=1 sudo bundle install' end cd "#{root_dir}/activesupport" do diff --git a/ci/geminstaller.yml b/ci/geminstaller.yml deleted file mode 100644 index 3dc2000bf9..0000000000 --- a/ci/geminstaller.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -gems: -- name: geminstaller - version: >= 0.4.3 -- name: rubygems-update - version: >= 1.3.5 -- name: bundler - version: >= 0.7.1 diff --git a/load_paths.rb b/load_paths.rb new file mode 100644 index 0000000000..55e2a530bd --- /dev/null +++ b/load_paths.rb @@ -0,0 +1,21 @@ +begin + require File.expand_path('../vendor/environment', __FILE__) +rescue LoadError + begin + require 'rubygems' + require 'bundler' + Bundler.setup + rescue LoadError + %w( + actionmailer + actionpack + activemodel + activerecord + activeresource + activesupport + railties + ).each do |framework| + $:.unshift File.expand_path("../#{framework}/lib", __FILE__) + end + end +end
\ No newline at end of file diff --git a/rails.gemspec b/rails.gemspec index 878a342903..b44dc27cb0 100644 --- a/rails.gemspec +++ b/rails.gemspec @@ -14,6 +14,7 @@ Gem::Specification.new do |s| s.add_dependency('activeresource', '= 3.0.pre') s.add_dependency('actionmailer', '= 3.0.pre') s.add_dependency('railties', '= 3.0.pre') + s.add_dependency('bundler', '>= 0.9.0.pre') s.rdoc_options << '--exclude' << '.' s.has_rdoc = false diff --git a/railties/Rakefile b/railties/Rakefile index b8f5e81b85..ea0b8ef8fb 100644 --- a/railties/Rakefile +++ b/railties/Rakefile @@ -1,7 +1,4 @@ -begin - require File.expand_path('../../vendor/gems/environment', __FILE__) -rescue LoadError -end +require File.expand_path('../../load_paths', __FILE__) require 'rake' require 'rake/testtask' diff --git a/railties/builtin/rails_info/rails/info_controller.rb b/railties/builtin/rails_info/rails/info_controller.rb index 47e87c5bf5..196eeb4a6c 100644 --- a/railties/builtin/rails_info/rails/info_controller.rb +++ b/railties/builtin/rails_info/rails/info_controller.rb @@ -1,9 +1,15 @@ class Rails::InfoController < ActionController::Base def properties - if consider_all_requests_local || local_request? + if consider_all_requests_local? || local_request? render :inline => Rails::Info.to_html else render :text => '<p>For security purposes, this information is only available to local requests.</p>', :status => :forbidden end end + + protected + + def consider_all_requests_local? + Rails.application.config.consider_all_requests_local + end end diff --git a/railties/guides/rails_guides/generator.rb b/railties/guides/rails_guides/generator.rb index bd25111405..6a41bde9f6 100644 --- a/railties/guides/rails_guides/generator.rb +++ b/railties/guides/rails_guides/generator.rb @@ -1,11 +1,5 @@ require 'set' -class String - def html_safe! - self - end unless "post 9415935902f120a9bac0bfce7129725a0db38ed3".respond_to?(:html_safe!) -end - module RailsGuides class Generator attr_reader :output, :view_path, :view, :guides_dir @@ -61,7 +55,7 @@ module RailsGuides body = set_header_section(body, @view) body = set_index(body, @view) - result = view.render(:layout => 'layout', :text => textile(body).html_safe!) + result = view.render(:layout => 'layout', :text => textile(body).html_safe) f.write result warn_about_broken_links(result) if ENV.key?("WARN_BROKEN_LINKS") end @@ -77,8 +71,8 @@ module RailsGuides header = textile(header) - view.content_for(:page_title) { page_title.html_safe! } - view.content_for(:header_section) { header.html_safe! } + view.content_for(:page_title) { page_title.html_safe } + view.content_for(:header_section) { header.html_safe } new_body end @@ -109,7 +103,7 @@ module RailsGuides index << '</ol>' index << '</div>' - view.content_for(:index_section) { index.html_safe! } + view.content_for(:index_section) { index.html_safe } i.result end diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile index 562bc76135..fb4c42f118 100644 --- a/railties/guides/source/active_support_core_extensions.textile +++ b/railties/guides/source/active_support_core_extensions.textile @@ -496,7 +496,42 @@ The class method +delegate+ h3. Extensions to +Class+ -h4. Class Attribute Accessors +h4. Class Attributes + +The method +Class#class_attribute+ declares one or more inheritable class attributes that can be overriden at any level down the hierarchy: + +<ruby> +class A + class_attribute :x +end + +class B < A; end + +class C < B; end + +A.x = :a +B.x # => :a +C.x # => :a + +B.x = :b +A.x # => :a +C.x # => :b + +C.x = :c +A.x # => :a +B.x # => :b +</ruby> + +For example that's the way the +allow_forgery_protection+ flag is implemented for controllers: + +<ruby> +class_attribute :allow_forgery_protection +self.allow_forgery_protection = true +</ruby> + +For convenience +class_attribute+ defines also a predicate, so that declaration also generates +allow_forgery_protection?+. Such predicate returns the double boolean negation of the value. + +NOTE: Defined in +active_support/core_ext/class/attribute.rb+ The macros +cattr_reader+, +cattr_writer+, and +cattr_accessor+ are analogous to their +attr_*+ counterparts but for classes. They initialize a class variable to +nil+ unless it already exists, and generate the corresponding class methods to access it: diff --git a/railties/guides/source/layout.html.erb b/railties/guides/source/layout.html.erb index 7dfcf4a507..5f324ece60 100644 --- a/railties/guides/source/layout.html.erb +++ b/railties/guides/source/layout.html.erb @@ -87,7 +87,7 @@ <div id="container"> <div class="wrapper"> <div id="mainCol"> - <%= yield.html_safe! %> + <%= yield.html_safe %> </div> </div> </div> diff --git a/railties/guides/source/rails_application_templates.textile b/railties/guides/source/rails_application_templates.textile index fc178fa44b..579b1a5538 100644 --- a/railties/guides/source/rails_application_templates.textile +++ b/railties/guides/source/rails_application_templates.textile @@ -88,7 +88,7 @@ Please note that you need to +git :init+ before you can install a plugin as a su Or use plain old SVN : <ruby> -plugin 'wtfsvn', :svn => 'svn://crap.com/wtf/trunk' +plugin 'usingsvn', :svn => 'svn://example.com/usingsvn/trunk' </ruby> h4. vendor/lib/file/initializer(filename, data = nil, &block) diff --git a/railties/lib/generators/rails/app/app_generator.rb b/railties/lib/generators/rails/app/app_generator.rb index 2e34992b3b..918bb98db8 100644 --- a/railties/lib/generators/rails/app/app_generator.rb +++ b/railties/lib/generators/rails/app/app_generator.rb @@ -90,6 +90,18 @@ module Rails::Generators template "config/boot.rb" end + def gem_for_database + # %w( mysql oracle postgresql sqlite3 frontbase ibm_db ) + case options[:database] + when "mysql" then "mysql" + when "oracle" then "ruby-oci8" + when "postgresql" then "pg" + when "sqlite3" then "sqlite3-ruby" + when "frontbase" then "ruby-frontbase" + when "ibm_db" then "ibm_db" + end + end + def create_activerecord_files return if options[:skip_activerecord] template "config/databases/#{options[:database]}.yml", "config/database.yml" diff --git a/railties/lib/generators/rails/app/templates/Gemfile b/railties/lib/generators/rails/app/templates/Gemfile index 7b5c89c3e2..50f1a6a414 100644 --- a/railties/lib/generators/rails/app/templates/Gemfile +++ b/railties/lib/generators/rails/app/templates/Gemfile @@ -1,4 +1,6 @@ # Edit this Gemfile to bundle your application's dependencies. +source :gemcutter + <% if !dev_or_edge? %> gem "rails", "<%= Rails::VERSION::STRING %>" <% end -%> @@ -11,6 +13,14 @@ gem "rails", "<%= Rails::VERSION::STRING %>" <%= "# " unless options.edge? %>gem "rails", :git => "git://github.com/rails/rails.git" <%- end -%> +<% unless options[:skip_activerecord] -%> +<% if options[:database] == 'sqlite3' -%> +# ActiveRecord requires a database adapter. By default, +# Rails has selected sqlite3. +<% end -%> +gem "<%= gem_for_database %>" +<% end -%> + ## Bundle the gems you use: # gem "bj" # gem "hpricot", "0.6" diff --git a/railties/lib/generators/rails/app/templates/config/boot.rb b/railties/lib/generators/rails/app/templates/config/boot.rb index 7fc1aeaeb8..70bd40bc4c 100644 --- a/railties/lib/generators/rails/app/templates/config/boot.rb +++ b/railties/lib/generators/rails/app/templates/config/boot.rb @@ -1,16 +1,19 @@ # Use Bundler (preferred) -environment = File.expand_path('../../vendor/gems/environment', __FILE__) -if File.exist?("#{environment}.rb") - require environment - -# Use 2.x style vendor/rails and RubyGems -else - vendor_rails = File.expand_path('../../vendor/rails', __FILE__) - if File.exist?(vendor_rails) - Dir["#{vendor_rails}/*/lib"].each { |path| $:.unshift(path) } - end - +begin + require File.expand_path('../../vendor/environment', __FILE__) +rescue LoadError require 'rubygems' + require 'bundler' + Bundler.setup + + # To use 2.x style vendor/rails and RubyGems + # + # vendor_rails = File.expand_path('../../vendor/rails', __FILE__) + # if File.exist?(vendor_rails) + # Dir["#{vendor_rails}/*/lib"].each { |path| $:.unshift(path) } + # end + # + # require 'rubygems' end <% unless options[:skip_activerecord] -%> diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index 31787b5cc9..d6ad045294 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -5,7 +5,7 @@ module Rails class Configuration < ::Rails::Engine::Configuration include ::Rails::Configuration::Deprecated - attr_accessor :cache_classes, :cache_store, :colorize_logging, + attr_accessor :allow_concurrency, :cache_classes, :cache_store, :colorize_logging, :consider_all_requests_local, :dependency_loading, :filter_parameters, :log_level, :logger, :metals, :plugins, :preload_frameworks, :reload_engines, :reload_plugins, @@ -13,11 +13,13 @@ module Rails def initialize(*) super + @allow_concurrency = false @colorize_logging = true @filter_parameters = [] @dependency_loading = true @serve_static_assets = true @time_zone = "UTC" + @consider_all_requests_local = true end def paths @@ -50,7 +52,7 @@ module Rails self.preload_frameworks = true self.cache_classes = true self.dependency_loading = false - self.action_controller.allow_concurrency = true if respond_to?(:action_controller) + self.allow_concurrency = true self end diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index 6a4ebe883b..7887a5d25f 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -8,10 +8,10 @@ module Rails def middleware @@default_middleware_stack ||= ActionDispatch::MiddlewareStack.new.tap do |middleware| middleware.use('::ActionDispatch::Static', lambda { Rails.public_path }, :if => lambda { Rails.application.config.serve_static_assets }) - middleware.use('::Rack::Lock', :if => lambda { !ActionController::Base.allow_concurrency }) + middleware.use('::Rack::Lock', :if => lambda { !Rails.application.config.allow_concurrency }) middleware.use('::Rack::Runtime') middleware.use('::Rails::Rack::Logger') - middleware.use('::ActionDispatch::ShowExceptions', lambda { ActionController::Base.consider_all_requests_local }) + middleware.use('::ActionDispatch::ShowExceptions', lambda { Rails.application.config.consider_all_requests_local }) middleware.use('::ActionDispatch::Callbacks', lambda { !Rails.application.config.cache_classes }) middleware.use('::ActionDispatch::Cookies') middleware.use(lambda { ActionController::Base.session_store }, lambda { ActionController::Base.session_options }) @@ -88,11 +88,12 @@ module Rails end class Generators #:nodoc: - attr_accessor :aliases, :options, :colorize_logging + attr_accessor :aliases, :options, :fallbacks, :colorize_logging def initialize @aliases = Hash.new { |h,k| h[k] = {} } @options = Hash.new { |h,k| h[k] = {} } + @fallbacks = {} @colorize_logging = true end diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index 90b513fcb4..8c54014fcb 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -67,6 +67,7 @@ module Rails no_color! unless config.colorize_logging aliases.deep_merge! config.aliases options.deep_merge! config.options + fallbacks.merge! config.fallbacks end def self.aliases #:nodoc: diff --git a/railties/lib/rails/generators/test_case.rb b/railties/lib/rails/generators/test_case.rb index 38a3cbb035..6b97c69d8d 100644 --- a/railties/lib/rails/generators/test_case.rb +++ b/railties/lib/rails/generators/test_case.rb @@ -1,4 +1,5 @@ -require 'active_support/core_ext/class/inheritable_attributes' +require 'active_support/core_ext/class/attribute' +require 'active_support/core_ext/module/delegation' require 'active_support/core_ext/hash/reverse_merge' require 'rails/generators' require 'fileutils' @@ -28,8 +29,8 @@ module Rails class TestCase < ActiveSupport::TestCase include FileUtils - extlib_inheritable_accessor :destination_root, :current_path, :generator_class, - :default_arguments, :instance_writer => false + class_attribute :destination_root, :current_path, :generator_class, :default_arguments + delegate :destination_root, :current_path, :generator_class, :default_arguments, :to => :'self.class' # Generators frequently change the current path using +FileUtils.cd+. # So we need to store the path at file load and revert back to it after each test. diff --git a/railties/test/abstract_unit.rb b/railties/test/abstract_unit.rb index 77ef82856a..aa66dbb9be 100644 --- a/railties/test/abstract_unit.rb +++ b/railties/test/abstract_unit.rb @@ -1,15 +1,7 @@ ORIG_ARGV = ARGV.dup -root = File.expand_path('../../..', __FILE__) -begin - require "#{root}/vendor/gems/environment" -rescue LoadError - %w(activesupport activemodel activerecord actionpack actionmailer activeresource railties).each do |lib| - $:.unshift "#{root}/#{lib}/lib" - end -end - -$:.unshift "#{root}/railties/builtin/rails_info" +require File.expand_path("../../../load_paths", __FILE__) +$:.unshift File.expand_path("../../builtin/rails_info", __FILE__) require 'stringio' require 'test/unit' diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb index 60d644bd59..56f45582c8 100644 --- a/railties/test/application/configuration_test.rb +++ b/railties/test/application/configuration_test.rb @@ -93,7 +93,7 @@ module ApplicationTests RUBY require "#{app_path}/config/application" - assert AppTemplate::Application.config.action_controller.allow_concurrency + assert AppTemplate::Application.config.allow_concurrency end test "the application can be marked as threadsafe when there are no frameworks" do diff --git a/railties/test/application/generators_test.rb b/railties/test/application/generators_test.rb index e54edea07c..25fa100275 100644 --- a/railties/test/application/generators_test.rb +++ b/railties/test/application/generators_test.rb @@ -30,6 +30,7 @@ module ApplicationTests assert_equal(true, c.generators.colorize_logging) assert_equal({}, c.generators.aliases) assert_equal({}, c.generators.options) + assert_equal({}, c.generators.fallbacks) end end @@ -51,11 +52,20 @@ module ApplicationTests end end - test "generators aliases and options on initialization" do + test "generators set rails fallbacks" do + with_config do |c| + c.generators.fallbacks[:shoulda] = :test_unit + expected = { :shoulda => :test_unit } + assert_equal expected, c.generators.fallbacks + end + end + + test "generators aliases, options and fallbacks on initialization" do add_to_config <<-RUBY config.generators.rails :aliases => { :test_framework => "-w" } config.generators.orm :datamapper config.generators.test_framework :rspec + config.generators.fallbacks[:shoulda] = :test_unit RUBY # Initialize the application @@ -65,6 +75,7 @@ module ApplicationTests assert_equal :rspec, Rails::Generators.options[:rails][:test_framework] assert_equal "-w", Rails::Generators.aliases[:rails][:test_framework] + assert_equal :test_unit, Rails::Generators.fallbacks[:shoulda] end test "generators no color on initialization" do diff --git a/railties/test/application/middleware_test.rb b/railties/test/application/middleware_test.rb index 0b92cdba54..ce9cd510a3 100644 --- a/railties/test/application/middleware_test.rb +++ b/railties/test/application/middleware_test.rb @@ -39,7 +39,7 @@ module ApplicationTests end test "removes lock if allow concurrency is set" do - add_to_config "config.action_controller.allow_concurrency = true" + add_to_config "config.allow_concurrency = true" boot! assert !middleware.include?("Rack::Lock") end diff --git a/railties/test/initializable_test.rb b/railties/test/initializable_test.rb index 6a7e4dcc25..74301a5dc5 100644 --- a/railties/test/initializable_test.rb +++ b/railties/test/initializable_test.rb @@ -10,7 +10,7 @@ module InitializableTests attr_accessor :foo, :bar end - initializer :omg do + initializer :start do @foo ||= 0 @foo += 1 end diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb index 940585836c..ff4ee6332b 100644 --- a/railties/test/isolation/abstract_unit.rb +++ b/railties/test/isolation/abstract_unit.rb @@ -183,23 +183,7 @@ module TestHelpers end def boot_rails - root = File.expand_path('../../../..', __FILE__) - begin - require "#{root}/vendor/gems/environment" - rescue LoadError - %w( - actionmailer/lib - actionpack/lib - activemodel/lib - activerecord/lib - activeresource/lib - activesupport/lib - railties/lib - railties - ).reverse_each do |path| - $:.unshift "#{root}/#{path}" - end - end + require File.expand_path('../../../../load_paths', __FILE__) end end end @@ -220,14 +204,18 @@ Module.new do end FileUtils.mkdir(tmp_path) - environment = File.expand_path('../../../../vendor/gems/environment', __FILE__) + environment = File.expand_path('../../../../load_paths', __FILE__) if File.exist?("#{environment}.rb") require_environment = "-r #{environment}" end `#{Gem.ruby} #{require_environment} #{RAILS_FRAMEWORK_ROOT}/railties/bin/rails #{tmp_path('app_template')}` File.open("#{tmp_path}/app_template/config/boot.rb", 'w') do |f| - f.puts "require '#{environment}'" if require_environment + if require_environment + f.puts "Dir.chdir('#{File.dirname(environment)}') do" + f.puts " require '#{environment}'" + f.puts "end" + end f.puts "require 'rails/all'" end end diff --git a/railties/test/rails_info_controller_test.rb b/railties/test/rails_info_controller_test.rb index edab27465e..4163fb2c6d 100644 --- a/railties/test/rails_info_controller_test.rb +++ b/railties/test/rails_info_controller_test.rb @@ -17,23 +17,23 @@ class InfoControllerTest < ActionController::TestCase ActionController::Routing::Routes.draw do |map| match ':controller/:action' end - @controller.stubs(:consider_all_requests_local => false, :local_request? => true) + @controller.stubs(:consider_all_requests_local? => false, :local_request? => true) end test "info controller does not allow remote requests" do - @controller.stubs(:consider_all_requests_local => false, :local_request? => false) + @controller.stubs(:consider_all_requests_local? => false, :local_request? => false) get :properties assert_response :forbidden end test "info controller renders an error message when request was forbidden" do - @controller.stubs(:consider_all_requests_local => false, :local_request? => false) + @controller.stubs(:consider_all_requests_local? => false, :local_request? => false) get :properties assert_select 'p' end test "info controller allows requests when all requests are considered local" do - @controller.stubs(:consider_all_requests_local => true, :local_request? => false) + @controller.stubs(:consider_all_requests_local? => true, :local_request? => false) get :properties assert_response :success end |