aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Gemfile2
-rw-r--r--actionpack/CHANGELOG4
-rw-r--r--actionpack/lib/action_controller/metal/data_streaming.rb15
-rw-r--r--actionpack/lib/action_dispatch/http/mime_types.rb12
-rw-r--r--actionpack/lib/action_dispatch/testing/test_process.rb2
-rw-r--r--actionpack/lib/action_view/asset_paths.rb106
-rw-r--r--actionpack/lib/action_view/helpers/asset_tag_helper.rb6
-rw-r--r--actionpack/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb23
-rw-r--r--actionpack/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb11
-rw-r--r--actionpack/lib/sprockets/helpers/rails_helper.rb31
-rw-r--r--actionpack/test/controller/send_file_test.rb19
-rw-r--r--actionpack/test/controller/test_test.rb7
-rw-r--r--actionpack/test/dispatch/mime_type_test.rb8
-rw-r--r--actionpack/test/template/asset_tag_helper_test.rb38
-rw-r--r--actionpack/test/template/sprockets_helper_test.rb71
-rw-r--r--activerecord/activerecord.gemspec2
-rw-r--r--activerecord/lib/active_record/base.rb33
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb9
-rw-r--r--activerecord/lib/active_record/locking/optimistic.rb2
-rw-r--r--activerecord/lib/active_record/named_scope.rb19
-rw-r--r--activerecord/lib/active_record/persistence.rb4
-rw-r--r--activerecord/lib/active_record/relation.rb5
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb2
-rw-r--r--activerecord/lib/active_record/relation/spawn_methods.rb2
-rw-r--r--activerecord/test/cases/relation_scoping_test.rb7
-rw-r--r--activerecord/test/cases/relation_test.rb2
-rw-r--r--activesupport/lib/active_support/ordered_options.rb4
-rw-r--r--railties/bin/rails2
-rw-r--r--railties/lib/rails/engine.rb12
-rw-r--r--railties/lib/rails/generators/rails/app/app_generator.rb1
-rw-r--r--railties/lib/rails/info.rb4
-rw-r--r--railties/railties.gemspec3
-rw-r--r--railties/test/generators/app_generator_test.rb3
33 files changed, 368 insertions, 103 deletions
diff --git a/Gemfile b/Gemfile
index ef9f613955..73585543b0 100644
--- a/Gemfile
+++ b/Gemfile
@@ -5,7 +5,7 @@ gemspec
if ENV['AREL']
gem "arel", :path => ENV['AREL']
else
- gem "arel", '~> 2.1.0'
+ gem "arel", '~> 2.1.3'
end
gem "coffee-script"
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG
index f4b6464bdc..bc252edadd 100644
--- a/actionpack/CHANGELOG
+++ b/actionpack/CHANGELOG
@@ -1,5 +1,9 @@
*Rails 3.2.0 (unreleased)*
+* send_file now guess the mime type [Esad Hajdarevic]
+
+* Mime type entries for PDF, ZIP and other formats were added [Esad Hajdarevic]
+
* Generate hidden input before select with :multiple option set to true.
This is useful when you rely on the fact that when no options is set,
the state of select will be sent to rails application. Without hidden field
diff --git a/actionpack/lib/action_controller/metal/data_streaming.rb b/actionpack/lib/action_controller/metal/data_streaming.rb
index 623a9873fc..50827d8107 100644
--- a/actionpack/lib/action_controller/metal/data_streaming.rb
+++ b/actionpack/lib/action_controller/metal/data_streaming.rb
@@ -26,8 +26,11 @@ module ActionController #:nodoc:
# Options:
# * <tt>:filename</tt> - suggests a filename for the browser to use.
# Defaults to <tt>File.basename(path)</tt>.
- # * <tt>:type</tt> - specifies an HTTP content type. Defaults to 'application/octet-stream'. You can specify
- # either a string or a symbol for a registered type register with <tt>Mime::Type.register</tt>, for example :json
+ # * <tt>:type</tt> - specifies an HTTP content type.
+ # You can specify either a string or a symbol for a registered type register with
+ # <tt>Mime::Type.register</tt>, for example :json
+ # If omitted, type will be guessed from the file extension specified in <tt>:filename</tt>.
+ # If no content type is registered for the extension, default type 'application/octet-stream' will be used.
# * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded.
# Valid values are 'inline' and 'attachment' (default).
# * <tt>:status</tt> - specifies the status code to send with the response. Defaults to '200 OK'.
@@ -84,6 +87,8 @@ module ActionController #:nodoc:
# * <tt>:filename</tt> - suggests a filename for the browser to use.
# * <tt>:type</tt> - specifies an HTTP content type. Defaults to 'application/octet-stream'. You can specify
# either a string or a symbol for a registered type register with <tt>Mime::Type.register</tt>, for example :json
+ # If omitted, type will be guessed from the file extension specified in <tt>:filename</tt>.
+ # If no content type is registered for the extension, default type 'application/octet-stream' will be used.
# * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded.
# Valid values are 'inline' and 'attachment' (default).
# * <tt>:status</tt> - specifies the status code to send with the response. Defaults to '200 OK'.
@@ -108,6 +113,8 @@ module ActionController #:nodoc:
private
def send_file_headers!(options)
+ type_provided = options.has_key?(:type)
+
options.update(DEFAULT_SEND_FILE_OPTIONS.merge(options))
[:type, :disposition].each do |arg|
raise ArgumentError, ":#{arg} option required" if options[arg].nil?
@@ -123,6 +130,10 @@ module ActionController #:nodoc:
raise ArgumentError, "Unknown MIME type #{options[:type]}" unless extension
self.content_type = extension
else
+ if !type_provided && options[:filename]
+ # If type wasn't provided, try guessing from file extension.
+ content_type = Mime::Type.lookup_by_extension(File.extname(options[:filename]).downcase.tr('.','')) || content_type
+ end
self.content_type = content_type
end
diff --git a/actionpack/lib/action_dispatch/http/mime_types.rb b/actionpack/lib/action_dispatch/http/mime_types.rb
index 68f37d2f65..3da4f91051 100644
--- a/actionpack/lib/action_dispatch/http/mime_types.rb
+++ b/actionpack/lib/action_dispatch/http/mime_types.rb
@@ -7,6 +7,15 @@ Mime::Type.register "text/javascript", :js, %w( application/javascript applicati
Mime::Type.register "text/css", :css
Mime::Type.register "text/calendar", :ics
Mime::Type.register "text/csv", :csv
+
+Mime::Type.register "image/png", :png, [], %w(png)
+Mime::Type.register "image/jpeg", :jpeg, [], %w(jpg jpeg jpe)
+Mime::Type.register "image/gif", :gif, [], %w(gif)
+Mime::Type.register "image/bmp", :bmp, [], %w(bmp)
+Mime::Type.register "image/tiff", :tiff, [], %w(tif tiff)
+
+Mime::Type.register "video/mpeg", :mpeg, [], %w(mpg mpeg mpe)
+
Mime::Type.register "application/xml", :xml, %w( text/xml application/x-xml )
Mime::Type.register "application/rss+xml", :rss
Mime::Type.register "application/atom+xml", :atom
@@ -19,5 +28,8 @@ Mime::Type.register "application/x-www-form-urlencoded", :url_encoded_form
# http://www.json.org/JSONRequest.html
Mime::Type.register "application/json", :json, %w( text/x-json application/jsonrequest )
+Mime::Type.register "application/pdf", :pdf, [], %w(pdf)
+Mime::Type.register "application/zip", :zip, [], %w(zip)
+
# Create Mime::ALL but do not add it to the SET.
Mime::ALL = Mime::Type.new("*/*", :all, [])
diff --git a/actionpack/lib/action_dispatch/testing/test_process.rb b/actionpack/lib/action_dispatch/testing/test_process.rb
index 367c295cf5..f668b81b45 100644
--- a/actionpack/lib/action_dispatch/testing/test_process.rb
+++ b/actionpack/lib/action_dispatch/testing/test_process.rb
@@ -39,7 +39,7 @@ module ActionDispatch
#
# post :change_avatar, :avatar => fixture_file_upload('/files/spongebob.png', 'image/png', :binary)
def fixture_file_upload(path, mime_type = nil, binary = false)
- fixture_path = ActionController::TestCase.send(:fixture_path) if ActionController::TestCase.respond_to?(:fixture_path)
+ fixture_path = self.class.fixture_path if self.class.respond_to?(:fixture_path)
Rack::Test::UploadedFile.new("#{fixture_path}#{path}", mime_type, binary)
end
end
diff --git a/actionpack/lib/action_view/asset_paths.rb b/actionpack/lib/action_view/asset_paths.rb
index 2b1fe545a6..4dd02755d3 100644
--- a/actionpack/lib/action_view/asset_paths.rb
+++ b/actionpack/lib/action_view/asset_paths.rb
@@ -4,7 +4,7 @@ module ActionView
class AssetPaths #:nodoc:
attr_reader :config, :controller
- def initialize(config, controller)
+ def initialize(config, controller = nil)
@config = config
@controller = controller
end
@@ -13,21 +13,29 @@ module ActionView
# Prefix with <tt>/dir/</tt> if lacking a leading +/+. Account for relative URL
# roots. Rewrite the asset path for cache-busting asset ids. Include
# asset host, if configured, with the correct request protocol.
- def compute_public_path(source, dir, ext = nil, include_host = true)
+ #
+ # When include_host is true and the asset host does not specify the protocol
+ # the protocol parameter specifies how the protocol will be added.
+ # When :relative (default), the protocol will be determined by the client using current protocol
+ # When :request, the protocol will be the request protocol
+ # Otherwise, the protocol is used (E.g. :http, :https, etc)
+ def compute_public_path(source, dir, ext = nil, include_host = true, protocol = nil)
source = source.to_s
return source if is_uri?(source)
source = rewrite_extension(source, dir, ext) if ext
source = rewrite_asset_path(source, dir)
-
- if controller && include_host
- has_request = controller.respond_to?(:request)
- source = rewrite_host_and_protocol(source, has_request)
- end
-
+ source = rewrite_relative_url_root(source, relative_url_root) if has_request?
+ source = rewrite_host_and_protocol(source, protocol) if include_host
source
end
+ # Return the filesystem path for the source
+ def compute_source_path(source, dir, ext)
+ source = rewrite_extension(source, dir, ext) if ext
+ File.join(config.assets_dir, dir, source)
+ end
+
def is_uri?(path)
path =~ %r{^[-a-z]+://|^cid:|^//}
end
@@ -46,13 +54,45 @@ module ActionView
relative_url_root && !source.starts_with?("#{relative_url_root}/") ? "#{relative_url_root}#{source}" : source
end
- def rewrite_host_and_protocol(source, has_request)
- source = rewrite_relative_url_root(source, controller.config.relative_url_root) if has_request
+ def has_request?
+ controller.respond_to?(:request)
+ end
+
+ def rewrite_host_and_protocol(source, protocol = nil)
host = compute_asset_host(source)
- if has_request && host && !is_uri?(host)
- host = "#{controller.request.protocol}#{host}"
+ if host && !is_uri?(host)
+ if (protocol || default_protocol) == :request && !has_request?
+ host = nil
+ else
+ host = "#{compute_protocol(protocol)}#{host}"
+ end
+ end
+ host.nil? ? source : "#{host}#{source}"
+ end
+
+ def compute_protocol(protocol)
+ protocol ||= default_protocol
+ case protocol
+ when :relative
+ "//"
+ when :request
+ unless @controller
+ invalid_asset_host!("The protocol requested was :request. Consider using :relative instead.")
+ end
+ @controller.request.protocol
+ else
+ "#{protocol}://"
end
- "#{host}#{source}"
+ end
+
+ def default_protocol
+ protocol = @config.action_controller.default_asset_host_protocol if @config.action_controller.present?
+ protocol ||= @config.default_asset_host_protocol
+ protocol || (has_request? ? :request : :relative)
+ end
+
+ def invalid_asset_host!(help_message)
+ raise ActionController::RoutingError, "This asset host cannot be computed without a request in scope. #{help_message}"
end
# Pick an asset host for this source. Returns +nil+ if no host is set,
@@ -61,19 +101,45 @@ module ActionView
# or the value returned from invoking call on an object responding to call
# (proc or otherwise).
def compute_asset_host(source)
- if host = config.asset_host
+ if host = asset_host_config
if host.respond_to?(:call)
- case host.is_a?(Proc) ? host.arity : host.method(:call).arity
- when 2
- request = controller.respond_to?(:request) && controller.request
- host.call(source, request)
- else
- host.call(source)
+ args = [source]
+ arity = arity_of(host)
+ if arity > 1 && !has_request?
+ invalid_asset_host!("Remove the second argument to your asset_host Proc if you do not need the request.")
end
+ args << current_request if (arity > 1 || arity < 0) && has_request?
+ host.call(*args)
else
(host =~ /%d/) ? host % (source.hash % 4) : host
end
end
end
+
+ def relative_url_root
+ config = controller.config if controller.respond_to?(:config)
+ config ||= config.action_controller if config.action_controller.present?
+ config ||= config
+ config.relative_url_root
+ end
+
+ def asset_host_config
+ if config.action_controller.present?
+ config.action_controller.asset_host
+ else
+ config.asset_host
+ end
+ end
+
+ # Returns the current request if one exists.
+ def current_request
+ controller.request if has_request?
+ end
+
+ # Returns the arity of a callable
+ def arity_of(callable)
+ callable.respond_to?(:arity) ? callable.arity : callable.method(:call).arity
+ end
+
end
end
diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
index 7970176d37..c442c20acd 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
@@ -347,7 +347,7 @@ module ActionView
src = options[:src] = path_to_image(source)
unless src =~ /^cid:/
- options[:alt] = options.fetch(:alt){ File.basename(src, '.*').capitalize }
+ options[:alt] = options.fetch(:alt){ image_alt(src) }
end
if size = options.delete(:size)
@@ -362,6 +362,10 @@ module ActionView
tag("img", options)
end
+ def image_alt(src)
+ File.basename(src, '.*').gsub(/-[[:xdigit:]]{32}\z/, '').capitalize
+ end
+
# Returns an html video tag for the +sources+. If +sources+ is a string,
# a single video tag will be returned. If +sources+ is an array, a video
# tag with nested source tags for each source will be returned. The
diff --git a/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb b/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb
index e4662a2919..3c05173a1b 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb
@@ -60,12 +60,16 @@ module ActionView
private
- def path_to_asset(source, include_host = true)
- asset_paths.compute_public_path(source, asset_name.to_s.pluralize, extension, include_host)
+ def path_to_asset(source, include_host = true, protocol = nil)
+ asset_paths.compute_public_path(source, asset_name.to_s.pluralize, extension, include_host, protocol)
+ end
+
+ def path_to_asset_source(source)
+ asset_paths.compute_source_path(source, asset_name.to_s.pluralize, extension)
end
def compute_paths(*args)
- expand_sources(*args).collect { |source| asset_paths.compute_public_path(source, asset_name.pluralize, extension, false) }
+ expand_sources(*args).collect { |source| path_to_asset_source(source) }
end
def expand_sources(sources, recursive)
@@ -92,7 +96,7 @@ module ActionView
def ensure_sources!(sources)
sources.each do |source|
- asset_file_path!(path_to_asset(source, false))
+ asset_file_path!(path_to_asset_source(source))
end
end
@@ -123,19 +127,14 @@ module ActionView
# Set mtime to the latest of the combined files to allow for
# consistent ETag without a shared filesystem.
- mt = asset_paths.map { |p| File.mtime(asset_file_path(p)) }.max
+ mt = asset_paths.map { |p| File.mtime(asset_file_path!(p)) }.max
File.utime(mt, mt, joined_asset_path)
end
- def asset_file_path(path)
- File.join(config.assets_dir, path.split('?').first)
- end
-
- def asset_file_path!(path, error_if_file_is_uri = false)
- if asset_paths.is_uri?(path)
+ def asset_file_path!(absolute_path, error_if_file_is_uri = false)
+ if asset_paths.is_uri?(absolute_path)
raise(Errno::ENOENT, "Asset file #{path} is uri and cannot be merged into single file") if error_if_file_is_uri
else
- absolute_path = asset_file_path(path)
raise(Errno::ENOENT, "Asset file not found at '#{absolute_path}'" ) unless File.exist?(absolute_path)
return absolute_path
end
diff --git a/actionpack/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb b/actionpack/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb
index e4f11c9bc7..8c25d38bbd 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb
@@ -16,7 +16,8 @@ module ActionView
end
def asset_tag(source, options)
- tag("link", { "rel" => "stylesheet", "type" => Mime::CSS, "media" => "screen", "href" => ERB::Util.html_escape(path_to_asset(source)) }.merge(options), false, false)
+ # We force the :request protocol here to avoid a double-download bug in IE7 and IE8
+ tag("link", { "rel" => "stylesheet", "type" => Mime::CSS, "media" => "screen", "href" => ERB::Util.html_escape(path_to_asset(source, true, :request)) }.merge(options), false, false)
end
def custom_dir
@@ -52,7 +53,7 @@ module ActionView
# If the +source+ filename has no extension, <tt>.css</tt> will be appended (except for explicit URIs).
# Full paths from the document root will be passed through.
# Used internally by +stylesheet_link_tag+ to build the stylesheet path.
- #
+ #
# ==== Examples
# stylesheet_path "style" # => /stylesheets/style.css
# stylesheet_path "dir/style.css" # => /stylesheets/dir/style.css
@@ -60,11 +61,7 @@ module ActionView
# stylesheet_path "http://www.example.com/css/style" # => http://www.example.com/css/style
# stylesheet_path "http://www.example.com/css/style.css" # => http://www.example.com/css/style.css
def stylesheet_path(source)
- if config.use_sprockets
- asset_path(source, 'css')
- else
- asset_paths.compute_public_path(source, 'stylesheets', 'css')
- end
+ asset_paths.compute_public_path(source, 'stylesheets', 'css', true, :request)
end
alias_method :path_to_stylesheet, :stylesheet_path # aliased to avoid conflicts with a stylesheet_path named route
diff --git a/actionpack/lib/sprockets/helpers/rails_helper.rb b/actionpack/lib/sprockets/helpers/rails_helper.rb
index 9f1f0f3b68..63820cc76c 100644
--- a/actionpack/lib/sprockets/helpers/rails_helper.rb
+++ b/actionpack/lib/sprockets/helpers/rails_helper.rb
@@ -10,6 +10,12 @@ module Sprockets
@asset_paths ||= begin
config = self.config if respond_to?(:config)
controller = self.controller if respond_to?(:controller)
+ config ||= Rails.application.config
+ if config.action_controller.present?
+ config.action_controller.default_asset_host_protocol ||= :relative
+ else
+ config.default_asset_host_protocol ||= :relative
+ end
RailsHelper::AssetPaths.new(config, controller)
end
end
@@ -50,7 +56,7 @@ module Sprockets
'rel' => "stylesheet",
'type' => "text/css",
'media' => "screen",
- 'href' => asset_path(source, 'css', body)
+ 'href' => asset_path(source, 'css', body, :request)
}.merge(options.stringify_keys)
tag 'link', tag_options
@@ -58,21 +64,26 @@ module Sprockets
end.join("\n").html_safe
end
+ def asset_path(source, default_ext = nil, body = false, protocol = nil)
+ source = source.logical_path if source.respond_to?(:logical_path)
+ path = asset_paths.compute_public_path(source, 'assets', default_ext, true, protocol)
+ body ? "#{path}?body=1" : path
+ end
+
private
def debug_assets?
params[:debug_assets] == '1' ||
params[:debug_assets] == 'true'
end
- def asset_path(source, default_ext = nil, body = false)
- source = source.logical_path if source.respond_to?(:logical_path)
- path = asset_paths.compute_public_path(source, Rails.application.config.assets.prefix, default_ext, true)
- body ? "#{path}?body=1" : path
- end
-
class AssetPaths < ::ActionView::AssetPaths #:nodoc:
- def compute_public_path(source, dir, ext=nil, include_host=true)
- super(source, Rails.application.config.assets.prefix, ext, include_host)
+ def compute_public_path(source, dir, ext=nil, include_host=true, protocol = nil)
+ super(source, Rails.application.config.assets.prefix, ext, include_host, protocol)
+ end
+
+ # Return the filesystem path for the source
+ def compute_source_path(source, ext)
+ asset_for(source, ext)
end
def asset_for(source, ext)
@@ -104,7 +115,7 @@ module Sprockets
# When included in Sprockets::Context, we need to ask the top-level config as the controller is not available
def performing_caching?
- @config ? @config.perform_caching : Rails.application.config.action_controller.perform_caching
+ config.action_controller.present? ? config.action_controller.perform_caching : config.perform_caching
end
end
end
diff --git a/actionpack/test/controller/send_file_test.rb b/actionpack/test/controller/send_file_test.rb
index c7c8360ae6..8f885ff28e 100644
--- a/actionpack/test/controller/send_file_test.rb
+++ b/actionpack/test/controller/send_file_test.rb
@@ -138,6 +138,25 @@ class SendFileTest < ActionController::TestCase
@controller.headers = {}
assert_raise(ArgumentError){ @controller.send(:send_file_headers!, options) }
end
+
+ def test_send_file_headers_guess_type_from_extension
+ {
+ 'image.png' => 'image/png',
+ 'image.jpeg' => 'image/jpeg',
+ 'image.jpg' => 'image/jpeg',
+ 'image.tif' => 'image/tiff',
+ 'image.gif' => 'image/gif',
+ 'movie.mpg' => 'video/mpeg',
+ 'file.zip' => 'application/zip',
+ 'file.unk' => 'application/octet-stream',
+ 'zip' => 'application/octet-stream'
+ }.each do |filename,expected_type|
+ options = { :filename => filename }
+ @controller.headers = {}
+ @controller.send(:send_file_headers!, options)
+ assert_equal expected_type, @controller.content_type
+ end
+ end
%w(file data).each do |method|
define_method "test_send_#{method}_status" do
diff --git a/actionpack/test/controller/test_test.rb b/actionpack/test/controller/test_test.rb
index 6265e78030..043d44500a 100644
--- a/actionpack/test/controller/test_test.rb
+++ b/actionpack/test/controller/test_test.rb
@@ -649,6 +649,13 @@ XML
end
+ def test_fixture_path_is_accessed_from_self_instead_of_active_support_test_case
+ TestTest.stubs(:fixture_path).returns(FILES_DIR)
+
+ uploaded_file = fixture_file_upload('/mona_lisa.jpg', 'image/png')
+ assert_equal File.open("#{FILES_DIR}/mona_lisa.jpg", READ_PLAIN).read, uploaded_file.read
+ end
+
def test_test_uploaded_file_with_binary
filename = 'mona_lisa.jpg'
path = "#{FILES_DIR}/#{filename}"
diff --git a/actionpack/test/dispatch/mime_type_test.rb b/actionpack/test/dispatch/mime_type_test.rb
index 11cf68fdb3..851fb59d51 100644
--- a/actionpack/test/dispatch/mime_type_test.rb
+++ b/actionpack/test/dispatch/mime_type_test.rb
@@ -52,7 +52,7 @@ class MimeTypeTest < ActiveSupport::TestCase
test "parse application with trailing star" do
accept = "application/*"
- expect = [Mime::HTML, Mime::JS, Mime::XML, Mime::RSS, Mime::ATOM, Mime::YAML, Mime::URL_ENCODED_FORM, Mime::JSON, Mime::PDF]
+ expect = [Mime::HTML, Mime::JS, Mime::XML, Mime::RSS, Mime::ATOM, Mime::YAML, Mime::URL_ENCODED_FORM, Mime::JSON, Mime::PDF, Mime::ZIP]
parsed = Mime::Type.parse(accept)
assert_equal expect, parsed
end
@@ -86,12 +86,12 @@ class MimeTypeTest < ActiveSupport::TestCase
test "custom type" do
begin
- Mime::Type.register("image/gif", :gif)
+ Mime::Type.register("image/foo", :foo)
assert_nothing_raised do
- assert_equal Mime::GIF, Mime::SET.last
+ assert_equal Mime::FOO, Mime::SET.last
end
ensure
- Mime::Type.unregister(:gif)
+ Mime::Type.unregister(:FOO)
end
end
diff --git a/actionpack/test/template/asset_tag_helper_test.rb b/actionpack/test/template/asset_tag_helper_test.rb
index 2abc806e97..df61901b44 100644
--- a/actionpack/test/template/asset_tag_helper_test.rb
+++ b/actionpack/test/template/asset_tag_helper_test.rb
@@ -424,6 +424,14 @@ class AssetTagHelperTest < ActionView::TestCase
PathToImageToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end
+ def test_image_alt
+ [nil, '/', '/foo/bar/', 'foo/bar/'].each do |prefix|
+ assert_equal 'Rails', image_alt("#{prefix}rails.png")
+ assert_equal 'Rails', image_alt("#{prefix}rails-9c0a079bdd7701d7e729bd956823d153.png")
+ assert_equal 'Avatar-0000', image_alt("#{prefix}avatar-0000.png")
+ end
+ end
+
def test_image_tag
ImageLinkToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end
@@ -854,7 +862,7 @@ class AssetTagHelperTest < ActionView::TestCase
def test_caching_stylesheet_link_tag_when_caching_on
ENV["RAILS_ASSET_ID"] = ""
- @controller.config.asset_host = 'http://a0.example.com'
+ @controller.config.asset_host = 'a0.example.com'
config.perform_caching = true
assert_dom_equal(
@@ -964,7 +972,7 @@ class AssetTagHelperTest < ActionView::TestCase
def test_caching_stylesheet_link_tag_when_caching_on_with_proc_asset_host
ENV["RAILS_ASSET_ID"] = ""
- @controller.config.asset_host = Proc.new { |source| "http://a#{source.length}.example.com" }
+ @controller.config.asset_host = Proc.new { |source| "a#{source.length}.example.com" }
config.perform_caching = true
assert_equal '/stylesheets/styles.css'.length, 23
@@ -1091,13 +1099,23 @@ class AssetTagHelperNonVhostTest < ActionView::TestCase
end
def test_should_compute_proper_path_with_asset_host
- @controller.config.asset_host = "http://assets.example.com"
+ @controller.config.asset_host = "assets.example.com"
assert_dom_equal(%(<link href="http://www.example.com/collaboration/hieraki" rel="alternate" title="RSS" type="application/rss+xml" />), auto_discovery_link_tag)
- assert_dom_equal(%(http://assets.example.com/collaboration/hieraki/javascripts/xmlhr.js), javascript_path("xmlhr"))
- assert_dom_equal(%(http://assets.example.com/collaboration/hieraki/stylesheets/style.css), stylesheet_path("style"))
- assert_dom_equal(%(http://assets.example.com/collaboration/hieraki/images/xml.png), image_path("xml.png"))
- assert_dom_equal(%(<img alt="Mouse" onmouseover="this.src='http://assets.example.com/collaboration/hieraki/images/mouse_over.png'" onmouseout="this.src='http://assets.example.com/collaboration/hieraki/images/mouse.png'" src="http://assets.example.com/collaboration/hieraki/images/mouse.png" />), image_tag("mouse.png", :mouseover => "/images/mouse_over.png"))
- assert_dom_equal(%(<img alt="Mouse2" onmouseover="this.src='http://assets.example.com/collaboration/hieraki/images/mouse_over2.png'" onmouseout="this.src='http://assets.example.com/collaboration/hieraki/images/mouse2.png'" src="http://assets.example.com/collaboration/hieraki/images/mouse2.png" />), image_tag("mouse2.png", :mouseover => image_path("mouse_over2.png")))
+ assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/javascripts/xmlhr.js), javascript_path("xmlhr"))
+ assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/stylesheets/style.css), stylesheet_path("style"))
+ assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/images/xml.png), image_path("xml.png"))
+ assert_dom_equal(%(<img alt="Mouse" onmouseover="this.src='gopher://assets.example.com/collaboration/hieraki/images/mouse_over.png'" onmouseout="this.src='gopher://assets.example.com/collaboration/hieraki/images/mouse.png'" src="gopher://assets.example.com/collaboration/hieraki/images/mouse.png" />), image_tag("mouse.png", :mouseover => "/images/mouse_over.png"))
+ assert_dom_equal(%(<img alt="Mouse2" onmouseover="this.src='gopher://assets.example.com/collaboration/hieraki/images/mouse_over2.png'" onmouseout="this.src='gopher://assets.example.com/collaboration/hieraki/images/mouse2.png'" src="gopher://assets.example.com/collaboration/hieraki/images/mouse2.png" />), image_tag("mouse2.png", :mouseover => image_path("mouse_over2.png")))
+ end
+
+ def test_should_compute_proper_path_with_asset_host_and_default_protocol
+ @controller.config.asset_host = "assets.example.com"
+ @controller.config.default_asset_host_protocol = :request
+ assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/javascripts/xmlhr.js), javascript_path("xmlhr"))
+ assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/stylesheets/style.css), stylesheet_path("style"))
+ assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/images/xml.png), image_path("xml.png"))
+ assert_dom_equal(%(<img alt="Mouse" onmouseover="this.src='gopher://assets.example.com/collaboration/hieraki/images/mouse_over.png'" onmouseout="this.src='gopher://assets.example.com/collaboration/hieraki/images/mouse.png'" src="gopher://assets.example.com/collaboration/hieraki/images/mouse.png" />), image_tag("mouse.png", :mouseover => "/images/mouse_over.png"))
+ assert_dom_equal(%(<img alt="Mouse2" onmouseover="this.src='gopher://assets.example.com/collaboration/hieraki/images/mouse_over2.png'" onmouseout="this.src='gopher://assets.example.com/collaboration/hieraki/images/mouse2.png'" src="gopher://assets.example.com/collaboration/hieraki/images/mouse2.png" />), image_tag("mouse2.png", :mouseover => image_path("mouse_over2.png")))
end
def test_should_ignore_asset_host_on_complete_url
@@ -1115,12 +1133,12 @@ class AssetTagHelperNonVhostTest < ActionView::TestCase
assert_match(%r(http://a[0123].example.com/collaboration/hieraki/images/xml.png), image_path('xml.png'))
end
- def test_asset_host_without_protocol_should_use_request_protocol
+ def test_asset_host_without_protocol_should_be_protocol_relative
@controller.config.asset_host = 'a.example.com'
assert_equal 'gopher://a.example.com/collaboration/hieraki/images/xml.png', image_path('xml.png')
end
- def test_asset_host_without_protocol_should_use_request_protocol_even_if_path_present
+ def test_asset_host_without_protocol_should_be_protocol_relative_even_if_path_present
@controller.config.asset_host = 'a.example.com/files/go/here'
assert_equal 'gopher://a.example.com/files/go/here/collaboration/hieraki/images/xml.png', image_path('xml.png')
end
diff --git a/actionpack/test/template/sprockets_helper_test.rb b/actionpack/test/template/sprockets_helper_test.rb
index b1317d0a35..6dc9a2a743 100644
--- a/actionpack/test/template/sprockets_helper_test.rb
+++ b/actionpack/test/template/sprockets_helper_test.rb
@@ -31,18 +31,21 @@ class SprocketsHelperTest < ActionView::TestCase
Rails.stubs(:application).returns(application)
application.stubs(:config).returns(config)
application.stubs(:assets).returns(@assets)
-
- config.perform_caching = true
+ @config = config
+ @config.action_controller ||= ActiveSupport::InheritableOptions.new
+ @config.perform_caching = true
end
def url_for(*args)
"http://www.example.com"
end
- test "asset path" do
+ test "asset_path" do
assert_equal "/assets/logo-9c0a079bdd7701d7e729bd956823d153.png",
asset_path("logo.png")
+ end
+ test "asset_path with root relative assets" do
assert_equal "/images/logo",
asset_path("/images/logo")
assert_equal "/images/logo.gif",
@@ -50,13 +53,73 @@ class SprocketsHelperTest < ActionView::TestCase
assert_equal "/dir/audio",
asset_path("/dir/audio")
-
+ end
+
+ test "asset_path with absolute urls" do
assert_equal "http://www.example.com/video/play",
asset_path("http://www.example.com/video/play")
assert_equal "http://www.example.com/video/play.mp4",
asset_path("http://www.example.com/video/play.mp4")
end
+ test "with a simple asset host the url should default to protocol relative" do
+ @controller.config.asset_host = "assets-%d.example.com"
+ assert_match %r{//assets-\d.example.com/assets/logo-[0-9a-f]+.png},
+ asset_path("logo.png")
+ end
+
+ test "with a simple asset host the url can be changed to use the request protocol" do
+ @controller.config.asset_host = "assets-%d.example.com"
+ @controller.config.default_asset_host_protocol = :request
+ assert_match %r{http://assets-\d.example.com/assets/logo-[0-9a-f]+.png},
+ asset_path("logo.png")
+ end
+
+ test "With a proc asset host that returns no protocol the url should be protocol relative" do
+ @controller.config.asset_host = Proc.new do |asset|
+ "assets-999.example.com"
+ end
+ assert_match %r{//assets-999.example.com/assets/logo-[0-9a-f]+.png},
+ asset_path("logo.png")
+ end
+
+ test "with a proc asset host that returns a protocol the url use it" do
+ @controller.config.asset_host = Proc.new do |asset|
+ "http://assets-999.example.com"
+ end
+ assert_match %r{http://assets-999.example.com/assets/logo-[0-9a-f]+.png},
+ asset_path("logo.png")
+ end
+
+ test "stylesheets served with a controller in scope can access the request" do
+ config.asset_host = Proc.new do |asset, request|
+ assert_not_nil request
+ "http://assets-666.example.com"
+ end
+ assert_match %r{http://assets-666.example.com/assets/logo-[0-9a-f]+.png},
+ asset_path("logo.png")
+ end
+
+ test "stylesheets served without a controller in scope cannot access the request" do
+ remove_instance_variable("@controller")
+ @config.action_controller.asset_host = Proc.new do |asset, request|
+ fail "This should not have been called."
+ end
+ assert_raises ActionController::RoutingError do
+ asset_path("logo.png")
+ end
+ end
+
+ test "stylesheets served without a controller in do not use asset hosts when the default protocol is :request" do
+ remove_instance_variable("@controller")
+ @config.action_controller.asset_host = "assets-%d.example.com"
+ @config.action_controller.default_asset_host_protocol = :request
+ @config.action_controller.perform_caching = true
+
+ assert_equal "/assets/logo-9c0a079bdd7701d7e729bd956823d153.png",
+ asset_path("logo.png")
+ end
+
test "asset path with relative url root" do
@controller.config.relative_url_root = "/collaboration/hieraki"
assert_equal "/collaboration/hieraki/images/logo.gif",
diff --git a/activerecord/activerecord.gemspec b/activerecord/activerecord.gemspec
index b7e23faa09..aff0c51829 100644
--- a/activerecord/activerecord.gemspec
+++ b/activerecord/activerecord.gemspec
@@ -21,6 +21,6 @@ Gem::Specification.new do |s|
s.add_dependency('activesupport', version)
s.add_dependency('activemodel', version)
- s.add_dependency('arel', '~> 2.1.1')
+ s.add_dependency('arel', '~> 2.1.3')
s.add_dependency('tzinfo', '~> 0.3.27')
end
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index e970445082..fd52038647 100644
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -709,6 +709,12 @@ module ActiveRecord #:nodoc:
connection_pool.columns_hash[table_name]
end
+ # Returns a hash where the keys are column names and the values are
+ # default values when instantiating the AR object for this table.
+ def column_defaults
+ connection_pool.column_defaults[table_name]
+ end
+
# Returns an array of column names as strings.
def column_names
@column_names ||= columns.map { |column| column.name }
@@ -1204,11 +1210,11 @@ MSG
end
def current_scope #:nodoc:
- Thread.current[:"#{self}_current_scope"]
+ Thread.current["#{self}_current_scope"]
end
def current_scope=(scope) #:nodoc:
- Thread.current[:"#{self}_current_scope"] = scope
+ Thread.current["#{self}_current_scope"] = scope
end
# Use this macro in your model to set a default scope for all operations on
@@ -1527,6 +1533,7 @@ MSG
@marked_for_destruction = false
@previously_changed = {}
@changed_attributes = {}
+ @relation = nil
ensure_proper_type
set_serialized_attributes
@@ -1535,9 +1542,8 @@ MSG
assign_attributes(attributes, options) if attributes
- result = yield self if block_given?
+ yield self if block_given?
run_callbacks :initialize
- result
end
# Populate +coder+ with attributes about this record that should be
@@ -1568,6 +1574,7 @@ MSG
# post.title # => 'hello world'
def init_with(coder)
@attributes = coder['attributes']
+ @relation = nil
set_serialized_attributes
@@ -1894,9 +1901,10 @@ MSG
private
def set_serialized_attributes
- (@attributes.keys & self.class.serialized_attributes.keys).each do |key|
- coder = self.class.serialized_attributes[key]
- @attributes[key] = coder.load @attributes[key]
+ sattrs = self.class.serialized_attributes
+
+ sattrs.each do |key, coder|
+ @attributes[key] = coder.load @attributes[key] if @attributes.key?(key)
end
end
@@ -1906,8 +1914,9 @@ MSG
# do Reply.new without having to set <tt>Reply[Reply.inheritance_column] = "Reply"</tt> yourself.
# No such attribute would be set for objects of the Message class in that example.
def ensure_proper_type
- unless self.class.descends_from_active_record?
- write_attribute(self.class.inheritance_column, self.class.sti_name)
+ klass = self.class
+ if klass.finder_needs_type_condition?
+ write_attribute(klass.inheritance_column, klass.sti_name)
end
end
@@ -2081,8 +2090,10 @@ MSG
end
def populate_with_current_scope_attributes
- self.class.scoped.scope_for_create.each do |att,value|
- respond_to?("#{att}=") && send("#{att}=", value)
+ return unless self.class.scope_attributes?
+
+ self.class.scope_attributes.each do |att,value|
+ send("#{att}=", value) if respond_to?("#{att}=")
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
index 090f6bc6fe..ddfdb05297 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
@@ -60,6 +60,7 @@ module ActiveRecord
attr_accessor :automatic_reconnect
attr_reader :spec, :connections
attr_reader :columns, :columns_hash, :primary_keys, :tables
+ attr_reader :column_defaults
# Creates a new ConnectionPool object. +spec+ is a ConnectionSpecification
# object which describes database connection information (e.g. adapter,
@@ -106,6 +107,12 @@ module ActiveRecord
}]
end
+ @column_defaults = Hash.new do |h, table_name|
+ h[table_name] = Hash[columns[table_name].map { |col|
+ [col.name, col.default]
+ }]
+ end
+
@primary_keys = Hash.new do |h, table_name|
h[table_name] = with_connection do |conn|
table_exists?(table_name) ? conn.primary_key(table_name) : 'id'
@@ -133,6 +140,7 @@ module ActiveRecord
def clear_cache!
@columns.clear
@columns_hash.clear
+ @column_defaults.clear
@tables.clear
end
@@ -140,6 +148,7 @@ module ActiveRecord
def clear_table_cache!(table_name)
@columns.delete table_name
@columns_hash.delete table_name
+ @column_defaults.delete table_name
@primary_keys.delete table_name
end
diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb
index 3afa257a76..6cfce6e573 100644
--- a/activerecord/lib/active_record/locking/optimistic.rb
+++ b/activerecord/lib/active_record/locking/optimistic.rb
@@ -73,7 +73,7 @@ module ActiveRecord
# <tt>locking_enabled?</tt> at this point as
# <tt>@attributes</tt> may not have been initialized yet.
- if lock_optimistically && result.include?(self.class.locking_column)
+ if result.key?(self.class.locking_column) && lock_optimistically
result[self.class.locking_column] ||= 0
end
diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb
index 14db7a6cd6..0313abe456 100644
--- a/activerecord/lib/active_record/named_scope.rb
+++ b/activerecord/lib/active_record/named_scope.rb
@@ -40,6 +40,25 @@ module ActiveRecord
end
end
+ ##
+ # Collects attributes from scopes that should be applied when creating
+ # an AR instance for the particular class this is called on.
+ def scope_attributes # :nodoc:
+ if current_scope
+ current_scope.scope_for_create
+ else
+ scope = relation.clone
+ scope.default_scoped = true
+ scope.scope_for_create
+ end
+ end
+
+ ##
+ # Are there default attributes associated with this scope?
+ def scope_attributes? # :nodoc:
+ current_scope || default_scopes.any?
+ end
+
# Adds a class method for retrieving and querying objects. A \scope represents a narrowing of a database query,
# such as <tt>where(:color => :red).select('shirts.*').includes(:washing_instructions)</tt>.
#
diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb
index 367a1be4d9..f425118f59 100644
--- a/activerecord/lib/active_record/persistence.rb
+++ b/activerecord/lib/active_record/persistence.rb
@@ -319,9 +319,7 @@ module ActiveRecord
# that a new instance, or one populated from a passed-in Hash, still has all the attributes
# that instances loaded from the database would.
def attributes_from_column_definition
- Hash[self.class.columns.map do |column|
- [column.name, column.default]
- end]
+ self.class.column_defaults.dup
end
end
end
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb
index 317af8a15d..9cd146b857 100644
--- a/activerecord/lib/active_record/relation.rb
+++ b/activerecord/lib/active_record/relation.rb
@@ -6,7 +6,7 @@ module ActiveRecord
JoinOperation = Struct.new(:relation, :join_class, :on)
ASSOCIATION_METHODS = [:includes, :eager_load, :preload]
MULTI_VALUE_METHODS = [:select, :group, :order, :joins, :where, :having, :bind]
- SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :create_with, :from, :reorder, :reverse_order]
+ SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :from, :reorder, :reverse_order]
include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches
@@ -29,6 +29,7 @@ module ActiveRecord
SINGLE_VALUE_METHODS.each {|v| instance_variable_set(:"@#{v}_value", nil)}
(ASSOCIATION_METHODS + MULTI_VALUE_METHODS).each {|v| instance_variable_set(:"@#{v}_values", [])}
@extensions = []
+ @create_with_value = {}
end
def insert(values)
@@ -403,7 +404,7 @@ module ActiveRecord
end
def scope_for_create
- @scope_for_create ||= where_values_hash.merge(@create_with_value || {})
+ @scope_for_create ||= where_values_hash.merge(create_with_value)
end
def eager_loading?
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index 7fbbefeea2..d17861f407 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -137,7 +137,7 @@ module ActiveRecord
def create_with(value)
relation = clone
- relation.create_with_value = value && (@create_with_value || {}).merge(value)
+ relation.create_with_value = value ? create_with_value.merge(value) : {}
relation
end
diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb
index 69706b5ead..ba882beca9 100644
--- a/activerecord/lib/active_record/relation/spawn_methods.rb
+++ b/activerecord/lib/active_record/relation/spawn_methods.rb
@@ -55,7 +55,7 @@ module ActiveRecord
merged_relation.lock_value = r.lock_value unless merged_relation.lock_value
- merged_relation = merged_relation.create_with(r.create_with_value) if r.create_with_value
+ merged_relation = merged_relation.create_with(r.create_with_value) unless r.create_with_value.empty?
# Apply scope extension modules
merged_relation.send :apply_modules, r.extensions
diff --git a/activerecord/test/cases/relation_scoping_test.rb b/activerecord/test/cases/relation_scoping_test.rb
index 0e158df6a0..77b7648576 100644
--- a/activerecord/test/cases/relation_scoping_test.rb
+++ b/activerecord/test/cases/relation_scoping_test.rb
@@ -472,6 +472,13 @@ class DefaultScopingTest < ActiveRecord::TestCase
assert_equal 'Jamis', jamis.name
end
+ # FIXME: I don't know if this is *desired* behavior, but it is *today's*
+ # behavior.
+ def test_create_with_empty_hash_will_not_reset
+ jamis = PoorDeveloperCalledJamis.create_with(:name => 'Aaron').create_with({}).new
+ assert_equal 'Aaron', jamis.name
+ end
+
def test_unscoped_with_named_scope_should_not_have_default_scope
assert_equal [DeveloperCalledJamis.find(developers(:poor_jamis).id)], DeveloperCalledJamis.poor
diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb
index 12e58bd340..b23ead6feb 100644
--- a/activerecord/test/cases/relation_test.rb
+++ b/activerecord/test/cases/relation_test.rb
@@ -20,7 +20,7 @@ module ActiveRecord
end
def test_single_values
- assert_equal [:limit, :offset, :lock, :readonly, :create_with, :from, :reorder, :reverse_order].map(&:to_s).sort,
+ assert_equal [:limit, :offset, :lock, :readonly, :from, :reorder, :reverse_order].map(&:to_s).sort,
Relation::SINGLE_VALUE_METHODS.map(&:to_s).sort
end
diff --git a/activesupport/lib/active_support/ordered_options.rb b/activesupport/lib/active_support/ordered_options.rb
index 8d8e6ebc58..bf81567d22 100644
--- a/activesupport/lib/active_support/ordered_options.rb
+++ b/activesupport/lib/active_support/ordered_options.rb
@@ -36,6 +36,10 @@ module ActiveSupport #:nodoc:
self[name]
end
end
+
+ def respond_to?(name)
+ true
+ end
end
class InheritableOptions < OrderedOptions
diff --git a/railties/bin/rails b/railties/bin/rails
new file mode 100644
index 0000000000..a7d6938e0d
--- /dev/null
+++ b/railties/bin/rails
@@ -0,0 +1,2 @@
+#!/usr/bin/env ruby
+require "rails/cli" \ No newline at end of file
diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb
index 52c89274e7..bf57a034b2 100644
--- a/railties/lib/rails/engine.rb
+++ b/railties/lib/rails/engine.rb
@@ -538,15 +538,9 @@ module Rails
end
initializer :append_assets_path do |app|
- if app.config.assets.respond_to?(:prepend_path)
- app.config.assets.prepend_path(*paths["vendor/assets"].existent)
- app.config.assets.prepend_path(*paths["lib/assets"].existent)
- app.config.assets.prepend_path(*paths["app/assets"].existent)
- else
- app.config.assets.paths.unshift(*paths["vendor/assets"].existent)
- app.config.assets.paths.unshift(*paths["lib/assets"].existent)
- app.config.assets.paths.unshift(*paths["app/assets"].existent)
- end
+ app.config.assets.paths.unshift(*paths["vendor/assets"].existent)
+ app.config.assets.paths.unshift(*paths["lib/assets"].existent)
+ app.config.assets.paths.unshift(*paths["app/assets"].existent)
end
initializer :prepend_helpers_path do |app|
diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb
index 242677cc65..6af9d299aa 100644
--- a/railties/lib/rails/generators/rails/app/app_generator.rb
+++ b/railties/lib/rails/generators/rails/app/app_generator.rb
@@ -88,6 +88,7 @@ module Rails
def lib
empty_directory "lib"
empty_directory_with_gitkeep "lib/tasks"
+ empty_directory_with_gitkeep "lib/assets"
end
def log
diff --git a/railties/lib/rails/info.rb b/railties/lib/rails/info.rb
index d05e031f56..a1e15092b2 100644
--- a/railties/lib/rails/info.rb
+++ b/railties/lib/rails/info.rb
@@ -78,6 +78,10 @@ module Rails
Rails::VERSION::STRING
end
+ property 'JavaScript Runtime' do
+ ExecJS.runtime.name
+ end
+
# Versions of each Rails framework (Active Record, Action Pack,
# Active Resource, Action Mailer, and Active Support).
frameworks.each do |framework|
diff --git a/railties/railties.gemspec b/railties/railties.gemspec
index 9c535f4f90..b917128885 100644
--- a/railties/railties.gemspec
+++ b/railties/railties.gemspec
@@ -15,6 +15,9 @@ Gem::Specification.new do |s|
s.files = Dir['CHANGELOG', 'README.rdoc', 'bin/**/*', 'guides/**/*', 'lib/**/{*,.[a-z]*}']
s.require_path = 'lib'
+ s.bindir = 'bin'
+ s.executables = ['rails']
+
s.rdoc_options << '--exclude' << '.'
s.add_dependency('rake', '>= 0.8.7')
diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb
index 03d185165f..86217f4ab9 100644
--- a/railties/test/generators/app_generator_test.rb
+++ b/railties/test/generators/app_generator_test.rb
@@ -10,6 +10,7 @@ DEFAULT_APP_FILES = %w(
config.ru
app/assets/javascripts
app/assets/stylesheets
+ app/assets/images
app/controllers
app/helpers
app/mailers
@@ -22,8 +23,8 @@ DEFAULT_APP_FILES = %w(
doc
lib
lib/tasks
+ lib/assets
log
- app/assets/images
script/rails
test/fixtures
test/functional