aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Gemfile7
-rw-r--r--README.rdoc4
-rwxr-xr-xRakefile4
-rw-r--r--actionmailer/lib/action_mailer/base.rb8
-rw-r--r--actionpack/actionpack.gemspec2
-rw-r--r--actionpack/lib/action_controller/metal/redirecting.rb1
-rw-r--r--actionpack/lib/action_controller/test_case.rb2
-rw-r--r--actionpack/lib/action_view.rb1
-rw-r--r--actionpack/lib/action_view/asset_paths.rb79
-rw-r--r--actionpack/lib/action_view/helpers/asset_paths.rb82
-rw-r--r--actionpack/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb3
-rw-r--r--actionpack/lib/action_view/helpers/cache_helper.rb10
-rw-r--r--actionpack/lib/action_view/helpers/form_helper.rb28
-rw-r--r--actionpack/lib/action_view/helpers/text_helper.rb3
-rw-r--r--actionpack/lib/sprockets/helpers/rails_helper.rb5
-rw-r--r--actionpack/lib/sprockets/railtie.rb4
-rw-r--r--actionpack/test/lib/controller/fake_models.rb11
-rw-r--r--actionpack/test/template/form_helper_test.rb16
-rw-r--r--actionpack/test/template/text_helper_test.rb11
-rw-r--r--activemodel/lib/active_model/mass_assignment_security/sanitizer.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb8
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb12
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb8
-rw-r--r--activerecord/lib/active_record/connection_adapters/column.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb123
-rw-r--r--activerecord/lib/active_record/migration.rb6
-rw-r--r--activerecord/lib/active_record/query_cache.rb8
-rw-r--r--activerecord/lib/active_record/railties/databases.rake2
-rw-r--r--activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb69
-rw-r--r--activerecord/test/cases/adapters/postgresql/schema_test.rb98
-rw-r--r--activerecord/test/cases/adapters/postgresql/view_test.rb49
-rw-r--r--activerecord/test/cases/connection_management_test.rb7
-rw-r--r--activerecord/test/cases/migration_test.rb12
-rw-r--r--activerecord/test/cases/query_cache_test.rb11
-rw-r--r--activesupport/lib/active_support/core_ext/class/attribute.rb24
-rw-r--r--activesupport/lib/active_support/core_ext/hash/indifferent_access.rb2
-rw-r--r--activesupport/test/core_ext/class/attribute_test.rb6
-rw-r--r--railties/CHANGELOG2
-rw-r--r--railties/guides/source/action_view_overview.textile6
-rw-r--r--railties/guides/source/active_support_core_extensions.textile48
-rw-r--r--railties/guides/source/asset_pipeline.textile92
-rw-r--r--railties/guides/source/caching_with_rails.textile1
-rw-r--r--railties/guides/source/command_line.textile94
-rw-r--r--railties/guides/source/configuring.textile17
-rw-r--r--railties/guides/source/getting_started.textile45
-rw-r--r--railties/guides/source/nested_model_forms.textile12
-rw-r--r--railties/guides/source/performance_testing.textile4
-rw-r--r--railties/guides/source/rails_application_templates.textile10
-rw-r--r--railties/lib/rails.rb23
-rw-r--r--railties/lib/rails/generators.rb3
-rw-r--r--railties/lib/rails/generators/actions.rb8
-rw-r--r--railties/lib/rails/generators/app_base.rb28
-rw-r--r--railties/lib/rails/generators/base.rb6
-rw-r--r--railties/lib/rails/generators/generated_attribute.rb2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/Gemfile18
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/application.rb7
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml62
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml6
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml15
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml6
-rw-r--r--railties/lib/rails/generators/rails/plugin_new/templates/Gemfile7
-rw-r--r--railties/lib/rails/railtie.rb2
-rw-r--r--railties/lib/rails/tasks/assets.rake21
-rw-r--r--railties/test/application/assets_test.rb28
-rw-r--r--railties/test/application/configuration_test.rb15
-rw-r--r--railties/test/fixtures/lib/generators/wrong_generator.rb3
-rw-r--r--railties/test/generators/app_generator_test.rb21
-rw-r--r--railties/test/generators/generated_attribute_test.rb13
-rw-r--r--railties/test/generators/model_generator_test.rb12
-rw-r--r--railties/test/generators/scaffold_generator_test.rb12
-rw-r--r--railties/test/generators_test.rb6
-rw-r--r--railties/test/isolation/abstract_unit.rb4
73 files changed, 1037 insertions, 354 deletions
diff --git a/Gemfile b/Gemfile
index c5b1a46d01..ef9f613955 100644
--- a/Gemfile
+++ b/Gemfile
@@ -10,7 +10,7 @@ end
gem "coffee-script"
gem "sass"
-gem "uglifier", :git => "git://github.com/lautis/uglifier.git"
+gem "uglifier", ">= 1.0.0"
gem "rake", ">= 0.8.7"
gem "mocha", ">= 0.9.8"
@@ -26,9 +26,6 @@ gem "memcache-client", ">= 1.8.5"
platforms :mri_18 do
gem "system_timer"
- # ruby-debug requires linecache which depends on require_relative but doesn't explicitly
- # declare this in its gemspec
- gem "require_relative"
gem "ruby-debug", ">= 0.10.3"
gem "json"
end
@@ -56,7 +53,7 @@ platforms :ruby do
group :db do
gem "pg", ">= 0.11.0"
gem "mysql", ">= 2.8.1"
- gem "mysql2", ">= 0.3.5"
+ gem "mysql2", ">= 0.3.6"
end
end
diff --git a/README.rdoc b/README.rdoc
index 7e2d7850c8..bca2126559 100644
--- a/README.rdoc
+++ b/README.rdoc
@@ -18,7 +18,7 @@ you to present the data from database rows as objects and embellish these data o
with business logic methods. Although most Rails models are backed by a database, models
can also be ordinary Ruby classes, or Ruby classes that implement a set of interfaces as
provided by the ActiveModel module. You can read more about Active Record in its
-{README}[link:files/activerecord/README_rdoc.html].
+{README}[link:blob/master/activerecord/README.rdoc].
The Controller layer is responsible for handling incoming HTTP requests and providing a
suitable response. Usually this means returning HTML, but Rails controllers can also
@@ -29,7 +29,7 @@ In Rails, the Controller and View layers are handled together by Action Pack.
These two layers are bundled in a single package due to their heavy interdependence.
This is unlike the relationship between the Active Record and Action Pack which are
independent. Each of these packages can be used independently outside of Rails. You
-can read more about Action Pack in its {README}[link:files/actionpack/README_rdoc.html].
+can read more about Action Pack in its {README}[link:blob/master/actionpack/README.rdoc].
== Getting Started
diff --git a/Rakefile b/Rakefile
index ba55e580f4..d18dac0dbd 100755
--- a/Rakefile
+++ b/Rakefile
@@ -61,6 +61,9 @@ RDoc::Task.new do |rdoc|
# The temporary solution is to have a README.rdoc without backslashes for
# GitHub, and gsub it to generate the main page of the API.
#
+ # Also, relative links in GitHub have to point to blobs, whereas in the API
+ # they need to point to files.
+ #
# The idea for the future is to have totally different files, since the
# API is no longer a generic entry point to Rails and deserves a
# dedicated main page specifically thought as an API entry point.
@@ -71,6 +74,7 @@ RDoc::Task.new do |rdoc|
# since no autolinking happens there and RDoc displays the backslash
# otherwise.
rdoc_main.gsub!(/^(?=\S).*?\b(?=Rails)\b/) { "#$&\\" }
+ rdoc_main.gsub!(%r{link:blob/master/(\w+)/README\.rdoc}, "link:files/\\1/README_rdoc.html")
File.open(RDOC_MAIN, 'w') do |f|
f.write(rdoc_main)
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index 3b4e59d703..085afb57c1 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -57,7 +57,7 @@ module ActionMailer #:nodoc:
# will accept (any valid Email header including optional fields).
#
# The mail method, if not passed a block, will inspect your views and send all the views with
- # the same name as the method, so the above action would send the +welcome.text.plain.erb+ view
+ # the same name as the method, so the above action would send the +welcome.text.erb+ view
# file as well as the +welcome.text.html.erb+ view file in a +multipart/alternative+ email.
#
# If you want to explicitly render only certain templates, pass a block:
@@ -88,7 +88,7 @@ module ActionMailer #:nodoc:
#
# To define a template to be used with a mailing, create an <tt>.erb</tt> file with the same
# name as the method in your mailer model. For example, in the mailer defined above, the template at
- # <tt>app/views/notifier/signup_notification.text.plain.erb</tt> would be used to generate the email.
+ # <tt>app/views/notifier/welcome.text.erb</tt> would be used to generate the email.
#
# Variables defined in the model are accessible as instance variables in the view.
#
@@ -153,7 +153,7 @@ module ActionMailer #:nodoc:
# by the content type. Each such detected template will be added as separate part to the message.
#
# For example, if the following templates exist:
- # * signup_notification.text.plain.erb
+ # * signup_notification.text.erb
# * signup_notification.text.html.erb
# * signup_notification.text.xml.builder
# * signup_notification.text.yaml.erb
@@ -178,7 +178,7 @@ module ActionMailer #:nodoc:
# end
# end
#
- # Which will (if it had both a <tt>welcome.text.plain.erb</tt> and <tt>welcome.text.html.erb</tt>
+ # Which will (if it had both a <tt>welcome.text.erb</tt> and <tt>welcome.text.html.erb</tt>
# template in the view directory), send a complete <tt>multipart/mixed</tt> email with two parts,
# the first part being a <tt>multipart/alternative</tt> with the text and HTML email parts inside,
# and the second being a <tt>application/pdf</tt> with a Base64 encoded copy of the file.pdf book
diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec
index 37a3d960f1..96ab168674 100644
--- a/actionpack/actionpack.gemspec
+++ b/actionpack/actionpack.gemspec
@@ -24,7 +24,7 @@ Gem::Specification.new do |s|
s.add_dependency('rack', '~> 1.3.0')
s.add_dependency('rack-test', '~> 0.6.0')
s.add_dependency('rack-mount', '~> 0.8.1')
- s.add_dependency('sprockets', '~> 2.0.0.beta.10')
+ s.add_dependency('sprockets', '~> 2.0.0.beta.11')
s.add_dependency('tzinfo', '~> 0.3.27')
s.add_dependency('erubis', '~> 2.7.0')
end
diff --git a/actionpack/lib/action_controller/metal/redirecting.rb b/actionpack/lib/action_controller/metal/redirecting.rb
index 55c650df6c..dee7eb1ec8 100644
--- a/actionpack/lib/action_controller/metal/redirecting.rb
+++ b/actionpack/lib/action_controller/metal/redirecting.rb
@@ -43,6 +43,7 @@ module ActionController
#
# The status code can either be a standard {HTTP Status code}[http://www.iana.org/assignments/http-status-codes] as an
# integer, or a symbol representing the downcased, underscored and symbolized description.
+ # Note that the status code must be a 3xx HTTP code, or redirection will not occur.
#
# It is also possible to assign a flash message as part of the redirection. There are two special accessors for commonly used the flash names
# +alert+ and +notice+ as well as a general purpose +flash+ bucket.
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index d14bb666cc..45bb641aee 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -210,7 +210,7 @@ module ActionController
DEFAULT_OPTIONS = Rack::Session::Abstract::ID::DEFAULT_OPTIONS
def initialize(session = {})
- @env, @by = nil, nil
+ super(nil, nil)
replace(session.stringify_keys)
@loaded = true
end
diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb
index 78eddb7530..d7229419a9 100644
--- a/actionpack/lib/action_view.rb
+++ b/actionpack/lib/action_view.rb
@@ -30,6 +30,7 @@ module ActionView
extend ActiveSupport::Autoload
eager_autoload do
+ autoload :AssetPaths
autoload :Base
autoload :Context
autoload :Helpers
diff --git a/actionpack/lib/action_view/asset_paths.rb b/actionpack/lib/action_view/asset_paths.rb
new file mode 100644
index 0000000000..2b1fe545a6
--- /dev/null
+++ b/actionpack/lib/action_view/asset_paths.rb
@@ -0,0 +1,79 @@
+require 'active_support/core_ext/file'
+
+module ActionView
+ class AssetPaths #:nodoc:
+ attr_reader :config, :controller
+
+ def initialize(config, controller)
+ @config = config
+ @controller = controller
+ end
+
+ # Add the extension +ext+ if not present. Return full or scheme-relative URLs otherwise untouched.
+ # 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)
+ 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
+ end
+
+ def is_uri?(path)
+ path =~ %r{^[-a-z]+://|^cid:|^//}
+ end
+
+ private
+
+ def rewrite_extension(source, dir, ext)
+ raise NotImplementedError
+ end
+
+ def rewrite_asset_path(source, path = nil)
+ raise NotImplementedError
+ end
+
+ def rewrite_relative_url_root(source, relative_url_root)
+ 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
+ host = compute_asset_host(source)
+ if has_request && host && !is_uri?(host)
+ host = "#{controller.request.protocol}#{host}"
+ end
+ "#{host}#{source}"
+ end
+
+ # Pick an asset host for this source. Returns +nil+ if no host is set,
+ # the host if no wildcard is set, the host interpolated with the
+ # numbers 0-3 if it contains <tt>%d</tt> (the number is the source hash mod 4),
+ # 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.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)
+ end
+ else
+ (host =~ /%d/) ? host % (source.hash % 4) : host
+ end
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_view/helpers/asset_paths.rb b/actionpack/lib/action_view/helpers/asset_paths.rb
index 9a99c3cf52..fae2e4fc1c 100644
--- a/actionpack/lib/action_view/helpers/asset_paths.rb
+++ b/actionpack/lib/action_view/helpers/asset_paths.rb
@@ -1,83 +1,7 @@
-require 'active_support/core_ext/file'
+ActiveSupport::Deprecation.warn "ActionView::Helpers::AssetPaths is deprecated. Please use ActionView::AssetPaths instead."
module ActionView
module Helpers
-
- class AssetPaths #:nodoc:
- attr_reader :config, :controller
-
- def initialize(config, controller)
- @config = config
- @controller = controller
- end
-
- # Add the extension +ext+ if not present. Return full or scheme-relative URLs otherwise untouched.
- # 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)
- 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
- end
-
- def is_uri?(path)
- path =~ %r{^[-a-z]+://|^cid:|^//}
- end
-
- private
-
- def rewrite_extension(source, dir, ext)
- raise NotImplementedError
- end
-
- def rewrite_asset_path(source, path = nil)
- raise NotImplementedError
- end
-
- def rewrite_relative_url_root(source, relative_url_root)
- 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
- host = compute_asset_host(source)
- if has_request && host && !is_uri?(host)
- host = "#{controller.request.protocol}#{host}"
- end
- "#{host}#{source}"
- end
-
- # Pick an asset host for this source. Returns +nil+ if no host is set,
- # the host if no wildcard is set, the host interpolated with the
- # numbers 0-3 if it contains <tt>%d</tt> (the number is the source hash mod 4),
- # 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.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)
- end
- else
- (host =~ /%d/) ? host % (source.hash % 4) : host
- end
- end
- end
- end
-
+ AssetPaths = ::ActionView::AssetPaths
end
-end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb b/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb
index 2d49823412..12a304b395 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb
@@ -1,11 +1,10 @@
require 'active_support/core_ext/file'
-require 'action_view/helpers/asset_paths'
module ActionView
module Helpers
module AssetTagHelper
- class AssetPaths < ActionView::Helpers::AssetPaths #:nodoc:
+ class AssetPaths < ::ActionView::AssetPaths #:nodoc:
# You can enable or disable the asset tag ids cache.
# With the cache enabled, the asset tag helper methods will make fewer
# expensive file system calls (the default implementation checks the file
diff --git a/actionpack/lib/action_view/helpers/cache_helper.rb b/actionpack/lib/action_view/helpers/cache_helper.rb
index b57617b3d1..f81ce3e31c 100644
--- a/actionpack/lib/action_view/helpers/cache_helper.rb
+++ b/actionpack/lib/action_view/helpers/cache_helper.rb
@@ -51,12 +51,10 @@ module ActionView
# This dance is needed because Builder can't use capture
pos = output_buffer.length
yield
- if output_buffer.is_a?(ActionView::OutputBuffer)
- safe_output_buffer = output_buffer.to_str
- fragment = safe_output_buffer.slice!(pos..-1)
- self.output_buffer = ActionView::OutputBuffer.new(safe_output_buffer)
- else
- fragment = output_buffer.slice!(pos..-1)
+ output_safe = output_buffer.html_safe?
+ fragment = output_buffer.slice!(pos..-1)
+ if output_safe
+ self.output_buffer = output_buffer.html_safe
end
controller.write_fragment(name, fragment, options)
end
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index 7ed949504d..0ef2357368 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -219,9 +219,9 @@ module ActionView
# <% end %>
#
# If you have an object that needs to be represented as a different
- # parameter, like a Client that acts as a Person:
+ # parameter, like a Person that acts as a Client:
#
- # <%= form_for(@post, :as => :client) do |f| %>
+ # <%= form_for(@person, :as => :client) do |f| %>
# ...
# <% end %>
#
@@ -290,7 +290,7 @@ module ActionView
#
# Example:
#
- # <%= form(@post) do |f| %>
+ # <%= form_for(@post) do |f| %>
# <% f.fields_for(:comments, :include_id => false) do |cf| %>
# ...
# <% end %>
@@ -517,6 +517,18 @@ module ActionView
# end
# end
#
+ # Note that the <tt>projects_attributes=</tt> writer method is in fact
+ # required for fields_for to correctly identify <tt>:projects</tt> as a
+ # collection, and the correct indices to be set in the form markup.
+ #
+ # When projects is already an association on Person you can use
+ # +accepts_nested_attributes_for+ to define the writer method for you:
+ #
+ # class Person < ActiveRecord::Base
+ # has_many :projects
+ # accepts_nested_attributes_for :projects
+ # end
+ #
# This model can now be used with a nested fields_for. The block given to
# the nested fields_for call will be repeated for each instance in the
# collection:
@@ -568,14 +580,6 @@ module ActionView
# ...
# <% end %>
#
- # When projects is already an association on Person you can use
- # +accepts_nested_attributes_for+ to define the writer method for you:
- #
- # class Person < ActiveRecord::Base
- # has_many :projects
- # accepts_nested_attributes_for :projects
- # end
- #
# If you want to destroy any of the associated models through the
# form, you have to enable it first using the <tt>:allow_destroy</tt>
# option for +accepts_nested_attributes_for+:
@@ -1237,7 +1241,7 @@ module ActionView
end
def fields_for(record_name, record_object = nil, fields_options = {}, &block)
- fields_options, record_object = record_object, nil if record_object.is_a?(Hash)
+ fields_options, record_object = record_object, nil if record_object.is_a?(Hash) && record_object.extractable_options?
fields_options[:builder] ||= options[:builder]
fields_options[:parent_builder] = self
diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb
index df450cc836..ae71ade588 100644
--- a/actionpack/lib/action_view/helpers/text_helper.rb
+++ b/actionpack/lib/action_view/helpers/text_helper.rb
@@ -256,6 +256,7 @@ module ActionView
# # => "<p><span>I'm allowed!</span> It's true.</p>"
def simple_format(text, html_options={}, options={})
text = '' if text.nil?
+ text = text.dup if text.frozen?
start_tag = tag('p', html_options, true)
text = sanitize(text) unless options[:sanitize] == false
text = text.to_str
@@ -280,7 +281,7 @@ module ActionView
# @items = [1,2,3,4]
# <table>
# <% @items.each do |item| %>
- # <tr class="<%= cycle("even", "odd") -%>">
+ # <tr class="<%= cycle("odd", "even") -%>">
# <td>item</td>
# </tr>
# <% end %>
diff --git a/actionpack/lib/sprockets/helpers/rails_helper.rb b/actionpack/lib/sprockets/helpers/rails_helper.rb
index 0b6bd8ca40..9f1f0f3b68 100644
--- a/actionpack/lib/sprockets/helpers/rails_helper.rb
+++ b/actionpack/lib/sprockets/helpers/rails_helper.rb
@@ -1,5 +1,4 @@
-require "action_view/helpers/asset_paths"
-require "action_view/helpers/asset_tag_helper"
+require "action_view/helpers"
module Sprockets
module Helpers
@@ -71,7 +70,7 @@ module Sprockets
body ? "#{path}?body=1" : path
end
- class AssetPaths < ActionView::Helpers::AssetPaths #:nodoc:
+ 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)
end
diff --git a/actionpack/lib/sprockets/railtie.rb b/actionpack/lib/sprockets/railtie.rb
index 38eb00ce01..ab5101f6fc 100644
--- a/actionpack/lib/sprockets/railtie.rb
+++ b/actionpack/lib/sprockets/railtie.rb
@@ -63,6 +63,10 @@ module Sprockets
env.logger = Rails.logger
+ if env.respond_to?(:cache)
+ env.cache = Rails.cache
+ end
+
if assets.compress
# temporarily hardcode default JS compressor to uglify. Soon, it will work
# the same as SCSS, where a default plugin sets the default.
diff --git a/actionpack/test/lib/controller/fake_models.rb b/actionpack/test/lib/controller/fake_models.rb
index 67baf369e2..cbef74f992 100644
--- a/actionpack/test/lib/controller/fake_models.rb
+++ b/actionpack/test/lib/controller/fake_models.rb
@@ -170,6 +170,17 @@ class Author < Comment
def post_attributes=(attributes); end
end
+class HashBackedAuthor < Hash
+ extend ActiveModel::Naming
+ include ActiveModel::Conversion
+
+ def persisted?; false; end
+
+ def name
+ "hash backed author"
+ end
+end
+
module Blog
def self._railtie
self
diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb
index 0507045ad2..bf65a9359b 100644
--- a/actionpack/test/template/form_helper_test.rb
+++ b/actionpack/test/template/form_helper_test.rb
@@ -1689,6 +1689,22 @@ class FormHelperTest < ActionView::TestCase
assert_dom_equal expected, output_buffer
end
+ def test_nested_fields_for_with_hash_like_model
+ @author = HashBackedAuthor.new
+
+ form_for(@post) do |f|
+ concat f.fields_for(:author, @author) { |af|
+ concat af.text_field(:name)
+ }
+ end
+
+ expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do
+ '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="hash backed author" />'
+ end
+
+ assert_dom_equal expected, output_buffer
+ end
+
def test_fields_for
output_buffer = fields_for(:post, @post) do |f|
concat f.text_field(:title)
diff --git a/actionpack/test/template/text_helper_test.rb b/actionpack/test/template/text_helper_test.rb
index 5a43b5f864..f7c3986bb1 100644
--- a/actionpack/test/template/text_helper_test.rb
+++ b/actionpack/test/template/text_helper_test.rb
@@ -36,8 +36,8 @@ class TextHelperTest < ActionView::TestCase
text = "A\r\n \nB\n\n\r\n\t\nC\nD".freeze
assert_equal "<p>A\n<br /> \n<br />B</p>\n\n<p>\t\n<br />C\n<br />D</p>", simple_format(text)
- assert_equal %q(<p class="test">This is a classy test</p>), simple_format("This is a classy test", :class => 'test')
- assert_equal %Q(<p class="test">para 1</p>\n\n<p class="test">para 2</p>), simple_format("para 1\n\npara 2", :class => 'test')
+ assert_equal %q(<p class="test">This is a classy test</p>), simple_format("This is a classy test", :class => 'test')
+ assert_equal %Q(<p class="test">para 1</p>\n\n<p class="test">para 2</p>), simple_format("para 1\n\npara 2", :class => 'test')
end
def test_simple_format_should_sanitize_input_when_sanitize_option_is_not_false
@@ -48,6 +48,13 @@ class TextHelperTest < ActionView::TestCase
assert_equal "<p><b> test with unsafe string </b><script>code!</script></p>", simple_format("<b> test with unsafe string </b><script>code!</script>", {}, :sanitize => false)
end
+ def test_simple_format_should_not_change_the_frozen_text_passed
+ text = "<b>Ok</b><script>code!</script>"
+ text_clone = text.dup
+ simple_format(text.freeze)
+ assert_equal text_clone, text
+ end
+
def test_truncate_should_not_be_html_safe
assert !truncate("Hello World!", :length => 12).html_safe?
end
diff --git a/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb b/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb
index ee43a6694f..bb0526adc3 100644
--- a/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb
+++ b/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb
@@ -19,7 +19,7 @@ module ActiveModel
removed_keys = attributes.keys - sanitized_attributes.keys
process_removed_attributes(removed_keys) if removed_keys.any?
end
-
+
def process_removed_attributes(attrs)
raise NotImplementedError, "#process_removed_attributes(attrs) suppose to be overwritten"
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 dd1d2d4fba..090f6bc6fe 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
@@ -426,6 +426,14 @@ module ActiveRecord
@testing = testing
end
+ def method_missing(method_sym, *arguments, &block)
+ @body.send(method_sym, *arguments, &block)
+ end
+
+ def respond_to?(method_sym, include_private = false)
+ super || @body.respond_to?(method_sym)
+ end
+
def each(&block)
body.each(&block)
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
index 70a8f6bb58..82f564e41d 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
@@ -328,7 +328,7 @@ module ActiveRecord
end
# Checks to see if a column exists. See SchemaStatements#column_exists?
- def column_exists?(column_name, type = nil, options = nil)
+ def column_exists?(column_name, type = nil, options = {})
@base.column_exists?(@table_name, column_name, type, options)
end
@@ -386,13 +386,13 @@ module ActiveRecord
# Removes the given index from the table.
#
# ===== Examples
- # ====== Remove the suppliers_name_index in the suppliers table
- # t.remove_index :name
- # ====== Remove the index named accounts_branch_id_index in the accounts table
+ # ====== Remove the index_table_name_on_column in the table_name table
+ # t.remove_index :column
+ # ====== Remove the index named index_table_name_on_branch_id in the table_name table
# t.remove_index :column => :branch_id
- # ====== Remove the index named accounts_branch_id_party_id_index in the accounts table
+ # ====== Remove the index named index_table_name_on_branch_id_and_party_id in the table_name table
# t.remove_index :column => [:branch_id, :party_id]
- # ====== Remove the index named by_branch_party in the accounts table
+ # ====== Remove the index named by_branch_party in the table_name table
# t.remove_index :name => :by_branch_party
def remove_index(options = {})
@base.remove_index(@table_name, options)
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
index 74c07c624d..8e3ba1297e 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
@@ -346,11 +346,11 @@ module ActiveRecord
# Remove the given index from the table.
#
- # Remove the suppliers_name_index in the suppliers table.
- # remove_index :suppliers, :name
- # Remove the index named accounts_branch_id_index in the accounts table.
+ # Remove the index_accounts_on_column in the accounts table.
+ # remove_index :accounts, :column
+ # Remove the index named index_accounts_on_branch_id in the accounts table.
# remove_index :accounts, :column => :branch_id
- # Remove the index named accounts_branch_id_party_id_index in the accounts table.
+ # Remove the index named index_accounts_on_branch_id_and_party_id in the accounts table.
# remove_index :accounts, :column => [:branch_id, :party_id]
# Remove the index named by_branch_party in the accounts table.
# remove_index :accounts, :name => :by_branch_party
diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb
index 3eddb69e73..a7856539b7 100644
--- a/activerecord/lib/active_record/connection_adapters/column.rb
+++ b/activerecord/lib/active_record/connection_adapters/column.rb
@@ -1,3 +1,5 @@
+require 'set'
+
module ActiveRecord
# :stopdoc:
module ConnectionAdapters
diff --git a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
index 798c0db2cf..d6c167ad36 100644
--- a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
@@ -1,6 +1,6 @@
# encoding: utf-8
-gem 'mysql2', '~> 0.3.5'
+gem 'mysql2', '~> 0.3.6'
require 'mysql2'
module ActiveRecord
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index 3e390ba994..6d638628df 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -466,10 +466,11 @@ module ActiveRecord
# Executes an INSERT query and returns the new record's ID
def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
- # Extract the table from the insert sql. Yuck.
- _, table = extract_schema_and_table(sql.split(" ", 4)[2])
-
- pk ||= primary_key(table)
+ unless pk
+ # Extract the table from the insert sql. Yuck.
+ table_ref = extract_table_ref_from_insert_sql(sql)
+ pk = primary_key(table_ref) if table_ref
+ end
if pk
select_value("#{sql} RETURNING #{quote_column_name(pk)}")
@@ -565,9 +566,9 @@ module ActiveRecord
def sql_for_insert(sql, pk, id_value, sequence_name, binds)
unless pk
- _, table = extract_schema_and_table(sql.split(" ", 4)[2])
-
- pk = primary_key(table)
+ # Extract the table from the insert sql. Yuck.
+ table_ref = extract_table_ref_from_insert_sql(sql)
+ pk = primary_key(table_ref) if table_ref
end
sql = "#{sql} RETURNING #{quote_column_name(pk)}" if pk
@@ -665,34 +666,33 @@ module ActiveRecord
SQL
end
+ # Returns true if table exists.
+ # If the schema is not specified as part of +name+ then it will only find tables within
+ # the current schema search path (regardless of permissions to access tables in other schemas)
def table_exists?(name)
schema, table = extract_schema_and_table(name.to_s)
+ return false unless table
- binds = [[nil, table.gsub(/(^"|"$)/,'')]]
+ binds = [[nil, table]]
binds << [nil, schema] if schema
exec_query(<<-SQL, 'SCHEMA', binds).rows.first[0].to_i > 0
- SELECT COUNT(*)
- FROM pg_tables
- WHERE tablename = $1
- #{schema ? "AND schemaname = $2" : ''}
+ SELECT COUNT(*)
+ FROM pg_class c
+ LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
+ WHERE c.relkind in ('v','r')
+ AND c.relname = $1
+ AND n.nspname = #{schema ? '$2' : 'ANY (current_schemas(false))'}
SQL
end
- # Extracts the table and schema name from +name+
- def extract_schema_and_table(name)
- schema, table = name.split('.', 2)
-
- unless table # A table was provided without a schema
- table = schema
- schema = nil
- end
-
- if name =~ /^"/ # Handle quoted table names
- table = name
- schema = nil
- end
- [schema, table]
+ # Returns true if schema exists.
+ def schema_exists?(name)
+ exec_query(<<-SQL, 'SCHEMA', [[nil, name]]).rows.first[0].to_i > 0
+ SELECT COUNT(*)
+ FROM pg_namespace
+ WHERE nspname = $1
+ SQL
end
# Returns an array of indexes for the given table.
@@ -742,6 +742,11 @@ module ActiveRecord
query('select current_database()')[0][0]
end
+ # Returns the current schema name.
+ def current_schema
+ query('SELECT current_schema', 'SCHEMA')[0][0]
+ end
+
# Returns the current database encoding format.
def encoding
query(<<-end_sql)[0][0]
@@ -806,7 +811,7 @@ module ActiveRecord
if pk && sequence
quoted_sequence = quote_table_name(sequence)
-
+
select_value <<-end_sql, 'Reset sequence'
SELECT setval('#{quoted_sequence}', (SELECT COALESCE(MAX(#{quote_column_name pk})+(SELECT increment_by FROM #{quoted_sequence}), (SELECT min_value FROM #{quoted_sequence})) FROM #{quote_table_name(table)}), false)
end_sql
@@ -835,7 +840,7 @@ module ActiveRecord
else
sequence = result.second+'.'+result.last
end
-
+
[result.first, sequence]
rescue
nil
@@ -960,27 +965,27 @@ module ActiveRecord
end
private
- def exec_no_cache(sql, binds)
- @connection.async_exec(sql)
- end
-
- def exec_cache(sql, binds)
- unless @statements.key? sql
- nextkey = "a#{@statements.length + 1}"
- @connection.prepare nextkey, sql
- @statements[sql] = nextkey
+ def exec_no_cache(sql, binds)
+ @connection.async_exec(sql)
end
- key = @statements[sql]
+ def exec_cache(sql, binds)
+ unless @statements.key? sql
+ nextkey = "a#{@statements.length + 1}"
+ @connection.prepare nextkey, sql
+ @statements[sql] = nextkey
+ end
- # Clear the queue
- @connection.get_last_result
- @connection.send_query_prepared(key, binds.map { |col, val|
- type_cast(val, col)
- })
- @connection.block
- @connection.get_last_result
- end
+ key = @statements[sql]
+
+ # Clear the queue
+ @connection.get_last_result
+ @connection.send_query_prepared(key, binds.map { |col, val|
+ type_cast(val, col)
+ })
+ @connection.block
+ @connection.get_last_result
+ end
# The internal PostgreSQL identifier of the money data type.
MONEY_COLUMN_TYPE_OID = 790 #:nodoc:
@@ -1080,9 +1085,29 @@ module ActiveRecord
end
end
- def table_definition
- TableDefinition.new(self)
- end
+ # Returns an array of <tt>[schema_name, table_name]</tt> extracted from +name+.
+ # +schema_name+ is nil if not specified in +name+.
+ # +schema_name+ and +table_name+ exclude surrounding quotes (regardless of whether provided in +name+)
+ # +name+ supports the range of schema/table references understood by PostgreSQL, for example:
+ #
+ # * <tt>table_name</tt>
+ # * <tt>"table.name"</tt>
+ # * <tt>schema_name.table_name</tt>
+ # * <tt>schema_name."table.name"</tt>
+ # * <tt>"schema.name"."table name"</tt>
+ def extract_schema_and_table(name)
+ table, schema = name.scan(/[^".\s]+|"[^"]*"/)[0..1].collect{|m| m.gsub(/(^"|"$)/,'') }.reverse
+ [schema, table]
+ end
+
+ def extract_table_ref_from_insert_sql(sql)
+ sql[/into\s+([^\(]*).*values\s*\(/i]
+ $1.strip if $1
+ end
+
+ def table_definition
+ TableDefinition.new(self)
+ end
end
end
end
diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb
index de26b21f1a..3d1bc5c1e0 100644
--- a/activerecord/lib/active_record/migration.rb
+++ b/activerecord/lib/active_record/migration.rb
@@ -116,8 +116,10 @@ module ActiveRecord
# with the name of the column. Other options include
# <tt>:name</tt> and <tt>:unique</tt> (e.g.
# <tt>{ :name => "users_name_index", :unique => true }</tt>).
- # * <tt>remove_index(table_name, index_name)</tt>: Removes the index specified
- # by +index_name+.
+ # * <tt>remove_index(table_name, :column => column_name)</tt>: Removes the index
+ # specified by +column_name+.
+ # * <tt>remove_index(table_name, :name => index_name)</tt>: Removes the index
+ # specified by +index_name+.
#
# == Irreversible transformations
#
diff --git a/activerecord/lib/active_record/query_cache.rb b/activerecord/lib/active_record/query_cache.rb
index 4e61671473..e485901440 100644
--- a/activerecord/lib/active_record/query_cache.rb
+++ b/activerecord/lib/active_record/query_cache.rb
@@ -33,6 +33,14 @@ module ActiveRecord
@target = target
end
+ def method_missing(method_sym, *arguments, &block)
+ @target.send(method_sym, *arguments, &block)
+ end
+
+ def respond_to?(method_sym, include_private = false)
+ super || @target.respond_to?(method_sym)
+ end
+
def each(&block)
@target.each(&block)
end
diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake
index 6ef24a4eaf..83909b0766 100644
--- a/activerecord/lib/active_record/railties/databases.rake
+++ b/activerecord/lib/active_record/railties/databases.rake
@@ -369,7 +369,7 @@ db_namespace = namespace :db do
ENV['PGPASSWORD'] = abcs[Rails.env]['password'].to_s if abcs[Rails.env]['password']
search_path = abcs[Rails.env]['schema_search_path']
unless search_path.blank?
- search_path = search_path.split(",").map{|search_path| "--schema=#{search_path.strip}" }.join(" ")
+ search_path = search_path.split(",").map{|search_path_part| "--schema=#{search_path_part.strip}" }.join(" ")
end
`pg_dump -i -U "#{abcs[Rails.env]['username']}" -s -x -O -f db/#{Rails.env}_structure.sql #{search_path} #{abcs[Rails.env]['database']}`
raise 'Error dumping database' if $?.exitstatus == 1
diff --git a/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb b/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb
index 7c49236854..d57794daf8 100644
--- a/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb
@@ -10,6 +10,45 @@ module ActiveRecord
@connection.exec_query('create table ex(id serial primary key, number integer, data character varying(255))')
end
+ def test_primary_key
+ assert_equal 'id', @connection.primary_key('ex')
+ end
+
+ def test_non_standard_primary_key
+ @connection.exec_query('drop table if exists ex')
+ @connection.exec_query('create table ex(data character varying(255) primary key)')
+ assert_equal 'data', @connection.primary_key('ex')
+ end
+
+ def test_primary_key_returns_nil_for_no_pk
+ @connection.exec_query('drop table if exists ex')
+ @connection.exec_query('create table ex(id integer)')
+ assert_nil @connection.primary_key('ex')
+ end
+
+ def test_primary_key_raises_error_if_table_not_found
+ assert_raises(ActiveRecord::StatementInvalid) do
+ @connection.primary_key('unobtainium')
+ end
+ end
+
+ def test_insert_sql_with_proprietary_returning_clause
+ id = @connection.insert_sql("insert into ex (number) values(5150)", nil, "number")
+ assert_equal "5150", id
+ end
+
+ def test_insert_sql_with_quoted_schema_and_table_name
+ id = @connection.insert_sql('insert into "public"."ex" (number) values(5150)')
+ expect = @connection.query('select max(id) from ex').first.first
+ assert_equal expect, id
+ end
+
+ def test_insert_sql_with_no_space_after_table_name
+ id = @connection.insert_sql("insert into ex(number) values(5150)")
+ expect = @connection.query('select max(id) from ex').first.first
+ assert_equal expect, id
+ end
+
def test_serial_sequence
assert_equal 'public.accounts_id_seq',
@connection.serial_sequence('accounts', 'id')
@@ -35,6 +74,36 @@ module ActiveRecord
@connection.default_sequence_name('zomg')
end
+ def test_pk_and_sequence_for
+ pk, seq = @connection.pk_and_sequence_for('ex')
+ assert_equal 'id', pk
+ assert_equal @connection.default_sequence_name('ex', 'id'), seq
+ end
+
+ def test_pk_and_sequence_for_with_non_standard_primary_key
+ @connection.exec_query('drop table if exists ex')
+ @connection.exec_query('create table ex(code serial primary key)')
+ pk, seq = @connection.pk_and_sequence_for('ex')
+ assert_equal 'code', pk
+ assert_equal @connection.default_sequence_name('ex', 'code'), seq
+ end
+
+ def test_pk_and_sequence_for_returns_nil_if_no_seq
+ @connection.exec_query('drop table if exists ex')
+ @connection.exec_query('create table ex(id integer primary key)')
+ assert_nil @connection.pk_and_sequence_for('ex')
+ end
+
+ def test_pk_and_sequence_for_returns_nil_if_no_pk
+ @connection.exec_query('drop table if exists ex')
+ @connection.exec_query('create table ex(id integer)')
+ assert_nil @connection.pk_and_sequence_for('ex')
+ end
+
+ def test_pk_and_sequence_for_returns_nil_if_table_not_found
+ assert_nil @connection.pk_and_sequence_for('unobtainium')
+ end
+
def test_exec_insert_number
insert(@connection, 'number' => 10)
diff --git a/activerecord/test/cases/adapters/postgresql/schema_test.rb b/activerecord/test/cases/adapters/postgresql/schema_test.rb
index a5c3e69af9..27e7b1a1c3 100644
--- a/activerecord/test/cases/adapters/postgresql/schema_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/schema_test.rb
@@ -20,6 +20,7 @@ class SchemaTest < ActiveRecord::TestCase
'email character varying(50)',
'moment timestamp without time zone default now()'
]
+ PK_TABLE_NAME = 'table_with_pk'
class Thing1 < ActiveRecord::Base
set_table_name "test_schema.things"
@@ -49,6 +50,7 @@ class SchemaTest < ActiveRecord::TestCase
@connection.execute "CREATE INDEX #{INDEX_B_NAME} ON #{SCHEMA2_NAME}.#{TABLE_NAME} USING btree (#{INDEX_B_COLUMN_S2});"
@connection.execute "CREATE INDEX #{INDEX_C_NAME} ON #{SCHEMA_NAME}.#{TABLE_NAME} USING gin (#{INDEX_C_COLUMN});"
@connection.execute "CREATE INDEX #{INDEX_C_NAME} ON #{SCHEMA2_NAME}.#{TABLE_NAME} USING gin (#{INDEX_C_COLUMN});"
+ @connection.execute "CREATE TABLE #{SCHEMA_NAME}.#{PK_TABLE_NAME} (id serial primary key)"
end
def teardown
@@ -63,12 +65,30 @@ class SchemaTest < ActiveRecord::TestCase
end
end
+ def test_table_exists_when_on_schema_search_path
+ with_schema_search_path(SCHEMA_NAME) do
+ assert(@connection.table_exists?(TABLE_NAME), "table should exist and be found")
+ end
+ end
+
+ def test_table_exists_when_not_on_schema_search_path
+ with_schema_search_path('PUBLIC') do
+ assert(!@connection.table_exists?(TABLE_NAME), "table exists but should not be found")
+ end
+ end
+
def test_table_exists_wrong_schema
assert(!@connection.table_exists?("foo.things"), "table should not exist")
end
- def test_table_exists_quoted_table
- assert(@connection.table_exists?('"things.table"'), "table should exist")
+ def test_table_exists_quoted_names
+ [ %("#{SCHEMA_NAME}"."#{TABLE_NAME}"), %(#{SCHEMA_NAME}."#{TABLE_NAME}"), %(#{SCHEMA_NAME}."#{TABLE_NAME}")].each do |given|
+ assert(@connection.table_exists?(given), "table should exist when specified as #{given}")
+ end
+ with_schema_search_path(SCHEMA_NAME) do
+ given = %("#{TABLE_NAME}")
+ assert(@connection.table_exists?(given), "table should exist when specified as #{given}")
+ end
end
def test_with_schema_prefixed_table_name
@@ -91,7 +111,6 @@ class SchemaTest < ActiveRecord::TestCase
end
end
-
def test_proper_encoding_of_table_name
assert_equal '"table_name"', @connection.quote_table_name('table_name')
assert_equal '"table.name"', @connection.quote_table_name('"table.name"')
@@ -164,6 +183,79 @@ class SchemaTest < ActiveRecord::TestCase
ActiveRecord::Base.connection.schema_search_path = "public"
end
+ def test_primary_key_with_schema_specified
+ [
+ %("#{SCHEMA_NAME}"."#{PK_TABLE_NAME}"),
+ %(#{SCHEMA_NAME}."#{PK_TABLE_NAME}"),
+ %(#{SCHEMA_NAME}.#{PK_TABLE_NAME})
+ ].each do |given|
+ assert_equal 'id', @connection.primary_key(given), "primary key should be found when table referenced as #{given}"
+ end
+ end
+
+ def test_primary_key_assuming_schema_search_path
+ with_schema_search_path(SCHEMA_NAME) do
+ assert_equal 'id', @connection.primary_key(PK_TABLE_NAME), "primary key should be found"
+ end
+ end
+
+ def test_primary_key_raises_error_if_table_not_found_on_schema_search_path
+ with_schema_search_path(SCHEMA2_NAME) do
+ assert_raises(ActiveRecord::StatementInvalid) do
+ @connection.primary_key(PK_TABLE_NAME)
+ end
+ end
+ end
+
+ def test_pk_and_sequence_for_with_schema_specified
+ [
+ %("#{SCHEMA_NAME}"."#{PK_TABLE_NAME}"),
+ %(#{SCHEMA_NAME}."#{PK_TABLE_NAME}"),
+ %(#{SCHEMA_NAME}.#{PK_TABLE_NAME})
+ ].each do |given|
+ pk, seq = @connection.pk_and_sequence_for(given)
+ assert_equal 'id', pk, "primary key should be found when table referenced as #{given}"
+ assert_equal "#{SCHEMA_NAME}.#{PK_TABLE_NAME}_id_seq", seq, "sequence name should be found when table referenced as #{given}"
+ end
+ end
+
+ def test_extract_schema_and_table
+ {
+ %(table_name) => [nil,'table_name'],
+ %("table.name") => [nil,'table.name'],
+ %(schema.table_name) => %w{schema table_name},
+ %("schema".table_name) => %w{schema table_name},
+ %(schema."table_name") => %w{schema table_name},
+ %("schema"."table_name") => %w{schema table_name},
+ %("even spaces".table) => ['even spaces','table'],
+ %(schema."table.name") => ['schema', 'table.name']
+ }.each do |given,expect|
+ assert_equal expect, @connection.send(:extract_schema_and_table, given)
+ end
+ end
+
+ def test_current_schema
+ {
+ %('$user',public) => 'public',
+ SCHEMA_NAME => SCHEMA_NAME,
+ %(#{SCHEMA2_NAME},#{SCHEMA_NAME},public) => SCHEMA2_NAME,
+ %(public,#{SCHEMA2_NAME},#{SCHEMA_NAME}) => 'public'
+ }.each do |given,expect|
+ with_schema_search_path(given) { assert_equal expect, @connection.current_schema }
+ end
+ end
+
+ def test_schema_exists?
+ {
+ 'public' => true,
+ SCHEMA_NAME => true,
+ SCHEMA2_NAME => true,
+ 'darkside' => false
+ }.each do |given,expect|
+ assert_equal expect, @connection.schema_exists?(given)
+ end
+ end
+
private
def columns(table_name)
@connection.send(:column_definitions, table_name).map do |name, type, default|
diff --git a/activerecord/test/cases/adapters/postgresql/view_test.rb b/activerecord/test/cases/adapters/postgresql/view_test.rb
new file mode 100644
index 0000000000..303ba9245a
--- /dev/null
+++ b/activerecord/test/cases/adapters/postgresql/view_test.rb
@@ -0,0 +1,49 @@
+require "cases/helper"
+
+class ViewTest < ActiveRecord::TestCase
+ self.use_transactional_fixtures = false
+
+ SCHEMA_NAME = 'test_schema'
+ TABLE_NAME = 'things'
+ VIEW_NAME = 'view_things'
+ COLUMNS = [
+ 'id integer',
+ 'name character varying(50)',
+ 'email character varying(50)',
+ 'moment timestamp without time zone'
+ ]
+
+ class ThingView < ActiveRecord::Base
+ set_table_name 'test_schema.view_things'
+ end
+
+ def setup
+ @connection = ActiveRecord::Base.connection
+ @connection.execute "CREATE SCHEMA #{SCHEMA_NAME} CREATE TABLE #{TABLE_NAME} (#{COLUMNS.join(',')})"
+ @connection.execute "CREATE TABLE #{SCHEMA_NAME}.\"#{TABLE_NAME}.table\" (#{COLUMNS.join(',')})"
+ @connection.execute "CREATE VIEW #{SCHEMA_NAME}.#{VIEW_NAME} AS SELECT id,name,email,moment FROM #{SCHEMA_NAME}.#{TABLE_NAME}"
+ end
+
+ def teardown
+ @connection.execute "DROP SCHEMA #{SCHEMA_NAME} CASCADE"
+ end
+
+ def test_table_exists
+ name = ThingView.table_name
+ assert @connection.table_exists?(name), "'#{name}' table should exist"
+ end
+
+ def test_column_definitions
+ assert_nothing_raised do
+ assert_equal COLUMNS, columns("#{SCHEMA_NAME}.#{VIEW_NAME}")
+ end
+ end
+
+ private
+ def columns(table_name)
+ @connection.send(:column_definitions, table_name).map do |name, type, default|
+ "#{name} #{type}" + (default ? " default #{default}" : '')
+ end
+ end
+
+end
diff --git a/activerecord/test/cases/connection_management_test.rb b/activerecord/test/cases/connection_management_test.rb
index 85871aebdf..a1d1177289 100644
--- a/activerecord/test/cases/connection_management_test.rb
+++ b/activerecord/test/cases/connection_management_test.rb
@@ -77,6 +77,13 @@ module ActiveRecord
@management.call(@env)
assert ActiveRecord::Base.connection_handler.active_connections?
end
+
+ test "proxy is polite to it's body and responds to it" do
+ body = Class.new(String) { def to_path; "/path"; end }.new
+ proxy = ConnectionManagement::Proxy.new(body)
+ assert proxy.respond_to?(:to_path)
+ assert_equal proxy.to_path, "/path"
+ end
end
end
end
diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb
index bf7565a0d0..93a1249e43 100644
--- a/activerecord/test/cases/migration_test.rb
+++ b/activerecord/test/cases/migration_test.rb
@@ -1071,6 +1071,18 @@ if ActiveRecord::Base.connection.supports_migrations?
Person.connection.drop_table :testings rescue nil
end
+ def test_column_exists_on_table_with_no_options_parameter_supplied
+ Person.connection.create_table :testings do |t|
+ t.string :foo
+ end
+ Person.connection.change_table :testings do |t|
+ assert t.column_exists?(:foo)
+ assert !(t.column_exists?(:bar))
+ end
+ ensure
+ Person.connection.drop_table :testings rescue nil
+ end
+
def test_add_table
assert !Reminder.table_exists?
diff --git a/activerecord/test/cases/query_cache_test.rb b/activerecord/test/cases/query_cache_test.rb
index a61180cfaf..ad17f6f83a 100644
--- a/activerecord/test/cases/query_cache_test.rb
+++ b/activerecord/test/cases/query_cache_test.rb
@@ -203,3 +203,14 @@ class QueryCacheExpiryTest < ActiveRecord::TestCase
end
end
end
+
+class QueryCacheBodyProxyTest < ActiveRecord::TestCase
+
+ test "is polite to it's body and responds to it" do
+ body = Class.new(String) { def to_path; "/path"; end }.new
+ proxy = ActiveRecord::QueryCache::BodyProxy.new(nil, body)
+ assert proxy.respond_to?(:to_path)
+ assert_equal proxy.to_path, "/path"
+ end
+
+end \ No newline at end of file
diff --git a/activesupport/lib/active_support/core_ext/class/attribute.rb b/activesupport/lib/active_support/core_ext/class/attribute.rb
index 7baba75ad3..ca9b2c1b60 100644
--- a/activesupport/lib/active_support/core_ext/class/attribute.rb
+++ b/activesupport/lib/active_support/core_ext/class/attribute.rb
@@ -1,5 +1,6 @@
require 'active_support/core_ext/kernel/singleton_class'
require 'active_support/core_ext/module/remove_method'
+require 'active_support/core_ext/array/extract_options'
class Class
# Declare a class-level attribute whose value is inheritable by subclasses.
@@ -56,11 +57,18 @@ class Class
# object.setting # => false
# Base.setting # => true
#
+ # To opt out of the instance reader method, pass :instance_reader => false.
+ #
+ # object.setting # => NoMethodError
+ # object.setting? # => NoMethodError
+ #
# To opt out of the instance writer method, pass :instance_writer => false.
#
# object.setting = false # => NoMethodError
def class_attribute(*attrs)
- instance_writer = !attrs.last.is_a?(Hash) || attrs.pop[:instance_writer]
+ options = attrs.extract_options!
+ instance_reader = options.fetch(:instance_reader, true)
+ instance_writer = options.fetch(:instance_writer, true)
attrs.each do |name|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
@@ -84,13 +92,15 @@ class Class
val
end
- remove_possible_method :#{name}
- def #{name}
- defined?(@#{name}) ? @#{name} : self.class.#{name}
- end
+ if instance_reader
+ remove_possible_method :#{name}
+ def #{name}
+ defined?(@#{name}) ? @#{name} : self.class.#{name}
+ end
- def #{name}?
- !!#{name}
+ def #{name}?
+ !!#{name}
+ end
end
RUBY
diff --git a/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb b/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb
index c2a6476604..0b368fe7b7 100644
--- a/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb
+++ b/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb
@@ -11,7 +11,7 @@ class Hash
end
# Called when object is nested under an object that receives
- # #with_indifferent_access. This method with be called on the current object
+ # #with_indifferent_access. This method will be called on the current object
# by the enclosing object and is aliased to #with_indifferent_access by
# default. Subclasses of Hash may overwrite this method to return +self+ if
# converting to an +ActiveSupport::HashWithIndifferentAccess+ would not be
diff --git a/activesupport/test/core_ext/class/attribute_test.rb b/activesupport/test/core_ext/class/attribute_test.rb
index d58b60482b..e290a6e012 100644
--- a/activesupport/test/core_ext/class/attribute_test.rb
+++ b/activesupport/test/core_ext/class/attribute_test.rb
@@ -60,6 +60,12 @@ class ClassAttributeTest < ActiveSupport::TestCase
assert_raise(NoMethodError) { object.setting = 'boom' }
end
+ test 'disabling instance reader' do
+ object = Class.new { class_attribute :setting, :instance_reader => false }.new
+ assert_raise(NoMethodError) { object.setting }
+ assert_raise(NoMethodError) { object.setting? }
+ end
+
test 'works well with singleton classes' do
object = @klass.new
object.singleton_class.setting = 'foo'
diff --git a/railties/CHANGELOG b/railties/CHANGELOG
index 880849d2ec..f2b0cf15cd 100644
--- a/railties/CHANGELOG
+++ b/railties/CHANGELOG
@@ -1,5 +1,7 @@
*Rails 3.2.0 (unreleased)*
+* Attributes on scaffold and model generators default to string. This allows the following: "rails g scaffold Post title body:text author" [José Valim]
+
* Removed old plugin generator (`rails generate plugin`) in favor of `rails plugin new` command. [Guillermo Iguaran]
* Removed old 'config.paths.app.controller' API in favor of 'config.paths["app/controller"]' API. [Guillermo Iguaran]
diff --git a/railties/guides/source/action_view_overview.textile b/railties/guides/source/action_view_overview.textile
index a3454579ad..7703d6c720 100644
--- a/railties/guides/source/action_view_overview.textile
+++ b/railties/guides/source/action_view_overview.textile
@@ -165,7 +165,7 @@ will produce
<em>emphasized</em>
<em><b>emph &amp; bold</b></em>
<a href="http://rubyonrails.org">A link</a>
-<target option="fast" name="compile" \>
+<target option="fast" name="compile" />
</html>
Any method with a block will be treated as an XML markup tag with nested markup in the block. For example, the following:
@@ -211,7 +211,7 @@ xml.rss("version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/") do
end
</ruby>
-h5. Template caching
+h5. Template Caching
By default, Rails will compile each template to a method in order to render it. When you alter a template, Rails will check the file's modification time and recompile it in development mode.
@@ -235,7 +235,7 @@ This will render a file named +_menu.html.erb+ at that point within the view is
That code will pull in the partial from +app/views/shared/_menu.html.erb+.
-h5. Using Partials to Simplify Views
+h5. Using Partials to simplify Views
One way to use partials is to treat them as the equivalent of subroutines: as a way to move details out of a view so that you can grasp what's going on more easily. For example, you might have a view that looked like this:
diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile
index 1fe805d2d7..221d20fee6 100644
--- a/railties/guides/source/active_support_core_extensions.textile
+++ b/railties/guides/source/active_support_core_extensions.textile
@@ -1036,18 +1036,24 @@ module ActionView
end
</ruby>
-we can access +field_error_proc+ in views. The generation of the writer instance method can be prevented by setting +:instance_writer+ to +false+ (not any false value, but exactly +false+):
+we can access +field_error_proc+ in views.
+
+The generation of the reader instance method can be prevented by setting +:instance_reader+ to +false+ and the generation of the writer instance method can be prevented by setting +:instance_writer+ to +false+. Generation of both methods can be prevented by setting +:instance_accessor+ to +false+. In all cases, the value must be exactly +false+ and not any false value.
<ruby>
-module ActiveRecord
- class Base
- # No pluralize_table_names= instance writer is generated.
- cattr_accessor :pluralize_table_names, :instance_writer => false
+module A
+ class B
+ # No first_name instance reader is generated.
+ cattr_accessor :first_name, :instance_reader => false
+ # No last_name= instance writer is generated.
+ cattr_accessor :last_name, :instance_writer => false
+ # No surname instance reader or surname= writer is generated.
+ cattr_accessor :surname, :instance_accessor => false
end
end
</ruby>
-A model may find that option useful as a way to prevent mass-assignment from setting the attribute.
+A model may find it useful to set +:instance_accessor+ to +false+ as a way to prevent mass-assignment from setting the attribute.
NOTE: Defined in +active_support/core_ext/class/attribute_accessors.rb+.
@@ -2300,7 +2306,7 @@ NOTE: Defined in +active_support/core_ext/array/grouping.rb+.
h5. +in_groups(number, fill_with = nil)+
-The method +in_groups+ splits an array into a certain number of groups. The method returns and array with the groups:
+The method +in_groups+ splits an array into a certain number of groups. The method returns an array with the groups:
<ruby>
%w(1 2 3 4 5 6 7).in_groups(3)
@@ -2732,7 +2738,7 @@ Active Support extends the method +Range#step+ so that it can be invoked without
(1..10).step(2) # => [1, 3, 5, 7, 9]
</ruby>
-As the example shows, in that case the method returns and array with the corresponding elements.
+As the example shows, in that case the method returns an array with the corresponding elements.
NOTE: Defined in +active_support/core_ext/range/blockless_step.rb+.
@@ -3334,6 +3340,32 @@ Active Support defines +Time.current+ to be today in the current time zone. That
When making Time comparisons using methods which honor the user time zone, make sure to use +Time.current+ and not +Time.now+. There are cases where the user time zone might be in the future compared to the system time zone, which +Time.today+ uses by default. This means +Time.now+ may equal +Time.yesterday+.
+h5. +all_day+, +all_week+, +all_month+, +all_quarter+ and +all_year+
+
+The method +all_day+ returns a range representing the whole day of the current time.
+
+<ruby>
+now = Time.current
+# => Mon, 09 Aug 2010 23:20:05 UTC +00:00
+now.all_day
+# => Mon, 09 Aug 2010 00:00:00 UTC +00:00..Mon, 09 Aug 2010 23:59:59 UTC +00:00
+</ruby>
+
+Analogously, +all_week+, +all_month+, +all_quarter+ and +all_year+ all serve the purpose of generating time ranges.
+
+<ruby>
+now = Time.current
+# => Mon, 09 Aug 2010 23:20:05 UTC +00:00
+now.all_week
+# => Mon, 09 Aug 2010 00:00:00 UTC +00:00..Sun, 15 Aug 2010 23:59:59 UTC +00:00
+now.all_month
+# => Sat, 01 Aug 2010 00:00:00 UTC +00:00..Tue, 31 Aug 2010 23:59:59 UTC +00:00
+now.all_quarter
+# => Thu, 01 Jul 2010 00:00:00 UTC +00:00..Thu, 30 Sep 2010 23:59:59 UTC +00:00
+now.all_year
+# => Fri, 01 Jan 2010 00:00:00 UTC +00:00..Fri, 31 Dec 2010 23:59:59 UTC +00:00
+</ruby>
+
h4. Time Constructors
Active Support defines +Time.current+ to be +Time.zone.now+ if there's a user time zone defined, with fallback to +Time.now+:
diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile
index c12bc3d1dc..1b444811a2 100644
--- a/railties/guides/source/asset_pipeline.textile
+++ b/railties/guides/source/asset_pipeline.textile
@@ -3,6 +3,7 @@ h2. Asset Pipeline
This guide will cover the ideology of the asset pipeline introduced in Rails 3.1.
By referring to this guide you will be able to:
+* Understand what the asset pipeline is and what it does
* Properly organize your application assets
* Understand the benefits of the asset pipeline
* Adding a preprocessor to the pipeline
@@ -12,46 +13,97 @@ endprologue.
h3. What Is The Asset Pipeline?
-The asset pipeline is a new feature introduced in Rails 3.1 using the "Sprockets":http://getsprockets.org/ engine. It allows developers to place design elements in +app/assets+ instead of +public+, there are many advantages to this. A big one is that they are now processed by Rails instead of your webserver, allowing you to use preprocessors like CoffeeScript, SCSS, or ERB. Another advantage is that your CSS and JavaScript is compiled into one file by default, this allows users to cache all the CSS and JavaScript data so your pages render faster. Not to mention how much cleaner your application will become.
+With Rails 3.1 comes a new feature known as the asset pipeline. The asset pipeline provides features that have usually been implemented by external gems, such as Jammit and Sprockets. These gems would serve concatenated or compressed versions of the assets of an application, such as stylesheets or javascript files so that the number of requests made to the server are lessened, making the page load faster.
+
+By having this now as a core feature of Rails, all developers can benefit from the power of having their assets pre-processed, compressed and minified by one central gem, Sprockets.
h3. How to Use the Asset Pipeline
-The asset pipeline is easy to migrate to and use. There are a few things that you'll need to learn first, like where to place your files, how to create a manifest, and how to add any preproccesors if you desire.
+In previous versions of Rails, all assets lived under the +public+ directory in directories such as +images+, +javascripts+ and +stylesheets+. With Rails 3.1, the preferred location for these assets is now the +app/assets+ directory. Files in this directory will be served by the Sprockets middleware included in the sprockets gem.
+
+This is not to say that assets can (or should) no longer be placed in +public+. They still can be, they will just be served by the application or the web server which is running the application and served just like normal files. You would only use +app/assets+ if you wish your files to undergo some pre-processing before they are served.
+
+When a scaffold or controller is generated for the application, Rails will also generate a JavaScript (or CoffeeScript if the +coffee-script+ gem is in the +Gemfile+) and CSS (or SCSS if +sass-rails+ is in the +Gemfile+) file for that controller. For example, if a +ProjectsController+ is generated, there will be a new file at +app/assets/javascripts/projects.js.coffee+ and another at +app/assets/stylesheets/projects.css.scss+. It's in these files that JavaScript and CSS unique to this part of the application belong.
h4. Asset Organization
-WIP
+Assets can be placed inside an application in one of three locations: +app/assets+, +lib/assets+ or +vendor/assets+.
+
++app/assets+ is for assets that are owned by the application, such as custom images, javascript files or stylesheets.
+
++lib/assets+ is for your own libraries' code that doesn't really fit into the scope of the application or those libraries which are shared across applications.
+
++vendor/assets+ is for assets that are owned by outside entities, such as code for JavaScript plugins.
+
+Any subdirectory that exists within these three locations will be added to the search path for Sprockets (visible by calling +Rails.application.config.assets.paths+ in a console). When an asset is requested, these paths will be looked through to see if they contain an asset matching the name specified. Once an asset has been found, it's processed by Sprockets and then served up.
+
+h4. External Assets
+
+Assets can also come from external sources such as engines. A good example of this is the +jquery_rails+ gem which comes with Rails 3.1 as standard. This gem contains an engine class which inherits from +Rails::Engine+. By doing this, Rails is informed that the directory for this gem may contain assets and the +app/assets+, +lib/assets+ and +vendor/assets+ directories of this engine are added to the search path of Sprockets.
+
+h4. Serving Assets
+
+To serve assets, we can use the same tags that we are generally familiar with:
+
+<erb>
+ <%= image_tag "rails.png" %>
+</erb>
+
+Providing that assets are enabled within our application (+Rails.application.config.assets.enabled+ is set to +true+), this file will be served by Sprockets unless a file at +public/images/rails.png+ exists, in which case that file will be served. If there is no file at +public/images+, Sprockets will look through the available paths until it finds a file that matches the name and then will serve it, first looking in the application's assets directories and then falling back to the various engines of the application.
+
+To include a JavaScript file we can still use the familiar +javascript_include_tag+.
+
+<erb>
+ <%= javascript_include_tag "application" %>
+</erb>
+
+Similarly, to include a CSS file we can also still use +stylesheet_link_tag+.
+
+<erb>
+ <%= stylesheet_link_tag "application" %>
+</erb>
+
+These files could just be straight JavaScript or CSS files, or they could be _manifest files_.
-Sprockets will automatically load manifest files by searching directories in app/assets and including the first file with a basename of index. (Confirm and add: does it load app/assets/index?)
+h4. Manifest Files and Directives
-h4. Directives
+Sprockets allows some assets to be manifest files. These manifest files require what's known as _directives_, which instruct Sprockets which files to require in order to build a single CSS or JavaScript file. With these directives, Sprockets will load the files specified, process them if necessary, concatenate them into one single file and then compress them (if +Rails.application.config.assets.compress+ is set to +true+). By serving one file rather than many, a page's load time can be greatly reduced.
-WIP
+For example, in the default Rails application there's a +app/assets/javascripts/application.js+ file which contains the following lines:
-Sprockets, the rails tie that powers the asset pipeline, provides three directives which are like Ruby's methods. They are: +require+, +require_tree+, and +require_self+. These directives must be called at the top of a file in a comment with an equal sign before it. (note: CSS directives need *= if in a continuous comment -- confirm please)
+<plain>
+ //= require jquery
+ //= require jquery_ujs
+ //= require_tree .
+</plain>
-The require directive loads a file with the supplied basename from the following paths: app/assets/*, lib/assets/*, vendor/assets/*, as well as any of your gem's asset files.
+In JS files, directives begin with +//=+. In this case, the file is using the +require+ directive twice and the +require_tree+ directive once. The +require+ directive tells Sprockets that we would like to require a file called +jquery.js+ that is available somewhere in the search path for Sprockets. By default, this is located inside the +vendor/assets/javascripts+ directory contained within the +jquery_rails+ gem. An identical event takes place for the +jquery_ujs+ require specified here also.
-Using the +require_tree+ directive you can easily include an entire folder of assets. The paths must be relative, so begin them with either a forward slash or dots. For example to include a folder in the same directory you would do +require_tree ./folder_name+
+The +require_tree .+ directive tells Sprockets to include _all_ JavaScript files in this directory into the output. A path relative to the file can be specified if only certain files are required to be loaded.
-Require self does... something
+There's also a default +app/assets/stylesheets/application.css+ file which contains these lines:
-h4. Stacking Preprocessors
+<plain>
+ /* ...
+ *= require_self
+ *= require_tree .
+ */
+</plain>
-Sprockets allows you to stack preprocessors. The stack is ran off the file extensions in a last in, first out method (like popping an array). For example if we want to make a JavaScript asset with both CoffeeScript and ERB the file would be named: +name.js.coffee.erb+. If it were named +name.js.erb.coffee+ CoffeeScript would raise an error because it doesn't understand ERB tags.
+The directives that work in the JavaScript files will also work in stylesheets, obviously requiring stylesheets rather than JavaScript files. The +require_tree+ directive here works the same way as the JavaScript one, requiring all stylesheets from the current directory.
-h4. Adding a Preproccessor
+In this example +require_self+ is used. This will put the CSS contained within the file (if any) at the top of any other CSS in this file unless +require_self+ is specified after another +require+ directive.
-WIP
+h4. Preprocessing
-https://github.com/rtomayko/tilt for gems or config.register_processor('text/css', MyAwesomeProccessor) for local stuff
+Based on the extensions of the assets, Sprockets will do preprocessing on the files. With the default gemset that comes with Rails, when a controller or a scaffold is generated, a CoffeeScript file and a SCSS file will be generated in place of a regular JavaScript and CSS file. The example used before was a controller called "projects", which generated an +app/assets/javascripts/projects.js.coffee+ and a +app/assets/stylesheets/projects.css.scss+ file.
-h3. Packaging Assets with Your Gems
+When these files are requested, they will be processed by the processors provided by the +coffee-script+ and +sass-rails+ gems and then sent back to the browser as JavaScript and SCSS respectively.
-You may find it useful to package certain assets with your gem. A good example would be the "pjax_rails":https://github.com/rails/pjax_rails/ gem. This gem bundles the latest "PJAX":https://github.com/defunkt/jquery-pjax library and some helper methods. If you take a look at the source of pjax_rails, you'll see that it bundles the assets in +lib/assets+ just the same way as you would in +app/assets+. Doing so allows pjax_rails to update JavaScripts without asking users to copy them into their public folder
+In addition to this single layer of pre-processing, we can also put on additional extensions to the end of the file in order for them to be processed using other languages first. For example, we could call our stylesheet +app/assets/stylesheets/projects.css.scss.erb+ it would first be processed as ERB, then SCSS and finally served as CSS. We could also do this with our JavaScript file, calling it +app/assets/javascripts/projects.js.coffee.erb+.
-If you want the user to load your JavaScript files in their template, you will have to ask them to add a directive to do so. Also avoid any common names such as +form_check.js+ instead try using +mygem/form_check.js+ so it's clear where it's coming from. This will also make it unlikely that your users will create a file with the same name causing the asset pipeline to choose the user's file over yours.
+Keep in mind that the order of these pre-processors is important. For example, if we called our JavaScript file +app/assets/javascripts/projects.js.erb.coffee+ then it would be processed with the CoffeeScript interpreter first, which wouldn't understand ERB and therefore we would run into problems.
-h3. More on Sprockets
+h4. Compressing Assets
-Sprockets is the engine that handles the asset pipeline in Rails 3.1 and above. Their official website is available at "http://getsprockets.org/":http://getsprockets.org/ and the source code is "available on github":https://github.com/sstephenson/sprockets.
+WIP: Compressed Assets in Rails are served ... how? \ No newline at end of file
diff --git a/railties/guides/source/caching_with_rails.textile b/railties/guides/source/caching_with_rails.textile
index f058dce42b..252003edd0 100644
--- a/railties/guides/source/caching_with_rails.textile
+++ b/railties/guides/source/caching_with_rails.textile
@@ -382,6 +382,7 @@ class ProductsController < ApplicationController
# anything. The default render checks for this using the parameters
# used in the previous call to stale? and will automatically send a
# :not_modified. So that's it, you're done.
+ end
end
</ruby>
diff --git a/railties/guides/source/command_line.textile b/railties/guides/source/command_line.textile
index 026c15feba..b0edc1017d 100644
--- a/railties/guides/source/command_line.textile
+++ b/railties/guides/source/command_line.textile
@@ -51,15 +51,13 @@ $ rails new commandsapp
Rails will set you up with what seems like a huge amount of stuff for such a tiny command! You've got the entire Rails directory structure now with all the code you need to run our simple application right out of the box.
-INFO: This output will seem very familiar when we get to the +generate+ command. Creepy foreshadowing!
-
h4. +rails server+
-The +rails server+ command launches a small web server named WEBrick which comes bundled with Ruby. You'll use this any time you want to view your work through a web browser.
+The +rails server+ command launches a small web server named WEBrick which comes bundled with Ruby. You'll use this any time you want to access your application through a web browser.
-INFO: WEBrick isn't your only option for serving Rails. We'll get to that in a later section.
+INFO: WEBrick isn't your only option for serving Rails. We'll get to that "later":#different-servers.
-Without any prodding of any kind, +rails server+ will run our new shiny Rails app:
+With no further work, +rails server+ will run our new shiny Rails app:
<shell>
$ cd commandsapp
@@ -77,13 +75,19 @@ With just three commands we whipped up a Rails server listening on port 3000. Go
You can also use the alias "s" to start the server: <tt>rails s</tt>.
+The server can be run on a different port using the +-p+ option. The default development environment can be changed using +-e+.
+
+<shell>
+$ rails server -e production -p 4000
+</shell>
+
h4. +rails generate+
-The +rails generate+ command uses templates to create a whole lot of things. You can always find out what's available by running +rails generate+ by itself. Let's do that:
+The +rails generate+ command uses templates to create a whole lot of things. Running +rails generate+ by itself gives a list of available generators:
<shell>
$ rails generate
-Usage: rails generate generator [args] [options]
+Usage: rails generate GENERATOR [args] [options]
...
...
@@ -99,7 +103,7 @@ Rails:
NOTE: You can install more generators through generator gems, portions of plugins you'll undoubtedly install, and you can even create your own!
-Using generators will save you a large amount of time by writing *boilerplate code*, code that is necessary for the app to work, but not necessary for you to spend time writing. That's what we have computers for.
+Using generators will save you a large amount of time by writing *boilerplate code*, code that is necessary for the app to work.
Let's make our own controller with the controller generator. But what command should we use? Let's ask the generator:
@@ -148,7 +152,8 @@ $ rails generate controller Greetings hello
create test/unit/helpers/greetings_helper_test.rb
invoke assets
create app/assets/javascripts/greetings.js
- create app/assets/stylesheets/greetings.css
+ invoke css
+ create app/assets/stylesheets/greetings.css
</shell>
@@ -171,7 +176,7 @@ Then the view, to display our message (in +app/views/greetings/hello.html.erb+):
<p><%= @message %></p>
</html>
-Deal. Go check it out in your browser. Fire up your server using +rails server+.
+Fire up your server using +rails server+.
<shell>
$ rails server
@@ -184,7 +189,7 @@ The URL will be "http://localhost:3000/greetings/hello":http://localhost:3000/gr
INFO: With a normal, plain-old Rails application, your URLs will generally follow the pattern of http://(host)/(controller)/(action), and a URL like http://(host)/(controller) will hit the *index* action of that controller.
-Rails comes with a generator for data models too:
+Rails comes with a generator for data models too.
<shell>
$ rails generate model
@@ -288,11 +293,7 @@ You can also use the alias "db" to invoke the dbconsole: <tt>rails db</tt>.
h4. +rails plugin+
-The +rails plugin+ command simplifies plugin management; think a miniature version of the Gem utility. Let's walk through installing a plugin. You can call the sub-command +discover+, which sifts through repositories looking for plugins, or call +source+ to add a specific repository of plugins, or you can specify the plugin location directly.
-
-Let's say you're creating a website for a client who wants a small accounting system. Every event having to do with money must be logged, and must never be deleted. Wouldn't it be great if we could override the behavior of a model to never actually take its record out of the database, but instead, just set a field?
-
-There is such a thing! The plugin we're installing is called +acts_as_paranoid+, and it lets models implement a +deleted_at+ column that gets set when you call destroy. Later, when calling find, the plugin will tack on a database check to filter out "deleted" things.
+The +rails plugin+ command simplifies plugin management. Plugins can be installed by name or their repository URLs. You need to have Git installed if you want to install a plugin from a Git repo. The same holds for Subversion too.
<shell>
$ rails plugin install https://github.com/technoweenie/acts_as_paranoid.git
@@ -310,6 +311,12 @@ h4. +rails runner+
$ rails runner "Model.long_running_method"
</shell>
+You can specify the environment in which the +runner+ command should operate using the +-e+ switch.
+
+<shell>
+$ rails runner -e staging "Model.long_running_method"
+</shell>
+
h4. +rails destroy+
Think of +destroy+ as the opposite of +generate+. It'll figure out what generate did, and undo it.
@@ -388,13 +395,56 @@ h4. +db+
The most common tasks of the +db:+ Rake namespace are +migrate+ and +create+, and it will pay off to try out all of the migration rake tasks (+up+, +down+, +redo+, +reset+). +rake db:version+ is useful when troubleshooting, telling you the current version of the database.
+More information about migrations can be found in the "Migrations":migrations.html guide.
+
h4. +doc+
-If you want to strip out or rebuild any of the Rails documentation (including this guide!), the +doc:+ namespace has the tools. Stripping documentation is mainly useful for slimming your codebase, like if you're writing a Rails application for an embedded platform.
+The +doc:+ namespace has the tools to generate documentation for your app, API documentation, guides. Documentation can also be stripped which is mainly useful for slimming your codebase, like if you're writing a Rails application for an embedded platform.
+
+* +rake doc:app+ generates documentation for your application in +doc/app+.
+* +rake doc:guides+ generates Rails guides in +doc/guides+.
+* +rake doc:rails+ generates API documentation for Rails in +doc/api+.
+* +rake doc:plugins+ generates API documentation for all the plugins installed in the application in +doc/plugins+.
+* +rake doc:clobber_plugins+ removes the generated documentation for all plugins.
h4. +notes+
-These tasks will search through your code for commented lines beginning with "FIXME", "OPTIMIZE", "TODO", or any custom annotation (like XXX) and show you them.
++rake notes+ will search through your code for comments beginning with FIXME, OPTIMIZE or TODO. The search is only done in files with extension +.builder+, +.rb+, +.rxml+, +.rhtml+ and +.erb+ for both default and custom annotations.
+
+<shell>
+$ rake notes
+(in /home/foobar/commandsapp)
+app/controllers/admin/users_controller.rb:
+ * [ 20] [TODO] any other way to do this?
+ * [132] [FIXME] high priority for next deploy
+
+app/model/school.rb:
+ * [ 13] [OPTIMIZE] refactor this code to make it faster
+ * [ 17] [FIXME]
+</shell>
+
+If you are looking for a specific annotation, say FIXME, you can use +rake notes:fixme+. Note that you have to lower case the annotation's name.
+
+<shell>
+$ rake notes:fixme
+(in /home/foobar/commandsapp)
+app/controllers/admin/users_controller.rb:
+ * [132] high priority for next deploy
+
+app/model/school.rb:
+ * [ 17]
+</shell>
+
+You can also use custom annotations in your code and list them using +rake notes:custom+ by specifying the annotation using an environment variable +ANNOTATION+.
+
+<shell>
+$ rake notes:custom ANNOTATION=BUG
+(in /home/foobar/commandsapp)
+app/model/post.rb:
+ * [ 23] Have to fix this one before pushing!
+</shell>
+
+NOTE. When using specific annotations and custom annotations, the annotation name (FIXME, BUG etc) is not displayed in the output lines.
h4. +routes+
@@ -478,11 +528,13 @@ development:
...
</shell>
-It also generated some lines in our database.yml configuration corresponding to our choice of PostgreSQL for database. The only catch with using the SCM options is that you have to make your application's directory first, then initialize your SCM, then you can run the +rails new+ command to generate the basis of your app.
+It also generated some lines in our database.yml configuration corresponding to our choice of PostgreSQL for database.
+
+NOTE. The only catch with using the SCM options is that you have to make your application's directory first, then initialize your SCM, then you can run the +rails new+ command to generate the basis of your app.
-h4. +server+ with Different Backends
+h4(#different-servers). +server+ with Different Backends
-Many people have created a large number different web servers in Ruby, and many of them can be used to run Rails. Since version 2.3, Rails uses Rack to serve its webpages, which means that any webserver that implements a Rack handler can be used. This includes WEBrick, Mongrel, Thin, and Phusion Passenger (to name a few!).
+Many people have created a large number of different web servers in Ruby, and many of them can be used to run Rails. Since version 2.3, Rails uses Rack to serve its webpages, which means that any webserver that implements a Rack handler can be used. This includes WEBrick, Mongrel, Thin, and Phusion Passenger (to name a few!).
NOTE: For more details on the Rack integration, see "Rails on Rack":rails_on_rack.html.
diff --git a/railties/guides/source/configuring.textile b/railties/guides/source/configuring.textile
index 80de36070d..8e6010ff79 100644
--- a/railties/guides/source/configuring.textile
+++ b/railties/guides/source/configuring.textile
@@ -98,7 +98,7 @@ NOTE. The +config.asset_path+ configuration is ignored if the asset pipeline is
* +config.secret_token+ used for specifying a key which allows sessions for the application to be verified against a known secure key to prevent tampering. Applications get +config.secret_token+ initialized to a random key in +config/initializers/secret_token.rb+.
-* +config.serve_static_assets+ configures Rails to serve static assets. Defaults to true, but in the production environment is turned off. The server software used to run the application should be used to serve the assets instead.
+* +config.serve_static_assets+ configures Rails itself to serve static assets. Defaults to true, but in the production environment is turned off as the server software (e.g. Nginx or Apache) used to run the application should serve static assets instead. Unlike the default setting set this to true when running (absolutely not recommended!) or testing your app in production mode using WEBrick. Otherwise you won´t be able use page caching and requests for files that exist regularly under the public directory will anyway hit your Rails app.
* +config.session_store+ is usually set up in +config/initializers/session_store.rb+ and specifies what class to use to store the session. Possible values are +:cookie_store+ which is the default, +:mem_cache_store+, and +:disabled+. The last one tells Rails not to deal with sessions. Custom session stores can also be specified:
@@ -116,8 +116,23 @@ WARNING: Threadsafe operation is incompatible with the normal workings of develo
* +config.whiny_nils+ enables or disables warnings when a certain set of methods are invoked on +nil+ and it does not respond to them. Defaults to true in development and test environments.
+h4. Configuring Assets
+
+Rails 3.1, by default, is set up to use the +sprockets+ gem to manage assets within an application. This gem concatenates and compresses assets in order to make serving them much less painful.
+
+* +config.assets.css_compressor+ defines the CSS compressor to use. Only supported value at the moment is +:yui+, which uses the +yui-compressor+ gem.
+
* +config.assets.enabled+ a flag that controls whether the asset pipeline is enabled. It is explicitly initialized in +config/application.rb+.
+* +config.assets.js_compressor+ defines the JavaScript compressor to use. Possible values are +:closure+, +:uglifier+ and +:yui+ which require the use of the +closure-compiler+, +uglifier+ or +yui-compressor+ gems respectively.
+
+* +config.assets.paths+ contains the paths which are used to look for assets. Appending paths to this configuration option will cause those paths to be used in the search for assets.
+
+* +config.assets.precompile+ allows you to specify additional assets (other than +application.css+ and +application.js+) which are to be precompiled when +rake assets:precompile+ is run.
+
+* +config.assets.prefix+ defines the prefix where assets are served from. Defaults to +/assets+.
+
+
h4. Configuring Generators
Rails 3 allows you to alter what generators are used with the +config.generators+ method. This method takes a block:
diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile
index 670979c3c2..3011f7136b 100644
--- a/railties/guides/source/getting_started.textile
+++ b/railties/guides/source/getting_started.textile
@@ -177,14 +177,14 @@ In any case, Rails will create a folder in your working directory called <tt>blo
|Gemfile|This file allows you to specify what gem dependencies are needed for your Rails application.|
|README|This is a brief instruction manual for your application. Use it to tell others what your application does, how to set it up, and so on.|
|Rakefile|This file contains batch jobs that can be run from the terminal.|
-|app/|Contains the controllers, models, and views for your application. You'll focus on this folder for the remainder of this guide.|
+|app/|Contains the controllers, models, views and assets for your application. You'll focus on this folder for the remainder of this guide.|
|config/|Configure your application's runtime rules, routes, database, and more.|
|config.ru|Rack configuration for Rack based servers used to start the application.|
|db/|Shows your current database schema, as well as the database migrations. You'll learn about migrations shortly.|
|doc/|In-depth documentation for your application.|
|lib/|Extended modules for your application (not covered in this guide).|
|log/|Application log files.|
-|public/|The only folder seen to the world as-is. This is where your images, JavaScript files, stylesheets (CSS), and other static files go.|
+|public/|The only folder seen to the world as-is. Contains the static files and compiled assets.|
|script/|Contains the rails script that starts your app and can contain other scripts you use to deploy or run your application.|
|test/|Unit tests, fixtures, and other test apparatus. These are covered in "Testing Rails Applications":testing.html|
|tmp/|Temporary files|
@@ -244,7 +244,7 @@ If your development computer's MySQL installation includes a root user with an e
h5. Configuring a PostgreSQL Database
-Finally if you choose to use PostgreSQL, your +config/database.yml+ will be customized to use PostgreSQL databases:
+If you choose to use PostgreSQL, your +config/database.yml+ will be customized to use PostgreSQL databases:
<yaml>
development:
@@ -256,6 +256,41 @@ development:
password:
</yaml>
+h5. Configuring an SQLite3 Database for JRuby Platform
+
+If you choose to use SQLite3 and using JRuby, your +config/database.yml+ will look a little different. Here's the development section:
+
+<yaml>
+development:
+ adapter: jdbcsqlite3
+ database: db/development.sqlite3
+</yaml>
+
+h5. Configuring a MySQL Database for JRuby Platform
+
+If you choose to use MySQL and using JRuby, your +config/database.yml+ will look a little different. Here's the development section:
+
+<yaml>
+development:
+ adapter: jdbcmysql
+ database: blog_development
+ username: root
+ password:
+</yaml>
+
+h5. Configuring a PostgreSQL Database for JRuby Platform
+
+Finally if you choose to use PostgreSQL and using JRuby, your +config/database.yml+ will look a little different. Here's the development section:
+
+<yaml>
+development:
+ adapter: jdbcpostgresql
+ encoding: unicode
+ database: blog_development
+ username: blog
+ password:
+<yaml>
+
Change the username and password in the +development+ section as appropriate.
TIP: You don't have to update the database configurations manually. If you had a look at the options of application generator, you have seen that one of them is named <tt>--database</tt>. It lets you choose an adapter for couple of most used relational databases. You can even run the generator repeatedly: <tt>cd .. && rails new blog --database=mysql</tt>. When you confirm the overwriting of the +config/database.yml+ file, your application will be configured for MySQL instead of SQLite.
@@ -290,7 +325,7 @@ This will fire up an instance of the WEBrick web server by default (Rails can al
TIP: To stop the web server, hit Ctrl+C in the terminal window where it's running. In development mode, Rails does not generally require you to stop the server; changes you make in files will be automatically picked up by the server.
-The "Welcome Aboard" page is the _smoke test_ for a new Rails application: it makes sure that you have your software configured correctly enough to serve a page. You can also click on the _About your application’s environment_ link to see a summary of your Application's environment.
+The "Welcome Aboard" page is the _smoke test_ for a new Rails application: it makes sure that you have your software configured correctly enough to serve a page. You can also click on the _About your application’s environment_ link to see a summary of your application's environment.
h4. Say "Hello", Rails
@@ -364,11 +399,11 @@ The scaffold generator will build 15 files in your application, along with some
|app/views/posts/new.html.erb |A view to create a new post|
|app/views/posts/_form.html.erb |A partial to control the overall look and feel of the form used in edit and new views|
|app/helpers/posts_helper.rb |Helper functions to be used from the post views|
+|app/assets/stylesheets/scaffold.css.scss |Cascading style sheet to make the scaffolded views look better|
|test/unit/post_test.rb |Unit testing harness for the posts model|
|test/functional/posts_controller_test.rb |Functional testing harness for the posts controller|
|test/unit/helpers/posts_helper_test.rb |Unit testing harness for the posts helper|
|config/routes.rb |Edited to include routing information for posts|
-|app/assets/stylesheets/scaffold.css.scss |Cascading style sheet to make the scaffolded views look better|
h4. Running a Migration
diff --git a/railties/guides/source/nested_model_forms.textile b/railties/guides/source/nested_model_forms.textile
index 55694c0eb4..4b1fd2e0ac 100644
--- a/railties/guides/source/nested_model_forms.textile
+++ b/railties/guides/source/nested_model_forms.textile
@@ -90,7 +90,7 @@ h3. Views
h4. Controller code
-A nested model form will _only_ be build if the associated object(s) exist. This means that for a new model instance you would probably want to build the associated object(s) first.
+A nested model form will _only_ be built if the associated object(s) exist. This means that for a new model instance you would probably want to build the associated object(s) first.
Consider the following typical RESTful controller which will prepare a new Person instance and its +address+ and +projects+ associations before rendering the +new+ template:
@@ -144,7 +144,7 @@ Now add a nested form for the +address+ association:
<%= f.text_field :name %>
<%= f.fields_for :address do |af| %>
- <%= f.text_field :street %>
+ <%= af.text_field :street %>
<% end %>
<% end %>
</erb>
@@ -159,7 +159,7 @@ This generates:
</form>
</html>
-Notice that +fields_for+ recognized the +address+ as an association for which a nested model form should be build by the way it has namespaced the +name+ attribute.
+Notice that +fields_for+ recognized the +address+ as an association for which a nested model form should be built by the way it has namespaced the +name+ attribute.
When this form is posted the Rails parameter parser will construct a hash like the following:
@@ -185,7 +185,7 @@ The form code for an association collection is pretty similar to that of a singl
<%= f.text_field :name %>
<%= f.fields_for :projects do |pf| %>
- <%= f.text_field :name %>
+ <%= pf.text_field :name %>
<% end %>
<% end %>
</erb>
@@ -201,7 +201,7 @@ Which generates:
</form>
</html>
-As you can see it has generated 2 +project name+ inputs, one for each new +project+ that’s build in the controllers +new+ action. Only this time the +name+ attribute of the input contains a digit as an extra namespace. This will be parsed by the Rails parameter parser as:
+As you can see it has generated 2 +project name+ inputs, one for each new +project+ that was built in the controller's +new+ action. Only this time the +name+ attribute of the input contains a digit as an extra namespace. This will be parsed by the Rails parameter parser as:
<ruby>
{
@@ -215,7 +215,7 @@ As you can see it has generated 2 +project name+ inputs, one for each new +proje
}
</ruby>
-You can basically see the +projects_attributes+ hash as an array of attribute hashes. One for each model instance.
+You can basically see the +projects_attributes+ hash as an array of attribute hashes, one for each model instance.
NOTE: The reason that +fields_for+ constructed a form which would result in a hash instead of an array is that it won't work for any forms nested deeper than one level deep.
diff --git a/railties/guides/source/performance_testing.textile b/railties/guides/source/performance_testing.textile
index fe0915bfea..a4187a3135 100644
--- a/railties/guides/source/performance_testing.textile
+++ b/railties/guides/source/performance_testing.textile
@@ -66,7 +66,7 @@ resources :posts
# home_controller.rb
class HomeController < ApplicationController
def dashboard
- @users = User.last_ten(:include => :avatars)
+ @users = User.last_ten.includes(:avatars)
@posts = Post.all_today
end
end
@@ -481,7 +481,7 @@ h4. +profiler+
Usage:
<shell>
-Usage: rails benchmarker 'Ruby.code' 'Ruby.more_code' ... [OPTS]
+Usage: rails profiler 'Ruby.code' 'Ruby.more_code' ... [OPTS]
-r, --runs N Number of runs.
Default: 1
-o, --output PATH Directory to use when writing the results.
diff --git a/railties/guides/source/rails_application_templates.textile b/railties/guides/source/rails_application_templates.textile
index 388d8eea3e..3db47a70e8 100644
--- a/railties/guides/source/rails_application_templates.textile
+++ b/railties/guides/source/rails_application_templates.textile
@@ -1,6 +1,6 @@
h2. Rails Application Templates
-Application templates are simple ruby files containing DSL for adding plugins/gems/initializers etc. to your freshly created Rails project or an existing Rails project.
+Application templates are simple Ruby files containing DSL for adding plugins/gems/initializers etc. to your freshly created Rails project or an existing Rails project.
By referring to this guide, you will be able to:
@@ -58,14 +58,12 @@ gem "bj"
gem "nokogiri"
</ruby>
-Please note that this will NOT install the gems for you. So you may want to run the +rake gems:install+ task too:
+Please note that this will NOT install the gems for you and you will have to run +bundle install+ to do that.
<ruby>
-rake "gems:install"
+bundle install
</ruby>
-And let Rails take care of installing the required gems if they’re not already installed.
-
h4. add_source(source, options = {})
Adds the given source to the generated application's +Gemfile+.
@@ -229,7 +227,7 @@ rake("rails:freeze:gems") if yes?("Freeze rails gems ?")
no?(question) acts just the opposite.
</ruby>
-h4. git(:must => "-a love")
+h4. git(:command)
Rails templates let you run any git command:
diff --git a/railties/lib/rails.rb b/railties/lib/rails.rb
index cca0891835..df92934457 100644
--- a/railties/lib/rails.rb
+++ b/railties/lib/rails.rb
@@ -87,6 +87,29 @@ module Rails
RAILS_CACHE
end
+ # Returns all rails groups for loading based on:
+ #
+ # * The Rails environment;
+ # * The environment variable RAILS_GROUPS;
+ # * The optional hash given as argument with group dependencies;
+ #
+ # == Examples
+ #
+ # groups :assets => [:development, :test]
+ #
+ # # Returns
+ # # => [:default, :development, :assets] for Rails.env == "development"
+ # # => [:default, :production] for Rails.env == "production"
+ #
+ def groups(hash={})
+ env = Rails.env
+ groups = [:default, env]
+ groups.concat ENV["RAILS_GROUPS"].to_s.split(",")
+ groups.concat hash.map { |k,v| k if v.map(&:to_s).include?(env) }
+ groups.compact!
+ groups
+ end
+
def version
VERSION::STRING
end
diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb
index 355b05ce0b..ea9f023511 100644
--- a/railties/lib/rails/generators.rb
+++ b/railties/lib/rails/generators.rb
@@ -299,9 +299,6 @@ module Rails
return
rescue LoadError => e
raise unless e.message =~ /#{Regexp.escape(path)}$/
- rescue NameError => e
- raise unless e.message =~ /Rails::Generator([\s(::)]|$)/
- warn "[WARNING] Could not load generator #{path.inspect} because it's a Rails 2.x generator, which is not supported anymore. Error: #{e.message}.\n#{e.backtrace.join("\n")}"
rescue Exception => e
warn "[WARNING] Could not load generator #{path.inspect}. Error: #{e.message}.\n#{e.backtrace.join("\n")}"
end
diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb
index d31a3262e3..433a56dc57 100644
--- a/railties/lib/rails/generators/actions.rb
+++ b/railties/lib/rails/generators/actions.rb
@@ -114,11 +114,11 @@ module Rails
# git :add => "this.file that.rb"
# git :add => "onefile.rb", :rm => "badfile.cxx"
#
- def git(command={})
- if command.is_a?(Symbol)
- run "git #{command}"
+ def git(commands={})
+ if commands.is_a?(Symbol)
+ run "git #{commands}"
else
- command.each do |command, options|
+ commands.each do |command, options|
run "git #{command} #{options}"
end
end
diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb
index 1196e2b7eb..378eceb4c3 100644
--- a/railties/lib/rails/generators/app_base.rb
+++ b/railties/lib/rails/generators/app_base.rb
@@ -10,7 +10,7 @@ module Rails
module Generators
class AppBase < Base
DATABASES = %w( mysql oracle postgresql sqlite3 frontbase ibm_db )
- JDBC_DATABASES = %w( jdbcmysql jdbcsqlite3 jdbcpostgresql )
+ JDBC_DATABASES = %w( jdbcmysql jdbcsqlite3 jdbcpostgresql jdbc )
DATABASES.concat(JDBC_DATABASES)
attr_accessor :rails_template
@@ -64,8 +64,8 @@ module Rails
def initialize(*args)
@original_wd = Dir.pwd
-
super
+ convert_database_option_for_jruby
end
protected
@@ -157,14 +157,26 @@ module Rails
when "postgresql" then "pg"
when "frontbase" then "ruby-frontbase"
when "mysql" then "mysql2"
- when "jdbcmysql" then "activerecord-jdbcmysql-adapter"
- when "jdbcsqlite3" then "activerecord-jdbcsqlite3-adapter"
- when "jdbcpostgresql" then "activerecord-jdbcpostgresql-adapter"
+ when "jdbcmysql" then "activerecord-jdbcmysql-adapter"
+ when "jdbcsqlite3" then "activerecord-jdbcsqlite3-adapter"
+ when "jdbcpostgresql" then "activerecord-jdbcpostgresql-adapter"
+ when "jdbc" then "activerecord-jdbc-adapter"
else options[:database]
end
end
- def gem_for_ruby_debugger
+ def convert_database_option_for_jruby
+ if defined?(JRUBY_VERSION)
+ case options[:database]
+ when "oracle" then options[:database].replace "jdbc"
+ when "postgresql" then options[:database].replace "jdbcpostgresql"
+ when "mysql" then options[:database].replace "jdbcmysql"
+ when "sqlite3" then options[:database].replace "jdbcsqlite3"
+ end
+ end
+ end
+
+ def ruby_debugger_gemfile_entry
if RUBY_VERSION < "1.9"
"gem 'ruby-debug'"
else
@@ -172,7 +184,7 @@ module Rails
end
end
- def gem_for_turn
+ def turn_gemfile_entry
unless RUBY_VERSION < "1.9.2" || options[:skip_test_unit]
<<-GEMFILE.strip_heredoc
group :test do
@@ -183,7 +195,7 @@ module Rails
end
end
- def gem_for_javascript
+ def javascript_gemfile_entry
"gem '#{options[:javascript]}-rails'" unless options[:skip_javascript]
end
diff --git a/railties/lib/rails/generators/base.rb b/railties/lib/rails/generators/base.rb
index 1f6a7a2f59..b9dc31457a 100644
--- a/railties/lib/rails/generators/base.rb
+++ b/railties/lib/rails/generators/base.rb
@@ -259,9 +259,9 @@ module Rails
extra << false unless Object.method(:const_defined?).arity == 1
# Extract the last Module in the nesting
- last = nesting.inject(Object) do |last, nest|
- break unless last.const_defined?(nest, *extra)
- last.const_get(nest)
+ last = nesting.inject(Object) do |last_module, nest|
+ break unless last_module.const_defined?(nest, *extra)
+ last_module.const_get(nest)
end
if last && last.const_defined?(last_name.camelize, *extra)
diff --git a/railties/lib/rails/generators/generated_attribute.rb b/railties/lib/rails/generators/generated_attribute.rb
index 9450894b05..f9f89c9f1d 100644
--- a/railties/lib/rails/generators/generated_attribute.rb
+++ b/railties/lib/rails/generators/generated_attribute.rb
@@ -7,7 +7,7 @@ module Rails
attr_accessor :name, :type
def initialize(name, type)
- raise Thor::Error, "Missing type for attribute '#{name}'.\nExample: '#{name}:string' where string is the type." if type.blank?
+ type = :string if type.blank?
@name, @type = name, type.to_sym
end
diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile
index ebe38bf8e6..cd674ddbdd 100644
--- a/railties/lib/rails/generators/rails/app/templates/Gemfile
+++ b/railties/lib/rails/generators/rails/app/templates/Gemfile
@@ -5,13 +5,17 @@ source 'http://rubygems.org'
<%= database_gemfile_entry -%>
<%= "gem 'jruby-openssl'\n" if defined?(JRUBY_VERSION) -%>
-# Asset template engines
<%= "gem 'json'\n" if RUBY_VERSION < "1.9.2" -%>
-gem 'sass-rails'
-gem 'coffee-script'
-gem 'uglifier'
-<%= gem_for_javascript %>
+# Gems used only for assets and not required
+# in production environments by default.
+group :assets do
+ gem 'sass-rails'
+ gem 'coffee-script'
+ gem 'uglifier'
+end
+
+<%= javascript_gemfile_entry %>
# Use unicorn as the web server
# gem 'unicorn'
@@ -20,6 +24,6 @@ gem 'uglifier'
# gem 'capistrano'
# To use debugger
-# <%= gem_for_ruby_debugger %>
+# <%= ruby_debugger_gemfile_entry %>
-<%= gem_for_turn -%>
+<%= turn_gemfile_entry -%>
diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb b/railties/lib/rails/generators/rails/app/templates/config/application.rb
index 37c2fb1263..7f623a7af9 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/application.rb
+++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb
@@ -11,9 +11,10 @@ require "active_resource/railtie"
<%= comment_if :skip_test_unit %> require "rails/test_unit/railtie"
<% end -%>
-# If you have a Gemfile, require the gems listed there, including any gems
-# you've limited to :test, :development, or :production.
-Bundler.require(:default, Rails.env) if defined?(Bundler)
+# If you have a Gemfile, require the default gems, the ones in the
+# current environment and also include :assets gems if in development
+# or test environments.
+Bundler.require *Rails.groups(:assets => %w(development test)) if defined?(Bundler)
module <%= app_const_base %>
class Application < Rails::Application
diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml
new file mode 100644
index 0000000000..1d2bf08b91
--- /dev/null
+++ b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml
@@ -0,0 +1,62 @@
+# If you are using mssql, derby, hsqldb, or h2 with one of the
+# ActiveRecord JDBC adapters, install the appropriate driver, e.g.,:
+# gem install activerecord-jdbcmssql-adapter
+#
+# Configure using Gemfile:
+# gem 'activerecord-jdbcmssql-adapter'
+#
+#development:
+# adapter: mssql
+# username: <%= app_name %>
+# password:
+# host: localhost
+# database: <%= app_name %>_development
+#
+# Warning: The database defined as "test" will be erased and
+# re-generated from your development database when you run "rake".
+# Do not set this db to the same as development or production.
+#
+#test:
+# adapter: mssql
+# username: <%= app_name %>
+# password:
+# host: localhost
+# database: <%= app_name %>_test
+#
+#production:
+# adapter: mssql
+# username: <%= app_name %>
+# password:
+# host: localhost
+# database: <%= app_name %>_production
+
+# If you are using oracle, db2, sybase, informix or prefer to use the plain
+# JDBC adapter, configure your database setting as the example below (requires
+# you to download and manually install the database vendor's JDBC driver .jar
+# file). See your driver documentation for the apropriate driver class and
+# connection string:
+
+development:
+ adapter: jdbc
+ username: <%= app_name %>
+ password:
+ driver:
+ url: jdbc:db://localhost/<%= app_name %>_development
+
+# Warning: The database defined as "test" will be erased and
+# re-generated from your development database when you run "rake".
+# Do not set this db to the same as development or production.
+
+test:
+ adapter: jdbc
+ username: <%= app_name %>
+ password:
+ driver:
+ url: jdbc:db://localhost/<%= app_name %>_test
+
+production:
+ adapter: jdbc
+ username: <%= app_name %>
+ password:
+ driver:
+ url: jdbc:db://localhost/<%= app_name %>_production
diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml
index 6bf83e86a5..5a594ac1f3 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml
+++ b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml
@@ -9,7 +9,7 @@
# And be sure to use new-style password hashing:
# http://dev.mysql.com/doc/refman/5.0/en/old-client.html
development:
- adapter: jdbcmysql
+ adapter: mysql
database: <%= app_name %>_development
username: root
password:
@@ -19,14 +19,14 @@ development:
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
- adapter: jdbcmysql
+ adapter: mysql
database: <%= app_name %>_test
username: root
password:
host: localhost
production:
- adapter: jdbcmysql
+ adapter: mysql
database: <%= app_name %>_production
username: root
password:
diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml
index 0c7f45322b..996ff4baa3 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml
+++ b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml
@@ -1,19 +1,10 @@
# PostgreSQL. Versions 7.4 and 8.x are supported.
#
-# Install the pg driver:
-# gem install pg
-# On Mac OS X with macports:
-# gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config
-# On Windows:
-# gem install pg
-# Choose the win32 build.
-# Install PostgreSQL and put its /bin directory on your path.
-#
# Configure Using Gemfile
# gem 'activerecord-jdbcpostgresql-adapter'
development:
- adapter: jdbcpostgresql
+ adapter: postgresql
encoding: unicode
database: <%= app_name %>_development
username: <%= app_name %>
@@ -38,14 +29,14 @@ development:
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
- adapter: jdbcpostgresql
+ adapter: postgresql
encoding: unicode
database: <%= app_name %>_test
username: <%= app_name %>
password:
production:
- adapter: jdbcpostgresql
+ adapter: postgresql
encoding: unicode
database: <%= app_name %>_production
username: <%= app_name %>
diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml
index 6d241d57ae..175f3eb3db 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml
+++ b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml
@@ -5,16 +5,16 @@
# gem 'activerecord-jdbcsqlite3-adapter'
#
development:
- adapter: jdbcsqlite3
+ adapter: sqlite3
database: db/development.sqlite3
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
- adapter: jdbcsqlite3
+ adapter: sqlite3
database: db/test.sqlite3
production:
- adapter: jdbcsqlite3
+ adapter: sqlite3
database: db/production.sqlite3
diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile b/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile
index c28e568711..7e6eb18341 100644
--- a/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile
+++ b/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile
@@ -7,9 +7,8 @@ source "http://rubygems.org"
<% end -%>
<% if mountable? -%>
-<%= gem_for_javascript -%>
+<%= javascript_gemfile_entry -%>
<% end -%>
-if RUBY_VERSION < '1.9'
- gem "ruby-debug", ">= 0.10.3"
-end
+# To use debugger
+# <%= ruby_debugger_gemfile_entry %> \ No newline at end of file
diff --git a/railties/lib/rails/railtie.rb b/railties/lib/rails/railtie.rb
index 0c641254cf..8c88b25617 100644
--- a/railties/lib/rails/railtie.rb
+++ b/railties/lib/rails/railtie.rb
@@ -84,7 +84,7 @@ module Rails
# == Loading rake tasks and generators
#
# If your railtie has rake tasks, you can tell Rails to load them through the method
- # rake tasks:
+ # rake_tasks:
#
# class MyRailtie < Rails::Railtie
# rake_tasks do
diff --git a/railties/lib/rails/tasks/assets.rake b/railties/lib/rails/tasks/assets.rake
index 4678ea460e..0236350576 100644
--- a/railties/lib/rails/tasks/assets.rake
+++ b/railties/lib/rails/tasks/assets.rake
@@ -1,21 +1,26 @@
namespace :assets do
desc "Compile all the assets named in config.assets.precompile"
- task :precompile => :environment do
- # Give assets access to asset_path
- Sprockets::Helpers::RailsHelper
+ task :precompile do
+ if ENV["RAILS_GROUPS"].to_s.empty?
+ ENV["RAILS_GROUPS"] = "assets"
+ Kernel.exec $0, *ARGV
+ else
+ Rake::Task["environment"].invoke
+ Sprockets::Helpers::RailsHelper
- assets = Rails.application.config.assets.precompile
- Rails.application.assets.precompile(*assets)
+ assets = Rails.application.config.assets.precompile
+ Rails.application.assets.precompile(*assets)
+ end
end
desc "Remove compiled assets"
task :clean => :environment do
assets = Rails.application.config.assets
public_asset_path = Rails.public_path + assets.prefix
- file_list = FileList.new("#{public_asset_path}/*.js", "#{public_asset_path}/*.css")
+ file_list = FileList.new("#{public_asset_path}/**/*")
file_list.each do |file|
- rm file
- rm "#{file}.gz", :force => true
+ rm_rf file
+ rm_rf "#{file}.gz"
end
end
end
diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb
index 2b593005a2..b76dae8e18 100644
--- a/railties/test/application/assets_test.rb
+++ b/railties/test/application/assets_test.rb
@@ -1,8 +1,9 @@
require 'isolation/abstract_unit'
+require 'active_support/core_ext/kernel/reporting'
require 'rack/test'
module ApplicationTests
- class RoutingTest < Test::Unit::TestCase
+ class AssetsTest < Test::Unit::TestCase
include ActiveSupport::Testing::Isolation
include Rack::Test::Methods
@@ -34,6 +35,31 @@ module ApplicationTests
assert_match "alert()", last_response.body
end
+ test "assets are compiled properly" do
+ app_file "app/assets/javascripts/application.js", "alert();"
+
+ capture(:stdout) do
+ Dir.chdir(app_path){ `bundle exec rake assets:precompile` }
+ end
+
+ file = Dir["#{app_path}/public/assets/application-*.js"][0]
+ assert_not_nil file, "Expected application.js asset to be generated, but none found"
+ assert_equal "alert();\n", File.read(file)
+ end
+
+ test "assets are cleaned up properly" do
+ app_file "public/assets/application.js", "alert();"
+ app_file "public/assets/application.css", "a { color: green; }"
+ app_file "public/assets/subdir/broken.png", "not really an image file"
+
+ capture(:stdout) do
+ Dir.chdir(app_path){ `bundle exec rake assets:clean` }
+ end
+
+ files = Dir["#{app_path}/public/assets/**/*"]
+ assert_equal 0, files.length, "Expected no assets, but found #{files.join(', ')}"
+ end
+
test "does not stream session cookies back" do
app_file "app/assets/javascripts/demo.js.erb", "<%= :alert %>();"
diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb
index 477dada820..2547863d12 100644
--- a/railties/test/application/configuration_test.rb
+++ b/railties/test/application/configuration_test.rb
@@ -39,6 +39,21 @@ module ApplicationTests
FileUtils.rm_rf(new_app) if File.directory?(new_app)
end
+ test "Rails.groups returns available groups" do
+ require "rails"
+
+ Rails.env = "development"
+ assert_equal [:default, "development"], Rails.groups
+ assert_equal [:default, "development", :assets], Rails.groups(:assets => [:development])
+ assert_equal [:default, "development", :assets], Rails.groups(:assets => %w(development))
+
+ Rails.env = "test"
+ assert_equal [:default, "test"], Rails.groups(:assets => [:development])
+
+ ENV["RAILS_GROUPS"] = "javascripts,stylesheets"
+ assert_equal [:default, "test", "javascripts", "stylesheets"], Rails.groups
+ end
+
test "Rails.application is nil until app is initialized" do
require 'rails'
assert_nil Rails.application
diff --git a/railties/test/fixtures/lib/generators/wrong_generator.rb b/railties/test/fixtures/lib/generators/wrong_generator.rb
deleted file mode 100644
index 6aa7cb052e..0000000000
--- a/railties/test/fixtures/lib/generators/wrong_generator.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-# Old generator version
-class WrongGenerator < Rails::Generator::NamedBase
-end
diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb
index c31c65a27d..03d185165f 100644
--- a/railties/test/generators/app_generator_test.rb
+++ b/railties/test/generators/app_generator_test.rb
@@ -134,7 +134,7 @@ class AppGeneratorTest < Rails::Generators::TestCase
def test_config_jdbcmysql_database
run_generator([destination_root, "-d", "jdbcmysql"])
- assert_file "config/database.yml", /jdbcmysql/
+ assert_file "config/database.yml", /mysql/
assert_file "Gemfile", /^gem\s+["']activerecord-jdbcmysql-adapter["']$/
# TODO: When the JRuby guys merge jruby-openssl in
# jruby this will be removed
@@ -143,16 +143,31 @@ class AppGeneratorTest < Rails::Generators::TestCase
def test_config_jdbcsqlite3_database
run_generator([destination_root, "-d", "jdbcsqlite3"])
- assert_file "config/database.yml", /jdbcsqlite3/
+ assert_file "config/database.yml", /sqlite3/
assert_file "Gemfile", /^gem\s+["']activerecord-jdbcsqlite3-adapter["']$/
end
def test_config_jdbcpostgresql_database
run_generator([destination_root, "-d", "jdbcpostgresql"])
- assert_file "config/database.yml", /jdbcpostgresql/
+ assert_file "config/database.yml", /postgresql/
assert_file "Gemfile", /^gem\s+["']activerecord-jdbcpostgresql-adapter["']$/
end
+ def test_config_jdbc_database
+ run_generator([destination_root, "-d", "jdbc"])
+ assert_file "config/database.yml", /jdbc/
+ assert_file "config/database.yml", /mssql/
+ assert_file "Gemfile", /^gem\s+["']activerecord-jdbc-adapter["']$/
+ end
+
+ def test_config_jdbc_database_when_no_option_given
+ if defined?(JRUBY_VERSION)
+ run_generator([destination_root])
+ assert_file "config/database.yml", /sqlite3/
+ assert_file "Gemfile", /^gem\s+["']activerecord-jdbcsqlite3-adapter["']$/
+ end
+ end
+
def test_generator_if_skip_active_record_is_given
run_generator [destination_root, "--skip-active-record"]
assert_no_file "config/database.yml"
diff --git a/railties/test/generators/generated_attribute_test.rb b/railties/test/generators/generated_attribute_test.rb
index 0d2e624f44..c9f8ab0a7b 100644
--- a/railties/test/generators/generated_attribute_test.rb
+++ b/railties/test/generators/generated_attribute_test.rb
@@ -113,15 +113,8 @@ class GeneratedAttributeTest < Rails::Generators::TestCase
end
end
- def test_nil_type_raises_exception
- assert_raise Thor::Error do
- create_generated_attribute(nil, 'title')
- end
- end
-
- def test_missing_type_raises_exception
- assert_raise Thor::Error do
- create_generated_attribute('', 'title')
- end
+ def test_blank_type_defaults_to_string_raises_exception
+ assert_equal :string, create_generated_attribute(nil, 'title').type
+ assert_equal :string, create_generated_attribute("", 'title').type
end
end
diff --git a/railties/test/generators/model_generator_test.rb b/railties/test/generators/model_generator_test.rb
index 8c5ba9926b..1b0cb425c6 100644
--- a/railties/test/generators/model_generator_test.rb
+++ b/railties/test/generators/model_generator_test.rb
@@ -12,9 +12,15 @@ class ModelGeneratorTest < Rails::Generators::TestCase
end
def test_model_with_missing_attribute_type
- content = capture(:stderr) { run_generator ["post", "title:string", "body"] }
- assert_match(/Missing type for attribute 'body'/, content)
- assert_match(/Example: 'body:string' where string is the type/, content)
+ run_generator ["post", "title", "body:text", "author"]
+
+ assert_migration "db/migrate/create_posts.rb" do |m|
+ assert_method :change, m do |up|
+ assert_match(/t\.string :title/, up)
+ assert_match(/t\.text :body/, up)
+ assert_match(/t\.string :author/, up)
+ end
+ end
end
def test_invokes_default_orm
diff --git a/railties/test/generators/scaffold_generator_test.rb b/railties/test/generators/scaffold_generator_test.rb
index 2135ffac81..c3c6015291 100644
--- a/railties/test/generators/scaffold_generator_test.rb
+++ b/railties/test/generators/scaffold_generator_test.rb
@@ -272,8 +272,14 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
end
def test_scaffold_generator_outputs_error_message_on_missing_attribute_type
- content = capture(:stderr) { run_generator ["post", "title:string", "body"]}
- assert_match(/Missing type for attribute 'body'/, content)
- assert_match(/Example: 'body:string' where string is the type/, content)
+ run_generator ["post", "title", "body:text", "author"]
+
+ assert_migration "db/migrate/create_posts.rb" do |m|
+ assert_method :change, m do |up|
+ assert_match(/t\.string :title/, up)
+ assert_match(/t\.text :body/, up)
+ assert_match(/t\.string :author/, up)
+ end
+ end
end
end
diff --git a/railties/test/generators_test.rb b/railties/test/generators_test.rb
index 301ae80bcf..56329f3183 100644
--- a/railties/test/generators_test.rb
+++ b/railties/test/generators_test.rb
@@ -88,12 +88,6 @@ class GeneratorsTest < Rails::Generators::TestCase
assert Rails::Generators.find_by_namespace(:model)
end
- def test_find_by_namespace_show_warning_if_generator_cant_be_loaded
- output = capture(:stderr) { Rails::Generators.find_by_namespace(:wrong) }
- assert_match(/\[WARNING\] Could not load generator/, output)
- assert_match(/Rails 2\.x generator/, output)
- end
-
def test_invoke_with_nested_namespaces
model_generator = mock('ModelGenerator') do
expects(:start).with(["Account"], {})
diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb
index 0a203fd4d0..685d1b154b 100644
--- a/railties/test/isolation/abstract_unit.rb
+++ b/railties/test/isolation/abstract_unit.rb
@@ -238,6 +238,10 @@ module TestHelpers
end
end
+ def remove_file(path)
+ FileUtils.rm_rf "#{app_path}/#{path}"
+ end
+
def controller(name, contents)
app_file("app/controllers/#{name}_controller.rb", contents)
end