aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/CHANGELOG.md16
-rw-r--r--actionpack/lib/action_dispatch/journey/route.rb4
-rw-r--r--actionpack/lib/action_dispatch/journey/visitors.rb8
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb10
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb10
-rw-r--r--actionpack/lib/action_view/helpers/capture_helper.rb2
-rw-r--r--actionpack/test/dispatch/routing_test.rb30
-rw-r--r--actionpack/test/template/capture_helper_test.rb4
-rw-r--r--activerecord/CHANGELOG.md44
-rw-r--r--activerecord/lib/active_record/associations/collection_proxy.rb13
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/quoting.rb10
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb12
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/connection_specification.rb4
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid.rb5
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb18
-rw-r--r--activerecord/lib/active_record/railtie.rb2
-rw-r--r--activerecord/lib/active_record/railties/databases.rake2
-rw-r--r--activerecord/lib/active_record/relation/predicate_builder.rb5
-rw-r--r--activerecord/lib/rails/generators/active_record/migration/migration_generator.rb11
-rw-r--r--activerecord/lib/rails/generators/active_record/migration/templates/create_table_migration.rb (renamed from activerecord/lib/rails/generators/active_record/model/templates/migration.rb)0
-rw-r--r--activerecord/lib/rails/generators/active_record/model/model_generator.rb2
-rw-r--r--activerecord/test/cases/adapters/postgresql/datatype_test.rb2
-rw-r--r--activerecord/test/cases/adapters/postgresql/hstore_test.rb15
-rw-r--r--activerecord/test/cases/adapters/postgresql/json_test.rb15
-rw-r--r--activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb6
-rw-r--r--activerecord/test/cases/associations_test.rb14
-rw-r--r--activerecord/test/cases/quoting_test.rb14
-rw-r--r--activerecord/test/cases/relation/where_test.rb25
-rw-r--r--activerecord/test/cases/relation_scoping_test.rb6
-rw-r--r--activerecord/test/schema/schema.rb2
-rw-r--r--activesupport/activesupport.gemspec2
-rw-r--r--guides/CHANGELOG.md2
-rw-r--r--guides/code/getting_started/public/404.html53
-rw-r--r--guides/code/getting_started/public/422.html53
-rw-r--r--guides/code/getting_started/public/500.html53
-rw-r--r--guides/source/action_controller_overview.md118
-rw-r--r--guides/source/migrations.md21
-rw-r--r--guides/source/upgrading_ruby_on_rails.md69
-rw-r--r--railties/CHANGELOG.md1
-rw-r--r--railties/lib/rails/application.rb58
-rw-r--r--railties/lib/rails/application/configuration.rb16
-rw-r--r--railties/lib/rails/generators/erb/scaffold/templates/show.html.erb1
-rw-r--r--railties/lib/rails/generators/rails/app/templates/public/404.html53
-rw-r--r--railties/lib/rails/generators/rails/app/templates/public/422.html53
-rw-r--r--railties/lib/rails/generators/rails/app/templates/public/500.html53
-rw-r--r--railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb12
-rw-r--r--railties/lib/rails/generators/rails/plugin_new/templates/%name%.gemspec3
-rw-r--r--railties/lib/rails/generators/rails/plugin_new/templates/Gemfile8
-rw-r--r--railties/lib/rails/generators/rails/plugin_new/templates/rails/javascripts.js13
-rw-r--r--railties/lib/rails/generators/rails/plugin_new/templates/rails/stylesheets.css13
-rw-r--r--railties/test/application/middleware_test.rb6
-rw-r--r--railties/test/application/rake/dbs_test.rb13
-rw-r--r--railties/test/generators/migration_generator_test.rb17
-rw-r--r--railties/test/generators/plugin_new_generator_test.rb55
56 files changed, 807 insertions, 258 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 2a9afed35b..3fc3e06160 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,5 +1,21 @@
## Rails 4.0.0 (unreleased) ##
+* Fixed `ActionView::Helpers::CaptureHelper#content_for` regression when trying to use it in
+ a boolean statement.
+ Fixes #9360.
+
+ *Nikolay Shebanov*
+
+* `format: true` does not override existing format constraints.
+ Fixes #9466.
+
+ Example:
+
+ # This will force the .json extension.
+ get '/json_only', to: ok, format: true, constraints: { format: /json/ }
+
+ *Yves Senn*
+
* Skip valid encoding checks for non-String parameters that come
from the matched route's defaults.
Fixes #9435.
diff --git a/actionpack/lib/action_dispatch/journey/route.rb b/actionpack/lib/action_dispatch/journey/route.rb
index 063302e0f2..6fda085681 100644
--- a/actionpack/lib/action_dispatch/journey/route.rb
+++ b/actionpack/lib/action_dispatch/journey/route.rb
@@ -71,6 +71,10 @@ module ActionDispatch
Visitors::Formatter.new(path_options).accept(path.spec)
end
+ def optimized_path
+ Visitors::OptimizedPath.new.accept(path.spec)
+ end
+
def optional_parts
path.optional_names.map { |n| n.to_sym }
end
diff --git a/actionpack/lib/action_dispatch/journey/visitors.rb b/actionpack/lib/action_dispatch/journey/visitors.rb
index 46bd58c178..2964d80d9f 100644
--- a/actionpack/lib/action_dispatch/journey/visitors.rb
+++ b/actionpack/lib/action_dispatch/journey/visitors.rb
@@ -74,6 +74,14 @@ module ActionDispatch
end
end
+ class OptimizedPath < String # :nodoc:
+ private
+
+ def visit_GROUP(node)
+ ""
+ end
+ end
+
# Used for formatting urls (url_for)
class Formatter < Visitor # :nodoc:
attr_reader :options, :consumed
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index dba9ccbfa5..4fbe156a72 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -113,14 +113,6 @@ module ActionDispatch
@options.merge!(default_controller_and_action)
end
- def normalize_format!
- if options[:format] == true
- options[:format] = /.+/
- elsif options[:format] == false
- options.delete(:format)
- end
- end
-
def normalize_requirements!
constraints.each do |key, requirement|
next unless segment_keys.include?(key) || key == :controller
@@ -129,7 +121,7 @@ module ActionDispatch
end
if options[:format] == true
- @requirements[:format] = /.+/
+ @requirements[:format] ||= /.+/
elsif Regexp === options[:format]
@requirements[:format] = options[:format]
elsif String === options[:format]
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index ca31b5e02e..619dd22ec1 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -165,7 +165,7 @@ module ActionDispatch
super
@path_parts = @route.required_parts
@arg_size = @path_parts.size
- @string_route = string_route(route)
+ @string_route = @route.optimized_path
end
def call(t, args)
@@ -180,14 +180,6 @@ module ActionDispatch
private
- def string_route(route)
- string_route = route.ast.to_s.dup
- while string_route.gsub!(/\([^\)]*\)/, "")
- true
- end
- string_route
- end
-
def optimized_helper(args)
path = @string_route.dup
klass = Journey::Router::Utils
diff --git a/actionpack/lib/action_view/helpers/capture_helper.rb b/actionpack/lib/action_view/helpers/capture_helper.rb
index 4ec860d69a..1bad82159a 100644
--- a/actionpack/lib/action_view/helpers/capture_helper.rb
+++ b/actionpack/lib/action_view/helpers/capture_helper.rb
@@ -156,7 +156,7 @@ module ActionView
end
nil
else
- @view_flow.get(name)
+ @view_flow.get(name).presence
end
end
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index 4775324b43..2bf7056ff7 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -3198,6 +3198,7 @@ class TestOptimizedNamedRoutes < ActionDispatch::IntegrationTest
app.draw do
ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] }
get '/foo' => ok, as: :foo
+ get '/post(/:action(/:id))' => ok, as: :posts
end
end
@@ -3215,6 +3216,11 @@ class TestOptimizedNamedRoutes < ActionDispatch::IntegrationTest
test 'named route called on included module' do
assert_equal '/foo', foo_path
end
+
+ test 'nested optional segments are removed' do
+ assert_equal '/post', Routes.url_helpers.posts_path
+ assert_equal '/post', posts_path
+ end
end
class TestNamedRouteUrlHelpers < ActionDispatch::IntegrationTest
@@ -3407,6 +3413,8 @@ class TestFormatConstraints < ActionDispatch::IntegrationTest
get '/string', to: ok, constraints: { format: 'json' }
get '/regexp', to: ok, constraints: { format: /json/ }
+ get '/json_only', to: ok, format: true, constraints: { format: /json/ }
+ get '/xml_only', to: ok, format: 'xml'
end
end
@@ -3434,6 +3442,28 @@ class TestFormatConstraints < ActionDispatch::IntegrationTest
get 'http://www.example.com/regexp.html'
assert_response :not_found
end
+
+ def test_enforce_with_format_true_with_constraint
+ get 'http://www.example.com/json_only.json'
+ assert_response :success
+
+ get 'http://www.example.com/json_only.html'
+ assert_response :not_found
+
+ get 'http://www.example.com/json_only'
+ assert_response :not_found
+ end
+
+ def test_enforce_with_string
+ get 'http://www.example.com/xml_only.xml'
+ assert_response :success
+
+ get 'http://www.example.com/xml_only'
+ assert_response :success
+
+ get 'http://www.example.com/xml_only.json'
+ assert_response :not_found
+ end
end
class TestRouteDefaults < ActionDispatch::IntegrationTest
diff --git a/actionpack/test/template/capture_helper_test.rb b/actionpack/test/template/capture_helper_test.rb
index 234ac3252d..938f1c3e54 100644
--- a/actionpack/test/template/capture_helper_test.rb
+++ b/actionpack/test/template/capture_helper_test.rb
@@ -137,6 +137,10 @@ class CaptureHelperTest < ActionView::TestCase
assert_equal 'bar', content_for(:title)
end
+ def test_content_for_returns_nil_when_content_missing
+ assert_equal nil, content_for(:some_missing_key)
+ end
+
def test_content_for_question_mark
assert ! content_for?(:title)
content_for :title, 'title'
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 4a5a2d17af..2eaf388095 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,5 +1,48 @@
## Rails 4.0.0 (unreleased) ##
+* Postgresql timestamp with time zone (timestamptz) datatype now returns a
+ ActiveSupport::TimeWithZone instance instead of a string
+
+ *Troy Kruthoff*
+
+* The `#append` method for collection associations behaves like`<<`.
+ `#prepend` is not defined and `<<` or `#append` should be used.
+ Fixes #7364.
+
+ *Yves Senn*
+
+* Added support for creating a table via Rails migration generator.
+ For example,
+
+ rails g migration create_books title:string content:text
+
+ will generate a migration that creates a table called books with
+ the listed attributes, without creating a model.
+
+ *Sammy Larbi*
+
+* Fix bug that raises the wrong exception when the exception handled by PostgreSQL adapter
+ doesn't respond to `#result`.
+ Fixes #8617.
+
+ *kennyj*
+
+* Support PostgreSQL specific column types when using `change_table`.
+ Fixes #9480.
+
+ Example:
+
+ change_table :authors do |t|
+ t.hstore :books
+ t.json :metadata
+ end
+
+ *Yves Senn*
+
+* Revert 408227d9c5ed7d, 'quote numeric'. This introduced some regressions.
+
+ *Steve Klabnik*
+
* Fix calculation of `db_runtime` property in
`ActiveRecord::Railties::ControllerRuntime#cleanup_view_runtime`.
Previously, after raising `ActionView::MissingTemplate`, `db_runtime` was
@@ -1527,4 +1570,5 @@
*Aaron Patterson*
+
Please check [3-2-stable](https://github.com/rails/rails/blob/3-2-stable/activerecord/CHANGELOG.md) for previous changes.
diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb
index e93e700c93..543204abac 100644
--- a/activerecord/lib/active_record/associations/collection_proxy.rb
+++ b/activerecord/lib/active_record/associations/collection_proxy.rb
@@ -83,9 +83,9 @@ module ActiveRecord
# # #<Pet id: 3, name: "Choo-Choo">
# # ]
#
- # Be careful because this also means you’re initializing a model
- # object with only the fields that you’ve selected. If you attempt
- # to access a field that is not in the initialized record you’ll
+ # Be careful because this also means you're initializing a model
+ # object with only the fields that you've selected. If you attempt
+ # to access a field that is not in the initialized record you'll
# receive:
#
# person.pets.select(:name).first.person_id
@@ -924,7 +924,7 @@ module ActiveRecord
alias_method :to_a, :to_ary
# Adds one or more +records+ to the collection by setting their foreign keys
- # to the association‘s primary key. Returns +self+, so several appends may be
+ # to the association's primary key. Returns +self+, so several appends may be
# chained together.
#
# class Person < ActiveRecord::Base
@@ -947,6 +947,11 @@ module ActiveRecord
proxy_association.concat(records) && self
end
alias_method :push, :<<
+ alias_method :append, :<<
+
+ def prepend(*args)
+ raise NoMethodError, "prepend on association is not defined. Please use << or append"
+ end
# Equivalent to +delete_all+. The difference is that returns +self+, instead
# of an array with the deleted objects, so methods can be chained. See
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
index aec4654eee..d18b9c991f 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
@@ -25,19 +25,13 @@ module ActiveRecord
when true, false
if column && column.type == :integer
value ? '1' : '0'
- elsif column && [:text, :string, :binary].include?(column.type)
- value ? "'1'" : "'0'"
else
value ? quoted_true : quoted_false
end
# BigDecimals need to be put in a non-normalized form and quoted.
when nil then "NULL"
- when Numeric, ActiveSupport::Duration
- value = BigDecimal === value ? value.to_s('F') : value.to_s
- if column && ![:integer, :float, :decimal].include?(column.type)
- value = "'#{value}'"
- end
- value
+ when BigDecimal then value.to_s('F')
+ when Numeric, ActiveSupport::Duration then value.to_s
when Date, Time then "'#{quoted_date(value)}'"
when Symbol then "'#{quote_string(value.to_s)}'"
when Class then "'#{value.to_s}'"
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 f758e19a4f..42206de8fc 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
@@ -44,8 +44,8 @@ module ActiveRecord
# Represents the schema of an SQL table in an abstract way. This class
# provides methods for manipulating the schema representation.
#
- # Inside migration files, the +t+ object in +create_table+ and
- # +change_table+ is actually of this type:
+ # Inside migration files, the +t+ object in +create_table+
+ # is actually of this type:
#
# class SomeMigration < ActiveRecord::Migration
# def up
@@ -489,7 +489,7 @@ module ActiveRecord
args.each do |name|
@base.add_column(@table_name, name, column_type, options)
end
- end
+ end
end
private
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 9bae880024..0cce8c7596 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
@@ -156,7 +156,7 @@ module ActiveRecord
#
# See also TableDefinition#column for details on how to create columns.
def create_table(table_name, options = {})
- td = table_definition
+ td = create_table_definition
td.primary_key(options[:primary_key] || Base.get_primary_key(table_name.to_s.singularize)) unless options[:id] == false
yield td if block_given?
@@ -298,10 +298,10 @@ module ActiveRecord
def change_table(table_name, options = {})
if supports_bulk_alter? && options[:bulk]
recorder = ActiveRecord::Migration::CommandRecorder.new(self)
- yield Table.new(table_name, recorder)
+ yield update_table_definition(table_name, recorder)
bulk_change_table(table_name, recorder.commands)
else
- yield Table.new(table_name, self)
+ yield update_table_definition(table_name, self)
end
end
@@ -727,9 +727,13 @@ module ActiveRecord
end
private
- def table_definition
+ def create_table_definition
TableDefinition.new(self)
end
+
+ def update_table_definition(table_name, base)
+ Table.new(table_name, base)
+ end
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
index 5480204511..9826b18053 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
@@ -212,6 +212,8 @@ module ActiveRecord
if value.kind_of?(String) && column && column.type == :binary && column.class.respond_to?(:string_to_binary)
s = column.class.string_to_binary(value).unpack("H*")[0]
"x'#{s}'"
+ elsif value.kind_of?(BigDecimal)
+ value.to_s("F")
else
super
end
diff --git a/activerecord/lib/active_record/connection_adapters/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/connection_specification.rb
index 2c683fc3ac..8bad7d0cf5 100644
--- a/activerecord/lib/active_record/connection_adapters/connection_specification.rb
+++ b/activerecord/lib/active_record/connection_adapters/connection_specification.rb
@@ -38,7 +38,7 @@ module ActiveRecord
private
def resolve_string_connection(spec) # :nodoc:
hash = configurations.fetch(spec) do |k|
- self.class.connection_url_to_hash(k)
+ connection_url_to_hash(k)
end
raise(AdapterNotSpecified, "#{spec} database is not configured") unless hash
@@ -65,7 +65,7 @@ module ActiveRecord
ConnectionSpecification.new(spec, adapter_method)
end
- def self.connection_url_to_hash(url) # :nodoc:
+ def connection_url_to_hash(url) # :nodoc:
config = URI.parse url
adapter = config.scheme
adapter = "postgresql" if adapter == "postgres"
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
index e09319890a..68f2f2ca7b 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
@@ -317,10 +317,6 @@ module ActiveRecord
alias_type 'macaddr', 'text'
alias_type 'uuid', 'text'
- # FIXME: I don't think this is correct. We should probably be returning a parsed date,
- # but the tests pass with a string returned.
- register_type 'timestamptz', OID::Identity.new
-
register_type 'money', OID::Money.new
register_type 'bytea', OID::Bytea.new
register_type 'bool', OID::Boolean.new
@@ -329,6 +325,7 @@ module ActiveRecord
alias_type 'float8', 'float4'
register_type 'timestamp', OID::Timestamp.new
+ register_type 'timestamptz', OID::Timestamp.new
register_type 'date', OID::Date.new
register_type 'time', OID::Time.new
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index 2bb2557efd..c91e1b3fb9 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -263,7 +263,7 @@ module ActiveRecord
attr_accessor :array
end
- class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
+ module ColumnMethods
def xml(*args)
options = args.extract_options!
column(args[0], 'xml', options)
@@ -325,6 +325,10 @@ module ActiveRecord
def json(name, options = {})
column(name, 'json', options)
end
+ end
+
+ class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
+ include ColumnMethods
def column(name, type = nil, options = {})
super
@@ -344,6 +348,10 @@ module ActiveRecord
end
end
+ class Table < ActiveRecord::ConnectionAdapters::Table
+ include ColumnMethods
+ end
+
ADAPTER_NAME = 'PostgreSQL'
NATIVE_DATABASE_TYPES = {
@@ -667,6 +675,8 @@ module ActiveRecord
UNIQUE_VIOLATION = "23505"
def translate_exception(exception, message)
+ return exception unless exception.respond_to?(:result)
+
case exception.result.try(:error_field, PGresult::PG_DIAG_SQLSTATE)
when UNIQUE_VIOLATION
RecordNotUnique.new(message, exception)
@@ -884,9 +894,13 @@ module ActiveRecord
$1.strip if $1
end
- def table_definition
+ def create_table_definition
TableDefinition.new(self)
end
+
+ def update_table_definition(table_name, base)
+ Table.new(table_name, base)
+ end
end
end
end
diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb
index 64eac3aca7..13f3bf7085 100644
--- a/activerecord/lib/active_record/railtie.rb
+++ b/activerecord/lib/active_record/railtie.rb
@@ -152,7 +152,7 @@ module ActiveRecord
# and then establishes the connection.
initializer "active_record.initialize_database" do |app|
ActiveSupport.on_load(:active_record) do
- self.configurations = app.config.database_configuration
+ self.configurations = app.config.database_configuration || {}
establish_connection
end
end
diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake
index f36af7182f..d92e268109 100644
--- a/activerecord/lib/active_record/railties/databases.rake
+++ b/activerecord/lib/active_record/railties/databases.rake
@@ -2,7 +2,7 @@ require 'active_record'
db_namespace = namespace :db do
task :load_config do
- ActiveRecord::Base.configurations = Rails.application.config.database_configuration
+ ActiveRecord::Base.configurations = Rails.application.config.database_configuration || {}
ActiveRecord::Migrator.migrations_paths = Rails.application.paths['db/migrate'].to_a
if defined?(ENGINE_PATH) && engine = Rails::Engine.find(ENGINE_PATH)
diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb b/activerecord/lib/active_record/relation/predicate_builder.rb
index 5cd015eba7..bd783a94cf 100644
--- a/activerecord/lib/active_record/relation/predicate_builder.rb
+++ b/activerecord/lib/active_record/relation/predicate_builder.rb
@@ -98,11 +98,6 @@ module ActiveRecord
when Class
# FIXME: I think we need to deprecate this behavior
attribute.eq(value.name)
- when Integer, ActiveSupport::Duration
- # Arel treats integers as literals, but they should be quoted when compared with strings
- table = attribute.relation
- column = table.engine.connection.schema_cache.columns_hash(table.name)[attribute.name.to_s]
- attribute.eq(Arel::Nodes::SqlLiteral.new(table.engine.connection.quote(value, column)))
else
attribute.eq(value)
end
diff --git a/activerecord/lib/rails/generators/active_record/migration/migration_generator.rb b/activerecord/lib/rails/generators/active_record/migration/migration_generator.rb
index 5f1dbe36d6..b967bb6e0f 100644
--- a/activerecord/lib/rails/generators/active_record/migration/migration_generator.rb
+++ b/activerecord/lib/rails/generators/active_record/migration/migration_generator.rb
@@ -8,13 +8,14 @@ module ActiveRecord
def create_migration_file
set_local_assigns!
validate_file_name!
- migration_template "migration.rb", "db/migrate/#{file_name}.rb"
+ migration_template @migration_template, "db/migrate/#{file_name}.rb"
end
protected
attr_reader :migration_action, :join_tables
def set_local_assigns!
+ @migration_template = "migration.rb"
case file_name
when /^(add|remove)_.*_(?:to|from)_(.*)/
@migration_action = $1
@@ -26,6 +27,9 @@ module ActiveRecord
set_index_names
end
+ when /^create_(.+)/
+ @table_name = $1.pluralize
+ @migration_template = "create_table_migration.rb"
end
end
@@ -44,7 +48,10 @@ module ActiveRecord
end
private
-
+ def attributes_with_index
+ attributes.select { |a| !a.reference? && a.has_index? }
+ end
+
def validate_file_name!
unless file_name =~ /^[_a-z0-9]+$/
raise IllegalMigrationNameError.new(file_name)
diff --git a/activerecord/lib/rails/generators/active_record/model/templates/migration.rb b/activerecord/lib/rails/generators/active_record/migration/templates/create_table_migration.rb
index 3a3cf86d73..3a3cf86d73 100644
--- a/activerecord/lib/rails/generators/active_record/model/templates/migration.rb
+++ b/activerecord/lib/rails/generators/active_record/migration/templates/create_table_migration.rb
diff --git a/activerecord/lib/rails/generators/active_record/model/model_generator.rb b/activerecord/lib/rails/generators/active_record/model/model_generator.rb
index 5f36181694..40e134e626 100644
--- a/activerecord/lib/rails/generators/active_record/model/model_generator.rb
+++ b/activerecord/lib/rails/generators/active_record/model/model_generator.rb
@@ -15,7 +15,7 @@ module ActiveRecord
def create_migration_file
return unless options[:migration] && options[:parent].nil?
attributes.each { |a| a.attr_options.delete(:index) if a.reference? && !a.has_index? } if options[:indexes] == false
- migration_template "migration.rb", "db/migrate/create_#{table_name}.rb"
+ migration_template "../../migration/templates/create_table_migration.rb", "db/migrate/create_#{table_name}.rb"
end
def create_model_file
diff --git a/activerecord/test/cases/adapters/postgresql/datatype_test.rb b/activerecord/test/cases/adapters/postgresql/datatype_test.rb
index 33c796191e..1e6ae85a25 100644
--- a/activerecord/test/cases/adapters/postgresql/datatype_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/datatype_test.rb
@@ -573,6 +573,7 @@ _SQL
@first_timestamp_with_zone = PostgresqlTimestampWithZone.find(1)
assert_equal Time.utc(2010,1,1, 11,0,0), @first_timestamp_with_zone.time
+ assert_instance_of Time, @first_timestamp_with_zone.time
ensure
ActiveRecord::Base.default_timezone = old_default_tz
ActiveRecord::Base.time_zone_aware_attributes = old_tz
@@ -590,6 +591,7 @@ _SQL
@first_timestamp_with_zone = PostgresqlTimestampWithZone.find(1)
assert_equal Time.utc(2010,1,1, 11,0,0), @first_timestamp_with_zone.time
+ assert_instance_of Time, @first_timestamp_with_zone.time
ensure
ActiveRecord::Base.default_timezone = old_default_tz
ActiveRecord::Base.time_zone_aware_attributes = old_tz
diff --git a/activerecord/test/cases/adapters/postgresql/hstore_test.rb b/activerecord/test/cases/adapters/postgresql/hstore_test.rb
index 6640f9b497..ad98d7c8ce 100644
--- a/activerecord/test/cases/adapters/postgresql/hstore_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/hstore_test.rb
@@ -65,6 +65,21 @@ class PostgresqlHstoreTest < ActiveRecord::TestCase
assert_equal :hstore, @column.type
end
+ def test_change_table_supports_hstore
+ @connection.transaction do
+ @connection.change_table('hstores') do |t|
+ t.hstore 'users', default: ''
+ end
+ Hstore.reset_column_information
+ column = Hstore.columns.find { |c| c.name == 'users' }
+ assert_equal :hstore, column.type
+
+ raise ActiveRecord::Rollback # reset the schema change
+ end
+ ensure
+ Hstore.reset_column_information
+ end
+
def test_type_cast_hstore
assert @column
diff --git a/activerecord/test/cases/adapters/postgresql/json_test.rb b/activerecord/test/cases/adapters/postgresql/json_test.rb
index d64037eec0..6fc08ae4f0 100644
--- a/activerecord/test/cases/adapters/postgresql/json_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/json_test.rb
@@ -31,6 +31,21 @@ class PostgresqlJSONTest < ActiveRecord::TestCase
assert_equal :json, @column.type
end
+ def test_change_table_supports_json
+ @connection.transaction do
+ @connection.change_table('json_data_type') do |t|
+ t.json 'users', default: '{}'
+ end
+ JsonDataType.reset_column_information
+ column = JsonDataType.columns.find { |c| c.name == 'users' }
+ assert_equal :json, column.type
+
+ raise ActiveRecord::Rollback # reset the schema change
+ end
+ ensure
+ JsonDataType.reset_column_information
+ end
+
def test_type_cast_json
assert @column
diff --git a/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb b/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb
index 872204c644..05e0f0e192 100644
--- a/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb
@@ -250,6 +250,12 @@ module ActiveRecord
assert_equal "DISTINCT posts.title, posts.updater_id AS alias_0", @connection.distinct("posts.title", ["posts.updater_id desc nulls last"])
end
+ def test_raise_error_when_cannot_translate_exception
+ assert_raise TypeError do
+ @connection.send(:log, nil) { @connection.execute(nil) }
+ end
+ end
+
private
def insert(ctx, data)
binds = data.map { |name, value|
diff --git a/activerecord/test/cases/associations_test.rb b/activerecord/test/cases/associations_test.rb
index d7f25f760e..201fa5d5a9 100644
--- a/activerecord/test/cases/associations_test.rb
+++ b/activerecord/test/cases/associations_test.rb
@@ -172,6 +172,18 @@ class AssociationProxyTest < ActiveRecord::TestCase
assert_equal 1, josh.posts.size
end
+ def test_append_behaves_like_push
+ josh = Author.new(:name => "Josh")
+ josh.posts.append Post.new(:title => "New on Edge", :body => "More cool stuff!")
+ assert josh.posts.loaded?
+ assert_equal 1, josh.posts.size
+ end
+
+ def test_prepend_is_not_defined
+ josh = Author.new(:name => "Josh")
+ assert_raises(NoMethodError) { josh.posts.prepend Post.new }
+ end
+
def test_save_on_parent_does_not_load_target
david = developers(:david)
@@ -291,7 +303,7 @@ class OverridingAssociationsTest < ActiveRecord::TestCase
end
def test_requires_symbol_argument
- assert_raises ArgumentError do
+ assert_raises ArgumentError do
Class.new(Post) do
belongs_to "author"
end
diff --git a/activerecord/test/cases/quoting_test.rb b/activerecord/test/cases/quoting_test.rb
index 0ad05223d4..3dd11ae89d 100644
--- a/activerecord/test/cases/quoting_test.rb
+++ b/activerecord/test/cases/quoting_test.rb
@@ -122,35 +122,35 @@ module ActiveRecord
def test_quote_float
float = 1.2
assert_equal float.to_s, @quoter.quote(float, nil)
- assert_equal float.to_s, @quoter.quote(float, FakeColumn.new(:float))
+ assert_equal float.to_s, @quoter.quote(float, Object.new)
end
def test_quote_fixnum
fixnum = 1
assert_equal fixnum.to_s, @quoter.quote(fixnum, nil)
- assert_equal fixnum.to_s, @quoter.quote(fixnum, FakeColumn.new(:integer))
+ assert_equal fixnum.to_s, @quoter.quote(fixnum, Object.new)
end
def test_quote_bignum
bignum = 1 << 100
assert_equal bignum.to_s, @quoter.quote(bignum, nil)
- assert_equal bignum.to_s, @quoter.quote(bignum, FakeColumn.new(:integer))
+ assert_equal bignum.to_s, @quoter.quote(bignum, Object.new)
end
def test_quote_bigdecimal
bigdec = BigDecimal.new((1 << 100).to_s)
assert_equal bigdec.to_s('F'), @quoter.quote(bigdec, nil)
- assert_equal bigdec.to_s('F'), @quoter.quote(bigdec, FakeColumn.new(:decimal))
+ assert_equal bigdec.to_s('F'), @quoter.quote(bigdec, Object.new)
end
def test_dates_and_times
@quoter.extend(Module.new { def quoted_date(value) 'lol' end })
assert_equal "'lol'", @quoter.quote(Date.today, nil)
- assert_equal "'lol'", @quoter.quote(Date.today, FakeColumn.new(:date))
+ assert_equal "'lol'", @quoter.quote(Date.today, Object.new)
assert_equal "'lol'", @quoter.quote(Time.now, nil)
- assert_equal "'lol'", @quoter.quote(Time.now, FakeColumn.new(:time))
+ assert_equal "'lol'", @quoter.quote(Time.now, Object.new)
assert_equal "'lol'", @quoter.quote(DateTime.now, nil)
- assert_equal "'lol'", @quoter.quote(DateTime.now, FakeColumn.new(:datetime))
+ assert_equal "'lol'", @quoter.quote(DateTime.now, Object.new)
end
def test_crazy_object
diff --git a/activerecord/test/cases/relation/where_test.rb b/activerecord/test/cases/relation/where_test.rb
index 53cdf89b1f..c43c7601a2 100644
--- a/activerecord/test/cases/relation/where_test.rb
+++ b/activerecord/test/cases/relation/where_test.rb
@@ -108,30 +108,5 @@ module ActiveRecord
assert_equal 4, Edge.where(blank).order("sink_id").to_a.size
end
end
-
- def test_where_with_integer_for_string_column
- count = Post.where(:title => 0).count
- assert_equal 0, count
- end
-
- def test_where_with_float_for_string_column
- count = Post.where(:title => 0.0).count
- assert_equal 0, count
- end
-
- def test_where_with_boolean_for_string_column
- count = Post.where(:title => false).count
- assert_equal 0, count
- end
-
- def test_where_with_decimal_for_string_column
- count = Post.where(:title => BigDecimal.new(0)).count
- assert_equal 0, count
- end
-
- def test_where_with_duration_for_string_column
- count = Post.where(:title => 0.seconds).count
- assert_equal 0, count
- end
end
end
diff --git a/activerecord/test/cases/relation_scoping_test.rb b/activerecord/test/cases/relation_scoping_test.rb
index 8e6c38706f..7388324a0d 100644
--- a/activerecord/test/cases/relation_scoping_test.rb
+++ b/activerecord/test/cases/relation_scoping_test.rb
@@ -391,19 +391,19 @@ class DefaultScopingTest < ActiveRecord::TestCase
def test_default_scope_with_inheritance
wheres = InheritedPoorDeveloperCalledJamis.all.where_values_hash
assert_equal "Jamis", wheres[:name]
- assert_equal Arel.sql("50000"), wheres[:salary]
+ assert_equal 50000, wheres[:salary]
end
def test_default_scope_with_module_includes
wheres = ModuleIncludedPoorDeveloperCalledJamis.all.where_values_hash
assert_equal "Jamis", wheres[:name]
- assert_equal Arel.sql("50000"), wheres[:salary]
+ assert_equal 50000, wheres[:salary]
end
def test_default_scope_with_multiple_calls
wheres = MultiplePoorDeveloperCalledJamis.all.where_values_hash
assert_equal "Jamis", wheres[:name]
- assert_equal Arel.sql("50000"), wheres[:salary]
+ assert_equal 50000, wheres[:salary]
end
def test_scope_overwrites_default
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index d789b6cb7a..cd9835259a 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -540,8 +540,6 @@ ActiveRecord::Schema.define do
create_table :price_estimates, :force => true do |t|
t.string :estimate_of_type
t.integer :estimate_of_id
- t.string :thing_type
- t.integer :thing_id
t.integer :price
end
diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec
index c71525309b..a28310032a 100644
--- a/activesupport/activesupport.gemspec
+++ b/activesupport/activesupport.gemspec
@@ -20,7 +20,7 @@ Gem::Specification.new do |s|
s.rdoc_options.concat ['--encoding', 'UTF-8']
- s.add_dependency 'i18n', '~> 0.6', '>= 0.6.2'
+ s.add_dependency('i18n', '~> 0.6', '>= 0.6.4')
s.add_dependency 'multi_json', '~> 1.3'
s.add_dependency 'tzinfo', '~> 0.3.33'
s.add_dependency 'minitest', '~> 4.2'
diff --git a/guides/CHANGELOG.md b/guides/CHANGELOG.md
index ee6e64b731..b0e52847e1 100644
--- a/guides/CHANGELOG.md
+++ b/guides/CHANGELOG.md
@@ -1,5 +1,5 @@
## Rails 4.0.0 (unreleased) ##
-
+* Change Service pages(404, etc). *Stanislav Sobolev*
## Rails 4.0.0.beta1 (unreleased) ##
diff --git a/guides/code/getting_started/public/404.html b/guides/code/getting_started/public/404.html
index 3d875c342e..ae7b8649ae 100644
--- a/guides/code/getting_started/public/404.html
+++ b/guides/code/getting_started/public/404.html
@@ -2,17 +2,48 @@
<html>
<head>
<title>The page you were looking for doesn't exist (404)</title>
- <style>
- body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
- div.dialog {
- width: 25em;
- padding: 0 4em;
- margin: 4em auto 0 auto;
- border: 1px solid #ccc;
- border-right-color: #999;
- border-bottom-color: #999;
- }
- h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
+ <style>
+ body
+ {
+ background-color: #efefef;
+ color: #2E2F30;
+ text-align: center;
+ font-family: arial,sans-serif;
+ }
+ div.dialog
+ {
+ width: 25em;
+ margin: 4em auto 0 auto;
+ border: 1px solid #CCC;
+ border-right-color: #999;
+ border-left-color: #999;
+ border-bottom-color: #BBB;
+ border-top: #B00100 solid 4px;
+ border-top-left-radius: 9px;
+ border-top-right-radius: 9px;
+ background-color: white;
+ padding: 7px 4em 0 4em;
+ }
+ h1{
+ font-size: 100%;
+ color: #730E15;
+ line-height: 1.5em;
+ }
+ body>p
+ {
+ width: 33em;
+ margin: 0 auto 1em;
+ padding: 1em 0;
+ background-color: #f7f7f7;
+ border: 1px solid #CCC;
+ border-right-color: #999;
+ border-bottom-color: #999;
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+ border-top-color: #DADADA;
+ color: #666;
+ box-shadow: 0 3px 8px rgba(50,50,50,0.17);
+ }
</style>
</head>
diff --git a/guides/code/getting_started/public/422.html b/guides/code/getting_started/public/422.html
index 3f1bfb3417..b75cc2fd6c 100644
--- a/guides/code/getting_started/public/422.html
+++ b/guides/code/getting_started/public/422.html
@@ -2,17 +2,48 @@
<html>
<head>
<title>The change you wanted was rejected (422)</title>
- <style>
- body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
- div.dialog {
- width: 25em;
- padding: 0 4em;
- margin: 4em auto 0 auto;
- border: 1px solid #ccc;
- border-right-color: #999;
- border-bottom-color: #999;
- }
- h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
+ <style>
+ body
+ {
+ background-color: #efefef;
+ color: #2E2F30;
+ text-align: center;
+ font-family: arial,sans-serif;
+ }
+ div.dialog
+ {
+ width: 25em;
+ margin: 4em auto 0 auto;
+ border: 1px solid #CCC;
+ border-right-color: #999;
+ border-left-color: #999;
+ border-bottom-color: #BBB;
+ border-top: #B00100 solid 4px;
+ border-top-left-radius: 9px;
+ border-top-right-radius: 9px;
+ background-color: white;
+ padding: 7px 4em 0 4em;
+ }
+ h1{
+ font-size: 100%;
+ color: #730E15;
+ line-height: 1.5em;
+ }
+ body>p
+ {
+ width: 33em;
+ margin: 0 auto 1em;
+ padding: 1em 0;
+ background-color: #f7f7f7;
+ border: 1px solid #CCC;
+ border-right-color: #999;
+ border-bottom-color: #999;
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+ border-top-color: #DADADA;
+ color: #666;
+ box-shadow: 0 3px 8px rgba(50,50,50,0.17);
+ }
</style>
</head>
diff --git a/guides/code/getting_started/public/500.html b/guides/code/getting_started/public/500.html
index 012977d3d2..9641851e74 100644
--- a/guides/code/getting_started/public/500.html
+++ b/guides/code/getting_started/public/500.html
@@ -2,17 +2,48 @@
<html>
<head>
<title>We're sorry, but something went wrong (500)</title>
- <style>
- body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
- div.dialog {
- width: 25em;
- padding: 0 4em;
- margin: 4em auto 0 auto;
- border: 1px solid #ccc;
- border-right-color: #999;
- border-bottom-color: #999;
- }
- h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
+ <style>
+ body
+ {
+ background-color: #efefef;
+ color: #2E2F30;
+ text-align: center;
+ font-family: arial,sans-serif;
+ }
+ div.dialog
+ {
+ width: 25em;
+ margin: 4em auto 0 auto;
+ border: 1px solid #CCC;
+ border-right-color: #999;
+ border-left-color: #999;
+ border-bottom-color: #BBB;
+ border-top: #B00100 solid 4px;
+ border-top-left-radius: 9px;
+ border-top-right-radius: 9px;
+ background-color: white;
+ padding: 7px 4em 0 4em;
+ }
+ h1{
+ font-size: 100%;
+ color: #730E15;
+ line-height: 1.5em;
+ }
+ body>p
+ {
+ width: 33em;
+ margin: 0 auto 1em;
+ padding: 1em 0;
+ background-color: #f7f7f7;
+ border: 1px solid #CCC;
+ border-right-color: #999;
+ border-bottom-color: #999;
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+ border-top-color: #DADADA;
+ color: #666;
+ box-shadow: 0 3px 8px rgba(50,50,50,0.17);
+ }
</style>
</head>
diff --git a/guides/source/action_controller_overview.md b/guides/source/action_controller_overview.md
index da155628f3..e65f7e5b18 100644
--- a/guides/source/action_controller_overview.md
+++ b/guides/source/action_controller_overview.md
@@ -6,6 +6,7 @@ In this guide you will learn how controllers work and how they fit into the requ
After reading this guide, you will know:
* How to follow the flow of a request through a controller.
+* How to restrict parameters passed to your controller.
* Why and how to store data in the session or cookies.
* How to work with filters to execute code during request processing.
* How to use Action Controller's built-in HTTP authentication.
@@ -170,6 +171,123 @@ These options will be used as a starting point when generating URLs, so it's pos
If you define `default_url_options` in `ApplicationController`, as in the example above, it would be used for all URL generation. The method can also be defined in one specific controller, in which case it only affects URLs generated there.
+### Strong Parameters
+
+With strong parameters Action Controller parameters are forbidden to
+be used in Active Model mass assignments until they have been
+whitelisted. This means you'll have to make a conscious choice about
+which attributes to allow for mass updating and thus prevent
+accidentally exposing that which shouldn't be exposed.
+
+In addition, parameters can be marked as required and flow through a
+predefined raise/rescue flow to end up as a 400 Bad Request with no
+effort.
+
+```ruby
+class PeopleController < ActionController::Base
+ # This will raise an ActiveModel::ForbiddenAttributes exception
+ # because it's using mass assignment without an explicit permit
+ # step.
+ def create
+ Person.create(params[:person])
+ end
+
+ # This will pass with flying colors as long as there's a person key
+ # in the parameters, otherwise it'll raise a
+ # ActionController::MissingParameter exception, which will get
+ # caught by ActionController::Base and turned into that 400 Bad
+ # Request reply.
+ def update
+ person = current_account.people.find(params[:id])
+ person.update_attributes!(person_params)
+ redirect_to person
+ end
+
+ private
+ # Using a private method to encapsulate the permissible parameters
+ # is just a good pattern since you'll be able to reuse the same
+ # permit list between create and update. Also, you can specialize
+ # this method with per-user checking of permissible attributes.
+ def person_params
+ params.require(:person).permit(:name, :age)
+ end
+end
+```
+
+#### Permitted Scalar Values
+
+Given
+
+```ruby
+params.permit(:id)
+```
+
+the key `:id` will pass the whitelisting if it appears in `params` and
+it has a permitted scalar value associated. Otherwise the key is going
+to be filtered out, so arrays, hashes, or any other objects cannot be
+injected.
+
+The permitted scalar types are `String`, `Symbol`, `NilClass`,
+`Numeric`, `TrueClass`, `FalseClass`, `Date`, `Time`, `DateTime`,
+`StringIO`, `IO`, `ActionDispatch::Http::UploadedFile` and
+`Rack::Test::UploadedFile`.
+
+To declare that the value in `params+ must be an array of permitted
+scalar values map the key to an empty array:
+
+```ruby
+params.permit(:id => [])
+```
+
+To whitelist an entire hash of parameters, the `permit!+ method can be
+used
+
+```ruby
+params.require(:log_entry).permit!
+```
+
+This will mark the `:log_entry` parameters hash and any subhash of it
+permitted. Extreme care should be taken when using `permit!` as it
+will allow all current and future model attributes to be
+mass-assigned.
+
+#### Nested Parameters
+
+You can also use permit on nested parameters, like:
+
+```ruby
+params.permit(:name, {:emails => []},
+ :friends => [ :name,
+ { :family => [ :name ], :hobbies => [] }])
+```
+
+This declaration whitelists the `name`, `emails` and `friends`
+attributes. It is expected that `emails` will be an array of permitted
+scalar values and that `friends` will be an array of resources with
+specific attributes : they should have a `name` attribute (any
+permitted scalar values allowed), a `hobbies` attribute as an array of
+permitted scalar values, and a `family` attribute which is restricted
+to having a `name` (any permitted scalar values allowed, too).
+
+#### Outside the Scope of Strong Parameters
+
+The strong parameter API was designed with the most common use cases
+in mind. It is not meant as a silver bullet to handle all your
+whitelisting problems. However you can easily mix the API with your
+own code to adapt to your situation.
+
+Imagine a situation where you want to whitelist an attribute
+containing a hash with any keys. Using strong parameters you can't
+allow a hash with any keys but you can use a simple assignment to get
+the job done:
+
+```ruby
+def product_params
+ params.require(:product).permit(:name).tap do |whitelisted|
+ whitelisted[:data] = params[:product][:data]
+ end
+end
+```
Session
-------
diff --git a/guides/source/migrations.md b/guides/source/migrations.md
index d738d847e9..89ae564c24 100644
--- a/guides/source/migrations.md
+++ b/guides/source/migrations.md
@@ -179,6 +179,27 @@ class AddDetailsToProducts < ActiveRecord::Migration
end
```
+If the migration name is of the form "CreateXXX" and is
+followed by a list of column names and types then a migration creating the table
+XXX with the columns listed will be generated. For example:
+
+```bash
+$ rails generate migration CreateProducts name:string part_number:string
+```
+
+generates
+
+```ruby
+class CreateProducts < ActiveRecord::Migration
+ def change
+ create_table :products do |t|
+ t.string :name
+ t.string :part_number
+ end
+ end
+end
+```
+
As always, what has been generated for you is just a starting point. You can add
or remove from it as you see fit by editing the
`db/migrate/YYYYMMDDHHMMSS_add_details_to_products.rb` file.
diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md
index 52f5232efc..57945a256b 100644
--- a/guides/source/upgrading_ruby_on_rails.md
+++ b/guides/source/upgrading_ruby_on_rails.md
@@ -47,6 +47,18 @@ Rails 4.0 no longer supports loading plugins from `vendor/plugins`. You must rep
* Rails 4.0 has removed `attr_accessible` and `attr_protected` feature in favor of Strong Parameters. You can use the [Protected Attributes gem](https://github.com/rails/protected_attributes) to a smoothly upgrade path.
+* Rails 4.0 requires that scopes use a callable object such as a Proc or lambda:
+
+```ruby
+ scope :active, where(active: true)
+
+ # becomes
+ scope :active, -> { where active: true }
+```
+
+* Rails 4.0 has deprecated `ActiveRecord::Fixtures` in favor of `ActiveRecord::FixtureSet`.
+* Rails 4.0 has deprecated `ActiveRecord::TestCase` in favor of `ActiveSupport::TestCase`.
+
### Active Resource
Rails 4.0 extracted Active Resource to its own gem. If you still need the feature you can add the [Active Resource gem](https://github.com/rails/activeresource) in your Gemfile.
@@ -66,7 +78,16 @@ Rails 4.0 extracted Active Resource to its own gem. If you still need the featur
### Action Pack
-* There is an upgrading cookie store `UpgradeSignatureToEncryptionCookieStore` which helps you upgrading apps that use `CookieStore` to the new default `EncryptedCookieStore`. To use this `CookieStore` set `Myapp::Application.config.session_store :upgrade_signature_to_encryption_cookie_store, key: '_myapp_session'` in `config/initializers/session_store.rb`. Additionally, add `Myapp::Application.config.secret_key_base = 'some secret'` in `config/initializers/secret_token.rb`. Do not remove `Myapp::Application.config.secret_token = 'some secret'`.
+* Rails 4.0 introduces a new `UpgradeSignatureToEncryptionCookieStore` cookie store. This is useful for upgrading apps using the old default `CookieStore` to the new default `EncryptedCookieStore`. To use this transitional cookie store, you'll want to leave your existing `secret_token` in place, add a new `secret_key_base`, and change your `session_store` like so:
+
+```ruby
+ # config/initializers/session_store.rb
+ Myapp::Application.config.session_store :upgrade_signature_to_encryption_cookie_store, key: 'existing session key'
+
+ # config/initializers/secret_token.rb
+ Myapp::Application.config.secret_token = 'existing secret token'
+ Myapp::Application.config.secret_key_base = 'new secret key base'
+```
* Rails 4.0 removed the `ActionController::Base.asset_path` option. Use the assets pipeline feature.
@@ -74,6 +95,12 @@ Rails 4.0 extracted Active Resource to its own gem. If you still need the featur
* Rails 4.0 has removed Action and Page caching from Action Pack. You will need to add the `actionpack-action_caching` gem in order to use `caches_action` and the `actionpack-page_caching` to use `caches_pages` in your controllers.
+* Rails 4.0 has removed the XML parameters parser. You will need to add the `actionpack-xml_parser` gem if you require this feature.
+
+* Rails 4.0 changes the default memcached client from `memcache-client` to `dalli`. To upgrade, simply add `gem 'dalli'` to your `Gemfile`.
+
+* Rails 4.0 deprecates the `dom_id` and `dom_class` methods. You will need to include the `ActionView::RecordIdentifier` module in controllers requiring this feature.
+
* Rails 4.0 changed how `assert_generates`, `assert_recognizes`, and `assert_routing` work. Now all these assertions raise `Assertion` instead of `ActionController::RoutingError`.
* Rails 4.0 also changed the way unicode character routes are drawn. Now you can draw unicode character routes directly. If you already draw such routes, you must change them, for example:
@@ -88,6 +115,19 @@ becomes
get 'こんにちは', controller: 'welcome', action: 'index'
```
+* Rails 4.0 requires that routes using `match` must specify the request method. For example:
+
+```ruby
+ # Rails 3.x
+ match "/" => "root#index"
+
+ # becomes
+ match "/" => "root#index", via: :get
+
+ # or
+ get "/" => "root#index"
+```
+
* Rails 4.0 has removed ActionDispatch::BestStandardsSupport middleware, !DOCTYPE html already triggers standards mode per http://msdn.microsoft.com/en-us/library/jj676915(v=vs.85).aspx and ChromeFrame header has been moved to `config.action_dispatch.default_headers`
Remember you must also remove any references to the middleware from your application code, for example:
@@ -101,6 +141,21 @@ Also check your environment settings for `config.action_dispatch.best_standards_
* In Rails 4.0, precompiling assets no longer automatically copies non-JS/CSS assets from `vendor/assets` and `lib/assets`. Rails application and engine developers should put these assets in `app/assets` or configure `config.assets.precompile`.
+* In Rails 4.0, `ActionController::UnknownFormat` is raised when the action doesn't handle the request format. By default, the exception is handled by responding with 406 Not Acceptable, but you can override that now. In Rails 3, 406 Not Acceptable was always returned. No overrides.
+
+* In Rails 4.0, a generic `ActionDispatch::ParamsParser::ParseError` exception is raised when `ParamsParser` fails to parse request params. You will want to rescue this exception instead of the low-level `MultiJson::DecodeError`, for example.
+
+* In Rails 4.0, `SCRIPT_NAME` is properly nested when engines are mounted on an app that's served from a URL prefix. You no longer have to set `default_url_options[:script_name]` to work around overwritten URL prefixes.
+
+* Rails 4.0 deprecated `ActionController::Integration` in favor of `ActionDispatch::Integration`.
+* Rails 4.0 deprecated `ActionController::IntegrationTest` in favor of `ActionDispatch::IntegrationTest`.
+* Rails 4.0 deprecated `ActionController::PerformanceTest` in favor of `ActionDispatch::PerformanceTest`.
+* Rails 4.0 deprecated `ActionController::AbstractRequest` in favor of `ActionDispatch::Request`.
+* Rails 4.0 deprecated `ActionController::Request` in favor of `ActionDispatch::Request`.
+* Rails 4.0 deprecated `ActionController::AbstractResponse` in favor of `ActionDispatch::Response`.
+* Rails 4.0 deprecated `ActionController::Response` in favor of `ActionDispatch::Response`.
+* Rails 4.0 deprecated `ActionController::Routing` in favor of `ActionDispatch::Routing`.
+
### Active Support
Rails 4.0 removes the `j` alias for `ERB::Util#json_escape` since `j` is already used for `ActionView::Helpers::JavaScriptHelper#escape_javascript`.
@@ -109,6 +164,18 @@ Rails 4.0 removes the `j` alias for `ERB::Util#json_escape` since `j` is already
The order in which helpers from more than one directory are loaded has changed in Rails 4.0. Previously, they were gathered and then sorted alphabetically. After upgrading to Rails 4.0, helpers will preserve the order of loaded directories and will be sorted alphabetically only within each directory. Unless you explicitly use the `helpers_path` parameter, this change will only impact the way of loading helpers from engines. If you rely on the ordering, you should check if correct methods are available after upgrade. If you would like to change the order in which engines are loaded, you can use `config.railties_order=` method.
+### Active Record Observer and Action Controller Sweeper
+
+Active Record Observer and Action Controller Sweeper have been extracted to the `rails-observers` gem. You will need to add the `rails-observers` gem if you require these features.
+
+### sprockets-rails
+
+* `assets:precompile:primary` has been removed. Use `assets:precompile` instead.
+
+### sass-rails
+
+* `asset_url` with two arguments is deprecated. For example: `asset-url("rails.png", image)` becomes `asset-url("rails.png")`
+
Upgrading from Rails 3.1 to Rails 3.2
-------------------------------------
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md
index f3c07470af..4f7cb8254f 100644
--- a/railties/CHANGELOG.md
+++ b/railties/CHANGELOG.md
@@ -2,6 +2,7 @@
## Rails 4.0.0.beta1 (February 25, 2013) ##
+* Change Service pages(404, etc). *Stanislav Sobolev*
* Improve `rake stats` for JavaScript and CoffeeScript: ignore block comments
and calculates number of functions.
diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb
index 5af7de720c..25cc36ff5d 100644
--- a/railties/lib/rails/application.rb
+++ b/railties/lib/rails/application.rb
@@ -305,22 +305,8 @@ module Rails
def default_middleware_stack #:nodoc:
ActionDispatch::MiddlewareStack.new.tap do |middleware|
app = self
- if rack_cache = config.action_dispatch.rack_cache
- begin
- require 'rack/cache'
- rescue LoadError => error
- error.message << ' Be sure to add rack-cache to your Gemfile'
- raise
- end
-
- if rack_cache == true
- rack_cache = {
- metastore: "rails:/",
- entitystore: "rails:/",
- verbose: false
- }
- end
+ if rack_cache = load_rack_cache
require "action_dispatch/http/rack_cache"
middleware.use ::Rack::Cache, rack_cache
end
@@ -337,12 +323,14 @@ module Rails
middleware.use ::ActionDispatch::Static, paths["public"].first, config.static_cache_control
end
- middleware.use ::Rack::Lock unless config.cache_classes
+ middleware.use ::Rack::Lock unless allow_concurrency?
middleware.use ::Rack::Runtime
middleware.use ::Rack::MethodOverride
middleware.use ::ActionDispatch::RequestId
- middleware.use ::Rails::Rack::Logger, config.log_tags # must come after Rack::MethodOverride to properly log overridden methods
- middleware.use ::ActionDispatch::ShowExceptions, config.exceptions_app || ActionDispatch::PublicExceptions.new(Rails.public_path)
+
+ # Must come after Rack::MethodOverride to properly log overridden methods
+ middleware.use ::Rails::Rack::Logger, config.log_tags
+ middleware.use ::ActionDispatch::ShowExceptions, show_exceptions_app
middleware.use ::ActionDispatch::DebugExceptions, app
middleware.use ::ActionDispatch::RemoteIp, config.action_dispatch.ip_spoofing_check, config.action_dispatch.trusted_proxies
@@ -368,6 +356,40 @@ module Rails
end
end
+ def allow_concurrency?
+ if config.allow_concurrency.nil?
+ config.cache_classes
+ else
+ config.allow_concurrency
+ end
+ end
+
+ def load_rack_cache
+ rack_cache = config.action_dispatch.rack_cache
+ return unless rack_cache
+
+ begin
+ require 'rack/cache'
+ rescue LoadError => error
+ error.message << ' Be sure to add rack-cache to your Gemfile'
+ raise
+ end
+
+ if rack_cache == true
+ {
+ metastore: "rails:/",
+ entitystore: "rails:/",
+ verbose: false
+ }
+ else
+ rack_cache
+ end
+ end
+
+ def show_exceptions_app
+ config.exceptions_app || ActionDispatch::PublicExceptions.new(Rails.public_path)
+ end
+
def build_original_fullpath(env) #:nodoc:
path_info = env["PATH_INFO"]
query_string = env["QUERY_STRING"]
diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb
index 17763b39c5..31fc80e544 100644
--- a/railties/lib/rails/application/configuration.rb
+++ b/railties/lib/rails/application/configuration.rb
@@ -5,7 +5,7 @@ require 'rails/engine/configuration'
module Rails
class Application
class Configuration < ::Rails::Engine::Configuration
- attr_accessor :asset_host, :assets, :autoflush_log,
+ attr_accessor :allow_concurrency, :asset_host, :assets, :autoflush_log,
:cache_classes, :cache_store, :consider_all_requests_local, :console,
:eager_load, :exceptions_app, :file_watcher, :filter_parameters,
:force_ssl, :helpers_paths, :logger, :log_formatter, :log_tags,
@@ -20,6 +20,7 @@ module Rails
def initialize(*)
super
self.encoding = "utf-8"
+ @allow_concurrency = nil
@consider_all_requests_local = false
@filter_parameters = []
@filter_redirect = []
@@ -98,14 +99,15 @@ module Rails
end
# Loads and returns the configuration of the database.
- # First, looks at If ENV['DATABASE_URL'] if it's not present it uses the #paths["config/database"]
- # The contents of the file are processed via ERB before being sent through YAML::load.
def database_configuration
- if ENV['DATABASE_URL']
- {Rails.env => ActiveRecord::ConnectionAdapters::ConnectionSpecification::Resolver.connection_url_to_hash(ENV['DATABASE_URL']).stringify_keys}
+ yaml = paths["config/database"].first
+ if File.exists?(yaml)
+ require "erb"
+ YAML.load ERB.new(IO.read(yaml)).result
+ elsif ENV['DATABASE_URL']
+ nil
else
- require 'erb'
- YAML.load ERB.new(IO.read(paths["config/database"].first)).result
+ raise "Could not load database configuration. No such file - #{yaml}"
end
rescue Psych::SyntaxError => e
raise "YAML syntax error occurred while parsing #{paths["config/database"].first}. " \
diff --git a/railties/lib/rails/generators/erb/scaffold/templates/show.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/show.html.erb
index e15c963971..daae72270f 100644
--- a/railties/lib/rails/generators/erb/scaffold/templates/show.html.erb
+++ b/railties/lib/rails/generators/erb/scaffold/templates/show.html.erb
@@ -7,6 +7,5 @@
</p>
<% end -%>
-
<%%= link_to 'Edit', edit_<%= singular_table_name %>_path(@<%= singular_table_name %>) %> |
<%%= link_to 'Back', <%= index_helper %>_path %>
diff --git a/railties/lib/rails/generators/rails/app/templates/public/404.html b/railties/lib/rails/generators/rails/app/templates/public/404.html
index 3d875c342e..0ee82d3722 100644
--- a/railties/lib/rails/generators/rails/app/templates/public/404.html
+++ b/railties/lib/rails/generators/rails/app/templates/public/404.html
@@ -2,17 +2,48 @@
<html>
<head>
<title>The page you were looking for doesn't exist (404)</title>
- <style>
- body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
- div.dialog {
- width: 25em;
- padding: 0 4em;
- margin: 4em auto 0 auto;
- border: 1px solid #ccc;
- border-right-color: #999;
- border-bottom-color: #999;
- }
- h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
+ <style>
+ body
+ {
+ background-color: #efefef;
+ color: #2E2F30;
+ text-align: center;
+ font-family: arial,sans-serif;
+ }
+ div.dialog
+ {
+ width: 25em;
+ margin: 4em auto 0 auto;
+ border: 1px solid #CCC;
+ border-right-color: #999;
+ border-left-color: #999;
+ border-bottom-color: #BBB;
+ border-top: #B00100 solid 4px;
+ border-top-left-radius: 9px;
+ border-top-right-radius: 9px;
+ background-color: white;
+ padding: 7px 4em 0 4em;
+ }
+ h1{
+ font-size: 100%;
+ color: #730E15;
+ line-height: 1.5em;
+ }
+ body>p
+ {
+ width: 33em;
+ margin: 0 auto 1em;
+ padding: 1em 0;
+ background-color: #f7f7f7;
+ border: 1px solid #CCC;
+ border-right-color: #999;
+ border-bottom-color: #999;
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+ border-top-color: #DADADA;
+ color: #666;
+ box-shadow:0 3px 8px rgba(50,50,50,0.17);
+ }
</style>
</head>
diff --git a/railties/lib/rails/generators/rails/app/templates/public/422.html b/railties/lib/rails/generators/rails/app/templates/public/422.html
index 3f1bfb3417..ed58409a27 100644
--- a/railties/lib/rails/generators/rails/app/templates/public/422.html
+++ b/railties/lib/rails/generators/rails/app/templates/public/422.html
@@ -2,17 +2,48 @@
<html>
<head>
<title>The change you wanted was rejected (422)</title>
- <style>
- body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
- div.dialog {
- width: 25em;
- padding: 0 4em;
- margin: 4em auto 0 auto;
- border: 1px solid #ccc;
- border-right-color: #999;
- border-bottom-color: #999;
- }
- h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
+ <style>
+ body
+ {
+ background-color: #efefef;
+ color: #2E2F30;
+ text-align: center;
+ font-family: arial,sans-serif;
+ }
+ div.dialog
+ {
+ width: 25em;
+ margin: 4em auto 0 auto;
+ border: 1px solid #CCC;
+ border-right-color: #999;
+ border-left-color: #999;
+ border-bottom-color: #BBB;
+ border-top: #B00100 solid 4px;
+ border-top-left-radius: 9px;
+ border-top-right-radius: 9px;
+ background-color: white;
+ padding: 7px 4em 0 4em;
+ }
+ h1{
+ font-size: 100%;
+ color: #730E15;
+ line-height: 1.5em;
+ }
+ body>p
+ {
+ width: 33em;
+ margin: 0 auto 1em;
+ padding: 1em 0;
+ background-color: #f7f7f7;
+ border: 1px solid #CCC;
+ border-right-color: #999;
+ border-bottom-color: #999;
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+ border-top-color: #DADADA;
+ color: #666;
+ box-shadow:0 3px 8px rgba(50,50,50,0.17);
+ }
</style>
</head>
diff --git a/railties/lib/rails/generators/rails/app/templates/public/500.html b/railties/lib/rails/generators/rails/app/templates/public/500.html
index 012977d3d2..9417de0cc0 100644
--- a/railties/lib/rails/generators/rails/app/templates/public/500.html
+++ b/railties/lib/rails/generators/rails/app/templates/public/500.html
@@ -2,17 +2,48 @@
<html>
<head>
<title>We're sorry, but something went wrong (500)</title>
- <style>
- body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
- div.dialog {
- width: 25em;
- padding: 0 4em;
- margin: 4em auto 0 auto;
- border: 1px solid #ccc;
- border-right-color: #999;
- border-bottom-color: #999;
- }
- h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
+ <style>
+ body
+ {
+ background-color: #efefef;
+ color: #2E2F30;
+ text-align: center;
+ font-family: arial,sans-serif;
+ }
+ div.dialog
+ {
+ width: 25em;
+ margin: 4em auto 0 auto;
+ border: 1px solid #CCC;
+ border-right-color: #999;
+ border-left-color: #999;
+ border-bottom-color: #BBB;
+ border-top: #B00100 solid 4px;
+ border-top-left-radius: 9px;
+ border-top-right-radius: 9px;
+ background-color: white;
+ padding: 7px 4em 0 4em;
+ }
+ h1{
+ font-size: 100%;
+ color: #730E15;
+ line-height: 1.5em;
+ }
+ body>p
+ {
+ width: 33em;
+ margin: 0 auto 1em;
+ padding: 1em 0;
+ background-color: #f7f7f7;
+ border: 1px solid #CCC;
+ border-right-color: #999;
+ border-bottom-color: #999;
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+ border-top-color: #DADADA;
+ color: #666;
+ box-shadow:0 3px 8px rgba(50,50,50,0.17);
+ }
</style>
</head>
diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb
index af00748037..5fe01d0961 100644
--- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb
+++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb
@@ -94,6 +94,11 @@ task default: :test
end
end
+ def test_dummy_assets
+ template "rails/javascripts.js", "#{dummy_path}/app/assets/javascripts/application.js", force: true
+ template "rails/stylesheets.css", "#{dummy_path}/app/assets/stylesheets/application.css", force: true
+ end
+
def test_dummy_clean
inside dummy_path do
remove_file ".gitignore"
@@ -112,7 +117,7 @@ task default: :test
def stylesheets
if mountable?
- copy_file "#{app_templates_dir}/app/assets/stylesheets/application.css",
+ copy_file "rails/stylesheets.css",
"app/assets/stylesheets/#{name}/application.css"
elsif full?
empty_directory_with_keep_file "app/assets/stylesheets/#{name}"
@@ -123,8 +128,8 @@ task default: :test
return if options.skip_javascript?
if mountable?
- template "#{app_templates_dir}/app/assets/javascripts/application.js.tt",
- "app/assets/javascripts/#{name}/application.js"
+ template "rails/javascripts.js",
+ "app/assets/javascripts/#{name}/application.js"
elsif full?
empty_directory_with_keep_file "app/assets/javascripts/#{name}"
end
@@ -263,6 +268,7 @@ task default: :test
build(:generate_test_dummy)
store_application_definition!
build(:test_dummy_config)
+ build(:test_dummy_assets)
build(:test_dummy_clean)
# ensure that bin/rails has proper dummy_path
build(:bin, true)
diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/%name%.gemspec b/railties/lib/rails/generators/rails/plugin_new/templates/%name%.gemspec
index e956d13d8a..f7c12e67dd 100644
--- a/railties/lib/rails/generators/rails/plugin_new/templates/%name%.gemspec
+++ b/railties/lib/rails/generators/rails/plugin_new/templates/%name%.gemspec
@@ -19,9 +19,6 @@ Gem::Specification.new do |s|
<% end -%>
<%= '# ' if options.dev? || options.edge? -%>s.add_dependency "rails", "~> <%= Rails::VERSION::STRING %>"
-<% if engine? && !options[:skip_javascript] -%>
- # s.add_dependency "<%= "#{options[:javascript]}-rails" %>"
-<% end -%>
<% unless options[:skip_active_record] -%>
s.add_development_dependency "<%= gem_for_database %>"
diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile b/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile
index a8b5bfaf3f..3f2b78f2fd 100644
--- a/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile
+++ b/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile
@@ -2,9 +2,6 @@ source "https://rubygems.org"
<% if options[:skip_gemspec] -%>
<%= '# ' if options.dev? || options.edge? -%>gem "rails", "~> <%= Rails::VERSION::STRING %>"
-<% if engine? && !options[:skip_javascript] -%>
-# gem "<%= "#{options[:javascript]}-rails" %>"
-<% end -%>
<% else -%>
# Declare your gem's dependencies in <%= name %>.gemspec.
# Bundler will treat runtime dependencies like base dependencies, and
@@ -12,11 +9,6 @@ source "https://rubygems.org"
gemspec
<% end -%>
-<% unless options[:javascript] == 'jquery' -%>
-# jquery-rails is used by the dummy application
-gem "jquery-rails"
-
-<% end -%>
<% if options[:skip_gemspec] -%>
group :development do
gem "<%= gem_for_database %>"
diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/rails/javascripts.js b/railties/lib/rails/generators/rails/plugin_new/templates/rails/javascripts.js
new file mode 100644
index 0000000000..084d5d1c49
--- /dev/null
+++ b/railties/lib/rails/generators/rails/plugin_new/templates/rails/javascripts.js
@@ -0,0 +1,13 @@
+// This is a manifest file that'll be compiled into application.js, which will include all the files
+// listed below.
+//
+// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
+// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
+//
+// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
+// compiled file.
+//
+// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
+// GO AFTER THE REQUIRES BELOW.
+//
+//= require_tree .
diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/rails/stylesheets.css b/railties/lib/rails/generators/rails/plugin_new/templates/rails/stylesheets.css
new file mode 100644
index 0000000000..3192ec897b
--- /dev/null
+++ b/railties/lib/rails/generators/rails/plugin_new/templates/rails/stylesheets.css
@@ -0,0 +1,13 @@
+/*
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
+ * listed below.
+ *
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
+ *
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
+ * compiled file, but it's generally better to create a new file per style scope.
+ *
+ *= require_self
+ *= require_tree .
+ */
diff --git a/railties/test/application/middleware_test.rb b/railties/test/application/middleware_test.rb
index 73ef2046c0..d8076c7151 100644
--- a/railties/test/application/middleware_test.rb
+++ b/railties/test/application/middleware_test.rb
@@ -96,6 +96,12 @@ module ApplicationTests
assert !middleware.include?("Rack::Lock")
end
+ test "removes lock if allow concurrency is set" do
+ add_to_config "config.allow_concurrency = true"
+ boot!
+ assert !middleware.include?("Rack::Lock")
+ end
+
test "removes static asset server if serve_static_assets is disabled" do
add_to_config "config.serve_static_assets = false"
boot!
diff --git a/railties/test/application/rake/dbs_test.rb b/railties/test/application/rake/dbs_test.rb
index 820b838702..9e711f25bd 100644
--- a/railties/test/application/rake/dbs_test.rb
+++ b/railties/test/application/rake/dbs_test.rb
@@ -166,19 +166,6 @@ module ApplicationTests
require "#{app_path}/config/environment"
db_test_load_structure
end
-
- test 'db:test:load_structure with database_url' do
- old_rails_env = ENV["RAILS_ENV"]
- ENV["RAILS_ENV"] = 'test'
-
- begin
- require "#{app_path}/config/environment"
- set_database_url
- db_test_load_structure
- ensure
- ENV["RAILS_ENV"] = old_rails_env
- end
- end
end
end
end
diff --git a/railties/test/generators/migration_generator_test.rb b/railties/test/generators/migration_generator_test.rb
index 62d9d1f06a..d876597944 100644
--- a/railties/test/generators/migration_generator_test.rb
+++ b/railties/test/generators/migration_generator_test.rb
@@ -172,8 +172,19 @@ class MigrationGeneratorTest < Rails::Generators::TestCase
end
end
- def test_should_create_empty_migrations_if_name_not_start_with_add_or_remove
- migration = "create_books"
+ def test_create_table_migration
+ run_generator ["create_books", "title:string", "content:text"]
+ assert_migration "db/migrate/create_books.rb" do |content|
+ assert_method :change, content do |change|
+ assert_match(/create_table :books/, change)
+ assert_match(/ t\.string :title/, change)
+ assert_match(/ t\.text :content/, change)
+ end
+ end
+ end
+
+ def test_should_create_empty_migrations_if_name_not_start_with_add_or_remove_or_create
+ migration = "delete_books"
run_generator [migration, "title:string", "content:text"]
assert_migration "db/migrate/#{migration}.rb" do |content|
@@ -182,7 +193,7 @@ class MigrationGeneratorTest < Rails::Generators::TestCase
end
end
end
-
+
def test_properly_identifies_usage_file
assert generator_class.send(:usage_path)
end
diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb
index 904c1db57e..34441ef679 100644
--- a/railties/test/generators/plugin_new_generator_test.rb
+++ b/railties/test/generators/plugin_new_generator_test.rb
@@ -63,13 +63,24 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase
assert_no_directory "test/integration/"
assert_no_file "test"
- assert_no_match(/APP_RAKEFILE/, File.read(File.join(destination_root, "Rakefile")))
+ assert_file "Rakefile" do |contents|
+ assert_no_match(/APP_RAKEFILE/, contents)
+ end
end
def test_generating_adds_dummy_app_rake_tasks_without_unit_test_files
run_generator [destination_root, "-T", "--mountable", '--dummy-path', 'my_dummy_app']
+ assert_file "Rakefile", /APP_RAKEFILE/
+ end
+
+ def test_generating_adds_dummy_app_without_javascript_and_assets_deps
+ run_generator [destination_root]
+
+ assert_file "test/dummy/app/assets/stylesheets/application.css"
- assert_match(/APP_RAKEFILE/, File.read(File.join(destination_root, "Rakefile")))
+ assert_file "test/dummy/app/assets/javascripts/application.js" do |contents|
+ assert_no_match(/jquery/, contents)
+ end
end
def test_ensure_that_plugin_options_are_not_passed_to_app_generator
@@ -112,7 +123,9 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase
def test_ensure_that_skip_active_record_option_is_passed_to_app_generator
run_generator [destination_root, "--skip_active_record"]
assert_no_file "test/dummy/config/database.yml"
- assert_no_match(/ActiveRecord/, File.read(File.join(destination_root, "test/test_helper.rb")))
+ assert_file "test/test_helper.rb" do |contents|
+ assert_no_match /ActiveRecord/, contents
+ end
end
def test_ensure_that_database_option_is_passed_to_app_generator
@@ -134,8 +147,6 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase
def test_skipping_javascripts_without_mountable_option
run_generator
assert_no_file "app/assets/javascripts/bukkits/application.js"
- assert_no_file "vendor/assets/javascripts/jquery.js"
- assert_no_file "vendor/assets/javascripts/jquery_ujs.js"
end
def test_javascripts_generation
@@ -143,33 +154,9 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase
assert_file "app/assets/javascripts/bukkits/application.js"
end
- def test_jquery_is_the_default_javascript_library
- run_generator [destination_root, "--mountable"]
- assert_file "app/assets/javascripts/bukkits/application.js" do |contents|
- assert_match %r{^//= require jquery}, contents
- assert_match %r{^//= require jquery_ujs}, contents
- end
- assert_file 'bukkits.gemspec' do |contents|
- assert_match(/jquery-rails/, contents)
- end
- end
-
- def test_other_javascript_libraries
- run_generator [destination_root, "--mountable", '-j', 'prototype']
- assert_file "app/assets/javascripts/bukkits/application.js" do |contents|
- assert_match %r{^//= require prototype}, contents
- assert_match %r{^//= require prototype_ujs}, contents
- end
- assert_file 'bukkits.gemspec' do |contents|
- assert_match(/prototype-rails/, contents)
- end
- end
-
def test_skip_javascripts
run_generator [destination_root, "--skip-javascript", "--mountable"]
assert_no_file "app/assets/javascripts/bukkits/application.js"
- assert_no_file "vendor/assets/javascripts/jquery.js"
- assert_no_file "vendor/assets/javascripts/jquery_ujs.js"
end
def test_template_from_dir_pwd
@@ -318,16 +305,6 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase
assert_no_match('gemspec', contents)
assert_match(/gem "rails", "~> #{Rails::VERSION::STRING}"/, contents)
assert_match(/group :development do\n gem "sqlite3"\nend/, contents)
- assert_match(/# gem "jquery-rails"/, contents)
- assert_no_match(/# jquery-rails is used by the dummy application\ngem "jquery-rails"/, contents)
- end
- end
-
- def test_skipping_gemspec_in_full_mode_with_javascript_option
- run_generator [destination_root, "--skip-gemspec", "--full", "--javascript=prototype"]
- assert_file "Gemfile" do |contents|
- assert_match(/# gem "prototype-rails"/, contents)
- assert_match(/# jquery-rails is used by the dummy application\ngem "jquery-rails"/, contents)
end
end