Merge branch 'master' into rm-uuid-fixtures

Conflicts:
	activerecord/CHANGELOG.md
	activesupport/CHANGELOG.md
This commit is contained in:
Rafael Mendonça França 2014-04-10 15:34:55 -03:00
commit 085ce4f141
79 changed files with 783 additions and 287 deletions

View File

@ -1,3 +1,4 @@
services: memcache
script: 'ci/travis.rb'
before_install:
- travis_retry gem install bundler

View File

@ -11,6 +11,7 @@ gem 'rack-cache', '~> 1.2'
gem 'jquery-rails', '~> 3.1.0'
gem 'turbolinks'
gem 'coffee-rails', '~> 4.0.0'
gem 'sprockets-rails', github: 'rails/sprockets-rails', branch: '2-1-stable'
# require: false so bcrypt is loaded only when has_secure_password is used.
# This is to avoid ActiveModel (and by extension the entire framework)

View File

@ -76,7 +76,7 @@ We encourage you to contribute to Ruby on Rails! Please check out the
## Code Status
* [![Build Status](https://travis-ci.org/rails/rails.png?branch=master)](https://travis-ci.org/rails/rails)
* [![Build Status](https://travis-ci.org/rails/rails.svg?branch=master)](https://travis-ci.org/rails/rails)
## License

View File

@ -32,11 +32,14 @@ module ActionDispatch
private
def redirect_to_https(request)
url = URI(request.url)
url.scheme = "https"
url.host = @host if @host
url.port = @port if @port
headers = { 'Content-Type' => 'text/html', 'Location' => url.to_s }
host = @host || request.host
port = @port || request.port
location = "https://#{host}"
location << ":#{port}" if port != 80
location << request.fullpath
headers = { 'Content-Type' => 'text/html', 'Location' => location }
[301, headers, []]
end

View File

@ -210,20 +210,29 @@ class FlashTest < ActionController::TestCase
end
def test_redirect_to_with_adding_flash_types
@controller.class.add_flash_types :foo
original_controller = @controller
test_controller_with_flash_type_foo = Class.new(TestController) do
add_flash_types :foo
end
@controller = test_controller_with_flash_type_foo.new
get :redirect_with_foo_flash
assert_equal "for great justice", @controller.send(:flash)[:foo]
ensure
@controller = original_controller
end
class SubclassesTestController < TestController; end
def test_add_flash_type_to_subclasses
TestController.add_flash_types :foo
assert SubclassesTestController._flash_types.include?(:foo)
test_controller_with_flash_type_foo = Class.new(TestController) do
add_flash_types :foo
end
subclass_controller_with_no_flash_type = Class.new(test_controller_with_flash_type_foo)
assert subclass_controller_with_no_flash_type._flash_types.include?(:foo)
end
def test_do_not_add_flash_type_to_parent_class
SubclassesTestController.add_flash_types :bar
def test_does_not_add_flash_type_to_parent_class
Class.new(TestController) do
add_flash_types :bar
end
assert_not TestController._flash_types.include?(:bar)
end
end

View File

@ -196,6 +196,13 @@ class SSLTest < ActionDispatch::IntegrationTest
response.headers['Location']
end
def test_redirect_to_host_with_port
self.app = ActionDispatch::SSL.new(default_app, :host => "ssl.example.org:443")
get "http://example.org/path?key=value"
assert_equal "https://ssl.example.org:443/path?key=value",
response.headers['Location']
end
def test_redirect_to_secure_host_when_on_subdomain
self.app = ActionDispatch::SSL.new(default_app, :host => "ssl.example.org")
get "http://ssl.example.org/path?key=value"

View File

@ -53,7 +53,7 @@ module ActiveModel
#
# Configuration options:
# * <tt>:on</tt> - Specifies when this validation is active
# (<tt>:create</tt> or <tt>:update</tt>.
# (<tt>:create</tt> or <tt>:update</tt>).
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine
# if the validation should occur (e.g. <tt>if: :allow_validation</tt>,
# or <tt>if: Proc.new { |user| user.signup_step > 2 }</tt>).

View File

@ -4,6 +4,34 @@
*Roderick van Domburg*
* Fixed a problem where an enum would overwrite values of another enum
with the same name in an unrelated class.
Fixes #14607.
*Evan Whalen*
* PostgreSQL and SQLite string columns no longer have a default limit of 255.
Fixes #13435, #9153.
*Vladimir Sazhin*, *Toms Mikoss*, *Yves Senn*
* Make possible to have an association called `records`.
Fixes #11645.
*prathamesh-sonpatki*
* `to_sql` on an association now matches the query that is actually executed, where it
could previously have incorrectly accrued additional conditions (e.g. as a result of
a previous query). CollectionProxy now always defers to the association scope's
`arel` method so the (incorrect) inherited one should be entirely concealed.
Fixes #14003.
*Jefferson Lai*
* Block a few default Class methods as scope name.
For instance, this will raise:

View File

@ -134,11 +134,11 @@ module ActiveRecord
end
def create(attributes = {}, &block)
create_record(attributes, &block)
_create_record(attributes, &block)
end
def create!(attributes = {}, &block)
create_record(attributes, true, &block)
_create_record(attributes, true, &block)
end
# Add +records+ to this association. Returns +self+ so method calls may
@ -182,11 +182,11 @@ module ActiveRecord
#
# See delete for more info.
def delete_all(dependent = nil)
if dependent.present? && ![:nullify, :delete_all].include?(dependent)
if dependent && ![:nullify, :delete_all].include?(dependent)
raise ArgumentError, "Valid values are :nullify or :delete_all"
end
dependent = if dependent.present?
dependent = if dependent
dependent
elsif options[:dependent] == :destroy
:delete_all
@ -449,13 +449,13 @@ module ActiveRecord
persisted + memory
end
def create_record(attributes, raise = false, &block)
def _create_record(attributes, raise = false, &block)
unless owner.persisted?
raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved"
end
if attributes.is_a?(Array)
attributes.collect { |attr| create_record(attr, raise, &block) }
attributes.collect { |attr| _create_record(attr, raise, &block) }
else
transaction do
add_to_target(build_record(attributes)) do |record|

View File

@ -357,7 +357,7 @@ module ActiveRecord
# Deletes all the records from the collection. For +has_many+ associations,
# the deletion is done according to the strategy specified by the <tt>:dependent</tt>
# option. Returns an array with the deleted records.
# option.
#
# If no <tt>:dependent</tt> option is given, then it will follow the
# default strategy. The default strategy is <tt>:nullify</tt>. This
@ -435,11 +435,6 @@ module ActiveRecord
# # ]
#
# person.pets.delete_all
# # => [
# # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
# # #<Pet id: 2, name: "Spook", person_id: 1>,
# # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
# # ]
#
# Pet.find(1, 2, 3)
# # => ActiveRecord::RecordNotFound
@ -860,6 +855,10 @@ module ActiveRecord
!!@association.include?(record)
end
def arel
scope.arel
end
def proxy_association
@association
end

View File

@ -18,11 +18,11 @@ module ActiveRecord
end
def create(attributes = {}, &block)
create_record(attributes, &block)
_create_record(attributes, &block)
end
def create!(attributes = {}, &block)
create_record(attributes, true, &block)
_create_record(attributes, true, &block)
end
def build(attributes = {})
@ -52,7 +52,7 @@ module ActiveRecord
replace(record)
end
def create_record(attributes, raise_error = false)
def _create_record(attributes, raise_error = false)
record = build_record(attributes)
yield(record) if block_given?
saved = record.save

View File

@ -79,11 +79,11 @@ module ActiveRecord
end
end
def update_record(*)
def _update_record(*)
partial_writes? ? super(keys_for_partial_write) : super
end
def create_record(*)
def _create_record(*)
partial_writes? ? super(keys_for_partial_write) : super
end

View File

@ -302,11 +302,11 @@ module ActiveRecord
run_callbacks(:save) { super }
end
def create_record #:nodoc:
def _create_record #:nodoc:
run_callbacks(:create) { super }
end
def update_record(*) #:nodoc:
def _update_record(*) #:nodoc:
run_callbacks(:update) { super }
end
end

View File

@ -33,7 +33,7 @@ module ActiveRecord
def initialize(url)
raise "Database URL cannot be empty" if url.blank?
@uri = URI.parse(url)
@adapter = @uri.scheme
@adapter = @uri.scheme.gsub('-', '_')
@adapter = "postgresql" if @adapter == "postgres"
if @uri.opaque
@ -220,10 +220,10 @@ module ActiveRecord
# an environment key or a URL spec, so we have deprecated
# this ambiguous behaviour and in the future this function
# can be removed in favor of resolve_url_connection.
if configurations.key?(spec)
if configurations.key?(spec) || spec !~ /:/
ActiveSupport::Deprecation.warn "Passing a string to ActiveRecord::Base.establish_connection " \
"for a configuration lookup is deprecated, please pass a symbol (#{spec.to_sym.inspect}) instead"
resolve_connection(configurations[spec])
resolve_symbol_connection(spec)
else
resolve_url_connection(spec)
end

View File

@ -4,14 +4,14 @@ module ActiveRecord
module Quoting
# Escapes binary strings for bytea input to the database.
def escape_bytea(value)
PGconn.escape_bytea(value) if value
@connection.escape_bytea(value) if value
end
# Unescapes bytea output from a database to the binary string it represents.
# NOTE: This is NOT an inverse of escape_bytea! This is only to be used
# on escaped binary output from database drive.
def unescape_bytea(value)
PGconn.unescape_bytea(value) if value
@connection.unescape_bytea(value) if value
end
# Quotes PostgreSQL-specific data types for SQL input.

View File

@ -209,7 +209,7 @@ module ActiveRecord
NATIVE_DATABASE_TYPES = {
primary_key: "serial primary key",
string: { name: "character varying", limit: 255 },
string: { name: "character varying" },
text: { name: "text" },
integer: { name: "integer" },
float: { name: "float" },

View File

@ -63,7 +63,7 @@ module ActiveRecord
NATIVE_DATABASE_TYPES = {
primary_key: 'INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL',
string: { name: "varchar", limit: 255 },
string: { name: "varchar" },
text: { name: "text" },
integer: { name: "integer" },
float: { name: "float" },

View File

@ -58,9 +58,9 @@ module ActiveRecord
end
class MergeAndResolveDefaultUrlConfig # :nodoc:
def initialize(raw_configurations, url = ENV['DATABASE_URL'])
def initialize(raw_configurations)
@raw_config = raw_configurations.dup
@url = url
@env = DEFAULT_ENV.call.to_s
end
# Returns fully resolved connection hashes.
@ -71,33 +71,10 @@ module ActiveRecord
private
def config
if @url
raw_merged_into_default
else
@raw_config
end
end
def raw_merged_into_default
default = default_url_hash
@raw_config.each do |env, values|
default[env] = values || {}
default[env].merge!("url" => @url) { |h, v1, v2| v1 || v2 } if default[env].is_a?(Hash)
end
default
end
# When the raw configuration is not present and ENV['DATABASE_URL']
# is available we return a hash with the connection information in
# the connection URL. This hash responds to any string key with
# resolved connection information.
def default_url_hash
Hash.new do |hash, key|
hash[key] = if key.is_a? String
ActiveRecord::ConnectionAdapters::ConnectionSpecification::ConnectionUrlResolver.new(@url).to_hash
else
nil
@raw_config.dup.tap do |cfg|
if url = ENV['DATABASE_URL']
cfg[@env] ||= {}
cfg[@env]["url"] ||= url
end
end
end

View File

@ -1,3 +1,5 @@
require 'active_support/core_ext/object/deep_dup'
module ActiveRecord
# Declare an enum attribute where the values map to integers in the database,
# but can be queried by name. Example:
@ -65,10 +67,14 @@ module ActiveRecord
#
# Where conditions on an enum attribute must use the ordinal value of an enum.
module Enum
DEFINED_ENUMS = {} # :nodoc:
def self.extended(base)
base.class_attribute(:defined_enums)
base.defined_enums = {}
end
def enum_mapping_for(attr_name) # :nodoc:
DEFINED_ENUMS[attr_name.to_s]
def inherited(base)
base.defined_enums = defined_enums.deep_dup
super
end
def enum(definitions)
@ -122,9 +128,8 @@ module ActiveRecord
klass.send(:detect_enum_conflict!, name, value, true)
klass.scope value, -> { klass.where name => i }
end
DEFINED_ENUMS[name.to_s] = enum_values
end
defined_enums[name.to_s] = enum_values
end
end
@ -134,7 +139,7 @@ module ActiveRecord
mod = Module.new do
private
def save_changed_attribute(attr_name, value)
if (mapping = self.class.enum_mapping_for(attr_name))
if (mapping = self.class.defined_enums[attr_name.to_s])
if attribute_changed?(attr_name)
old = changed_attributes[attr_name]

View File

@ -66,7 +66,7 @@ module ActiveRecord
send(lock_col + '=', previous_lock_value + 1)
end
def update_record(attribute_names = @attributes.keys) #:nodoc:
def _update_record(attribute_names = @attributes.keys) #:nodoc:
return super unless locking_enabled?
return 0 if attribute_names.empty?

View File

@ -484,24 +484,24 @@ module ActiveRecord
def create_or_update
raise ReadOnlyRecord if readonly?
result = new_record? ? create_record : update_record
result = new_record? ? _create_record : _update_record
result != false
end
# Updates the associated record with values matching those of the instance attributes.
# Returns the number of affected rows.
def update_record(attribute_names = @attributes.keys)
def _update_record(attribute_names = @attributes.keys)
attributes_values = arel_attributes_with_values_for_update(attribute_names)
if attributes_values.empty?
0
else
self.class.unscoped.update_record attributes_values, id, id_was
self.class.unscoped._update_record attributes_values, id, id_was
end
end
# Creates a record with values matching those of the instance attributes
# and returns its id.
def create_record(attribute_names = @attributes.keys)
def _create_record(attribute_names = @attributes.keys)
attributes_values = arel_attributes_with_values_for_create(attribute_names)
new_id = self.class.unscoped.insert attributes_values

View File

@ -22,11 +22,11 @@ module ActiveRecord
end
def self.add_reflection(ar, name, reflection)
ar.reflections = ar.reflections.merge(name => reflection)
ar.reflections = ar.reflections.merge(name.to_s => reflection)
end
def self.add_aggregate_reflection(ar, name, reflection)
ar.aggregate_reflections = ar.aggregate_reflections.merge(name => reflection)
ar.aggregate_reflections = ar.aggregate_reflections.merge(name.to_s => reflection)
end
# \Reflection enables to interrogate Active Record classes and objects
@ -48,7 +48,7 @@ module ActiveRecord
# Account.reflect_on_aggregation(:balance) # => the balance AggregateReflection
#
def reflect_on_aggregation(aggregation)
aggregate_reflections[aggregation]
aggregate_reflections[aggregation.to_s]
end
# Returns an array of AssociationReflection objects for all the
@ -72,7 +72,7 @@ module ActiveRecord
# Invoice.reflect_on_association(:line_items).macro # returns :has_many
#
def reflect_on_association(association)
reflections[association]
reflections[association.to_s]
end
# Returns an array of AssociationReflection objects for all associations which have <tt>:autosave</tt> enabled.
@ -617,7 +617,7 @@ module ActiveRecord
# # => [:tag, :tags]
#
def source_reflection_names
(options[:source] ? [options[:source]] : [name.to_s.singularize, name]).collect { |n| n.to_sym }.uniq
options[:source] ? [options[:source]] : [name.to_s.singularize, name].uniq
end
def source_reflection_name # :nodoc:

View File

@ -70,7 +70,7 @@ module ActiveRecord
binds)
end
def update_record(values, id, id_was) # :nodoc:
def _update_record(values, id, id_was) # :nodoc:
substitutes, binds = substitute_values values
um = @klass.unscoped.where(@klass.arel_table[@klass.primary_key].eq(id_was || id)).arel.compile_update(substitutes, @klass.primary_key)

View File

@ -231,7 +231,7 @@ module ActiveRecord
def execute_simple_calculation(operation, column_name, distinct) #:nodoc:
# Postgresql doesn't like ORDER BY when there are no GROUP BY
relation = reorder(nil)
relation = unscope(:order)
column_alias = column_name

View File

@ -139,7 +139,6 @@ module ActiveRecord
def merge_single_values
relation.from_value = values[:from] unless relation.from_value
relation.lock_value = values[:lock] unless relation.lock_value
relation.reverse_order_value = values[:reverse_order]
unless values[:create_with].blank?
relation.create_with_value = (relation.create_with_value || {}).merge(values[:create_with])

View File

@ -825,7 +825,9 @@ module ActiveRecord
end
def reverse_order! # :nodoc:
self.reverse_order_value = !reverse_order_value
orders = order_values.uniq
orders.reject!(&:blank?)
self.order_values = reverse_sql_order(orders)
self
end
@ -871,7 +873,6 @@ module ActiveRecord
case scope
when :order
self.reverse_order_value = false
result = []
else
result = [] unless single_val_method
@ -1031,7 +1032,6 @@ module ActiveRecord
def build_order(arel)
orders = order_values.uniq
orders.reject!(&:blank?)
orders = reverse_sql_order(orders) if reverse_order_value
arel.order(*orders) unless orders.empty?
end

View File

@ -43,7 +43,7 @@ module ActiveRecord
private
def create_record
def _create_record
if self.record_timestamps
current_time = current_time_from_proper_timezone
@ -57,7 +57,7 @@ module ActiveRecord
super
end
def update_record(*args)
def _update_record(*args)
if should_record_timestamps?
current_time = current_time_from_proper_timezone

View File

@ -93,7 +93,7 @@ module ActiveRecord
end
def map_enum_attribute(klass, attribute, value)
mapping = klass.enum_mapping_for(attribute.to_s)
mapping = klass.defined_enums[attribute.to_s]
value = mapping[value] if value && mapping
value
end

View File

@ -25,7 +25,7 @@ class PostgresqlArrayTest < ActiveRecord::TestCase
def test_column
assert_equal :string, @column.type
assert_equal "character varying(255)", @column.sql_type
assert_equal "character varying", @column.sql_type
assert @column.array
assert_not @column.text?
assert_not @column.number?

View File

@ -70,6 +70,23 @@ class PostgresqlByteaTest < ActiveRecord::TestCase
assert_equal(data, record.payload)
end
def test_via_to_sql
data = "'\u001F\\"
record = ByteaDataType.create(payload: data)
sql = ByteaDataType.where(payload: data).select(:payload).to_sql
result = @connection.query(sql)
assert_equal([[data]], result)
end
def test_via_to_sql_with_complicating_connection
Thread.new do
other_conn = ActiveRecord::Base.connection
other_conn.execute('SET standard_conforming_strings = off')
end.join
test_via_to_sql
end
def test_write_binary
data = File.read(File.join(File.dirname(__FILE__), '..', '..', '..', 'assets', 'example.log'))
assert(data.size > 1)

View File

@ -16,6 +16,8 @@ require 'models/essay'
require 'models/toy'
require 'models/invoice'
require 'models/line_item'
require 'models/column'
require 'models/record'
class BelongsToAssociationsTest < ActiveRecord::TestCase
fixtures :accounts, :companies, :developers, :projects, :topics,
@ -885,4 +887,10 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
end
end
end
test 'belongs_to works with model called Record' do
record = Record.create!
Column.create! record: record
assert_equal 1, Column.count
end
end

View File

@ -387,6 +387,20 @@ class CalculationsTest < ActiveRecord::TestCase
assert_raise(ArgumentError) { Account.count(1, 2, 3) }
end
def test_count_with_order
assert_equal 6, Account.order(:credit_limit).count
end
def test_count_with_reverse_order
assert_equal 6, Account.order(:credit_limit).reverse_order.count
end
def test_count_with_where_and_order
assert_equal 1, Account.where(firm_name: '37signals').count
assert_equal 1, Account.where(firm_name: '37signals').order(:firm_name).count
assert_equal 1, Account.where(firm_name: '37signals').order(:firm_name).reverse_order.count
end
def test_should_sum_expression
# Oracle adapter returns floating point value 636.0 after SUM
if current_adapter?(:OracleAdapter)

View File

@ -25,35 +25,45 @@ module ActiveRecord
ConnectionSpecification::Resolver.new(klass.new(config).resolve).spec(spec)
end
def test_resolver_with_database_uri_and_known_key
def test_resolver_with_database_uri_and_current_env_symbol_key
ENV['DATABASE_URL'] = "postgres://localhost/foo"
config = { "production" => { "adapter" => "not_postgres", "database" => "not_foo" } }
actual = resolve(:production, config)
config = { "not_production" => { "adapter" => "not_postgres", "database" => "not_foo" } }
actual = resolve(:default_env, config)
expected = { "adapter"=>"postgresql", "database"=>"foo", "host"=>"localhost" }
assert_equal expected, actual
end
def test_resolver_with_database_uri_and_known_string_key
def test_resolver_with_database_uri_and_and_current_env_string_key
ENV['DATABASE_URL'] = "postgres://localhost/foo"
config = { "production" => { "adapter" => "not_postgres", "database" => "not_foo" } }
actual = assert_deprecated { resolve("production", config) }
config = { "default_env" => { "adapter" => "not_postgres", "database" => "not_foo" } }
actual = assert_deprecated { resolve("default_env", config) }
expected = { "adapter"=>"postgresql", "database"=>"foo", "host"=>"localhost" }
assert_equal expected, actual
end
def test_resolver_with_database_uri_and_known_key
ENV['DATABASE_URL'] = "postgres://localhost/foo"
config = { "production" => { "adapter" => "not_postgres", "database" => "not_foo", "host" => "localhost" } }
actual = resolve(:production, config)
expected = { "adapter"=>"not_postgres", "database"=>"not_foo", "host"=>"localhost" }
assert_equal expected, actual
end
def test_resolver_with_database_uri_and_unknown_symbol_key
ENV['DATABASE_URL'] = "postgres://localhost/foo"
config = { "not_production" => { "adapter" => "not_postgres", "database" => "not_foo" } }
actual = resolve(:production, config)
expected = { "adapter"=>"postgresql", "database"=>"foo", "host"=>"localhost" }
assert_equal expected, actual
assert_raises AdapterNotSpecified do
resolve(:production, config)
end
end
def test_resolver_with_database_uri_and_unknown_string_key
ENV['DATABASE_URL'] = "postgres://localhost/foo"
config = { "not_production" => { "adapter" => "not_postgres", "database" => "not_foo" } }
assert_raises AdapterNotSpecified do
spec("production", config)
assert_deprecated do
assert_raises AdapterNotSpecified do
spec("production", config)
end
end
end
@ -73,16 +83,24 @@ module ActiveRecord
def test_environment_does_not_exist_in_config_url_does_exist
ENV['DATABASE_URL'] = "postgres://localhost/foo"
config = { "not_production" => { "adapter" => "not_postgres", "database" => "not_foo" } }
config = { "not_default_env" => { "adapter" => "not_postgres", "database" => "not_foo" } }
actual = klass.new(config).resolve
expect_prod = { "adapter"=>"postgresql", "database"=>"foo", "host"=>"localhost" }
assert_equal expect_prod, actual["production"]
assert_equal expect_prod, actual["default_env"]
end
def test_url_with_hyphenated_scheme
ENV['DATABASE_URL'] = "ibm-db://localhost/foo"
config = { "default_env" => { "adapter" => "not_postgres", "database" => "not_foo", "host" => "localhost" } }
actual = resolve(:default_env, config)
expected = { "adapter"=>"ibm_db", "database"=>"foo", "host"=>"localhost" }
assert_equal expected, actual
end
def test_string_connection
config = { "production" => "postgres://localhost/foo" }
config = { "default_env" => "postgres://localhost/foo" }
actual = klass.new(config).resolve
expected = { "production" =>
expected = { "default_env" =>
{ "adapter" => "postgresql",
"database" => "foo",
"host" => "localhost"
@ -92,9 +110,9 @@ module ActiveRecord
end
def test_url_sub_key
config = { "production" => { "url" => "postgres://localhost/foo" } }
config = { "default_env" => { "url" => "postgres://localhost/foo" } }
actual = klass.new(config).resolve
expected = { "production" =>
expected = { "default_env" =>
{ "adapter" => "postgresql",
"database" => "foo",
"host" => "localhost"
@ -123,9 +141,10 @@ module ActiveRecord
expected = { "adapter" => "postgresql",
"database" => "foo",
"host" => "localhost" }
assert_equal expected, actual["production"]
assert_equal expected, actual["development"]
assert_equal expected, actual["test"]
assert_equal expected, actual["default_env"]
assert_equal nil, actual["production"]
assert_equal nil, actual["development"]
assert_equal nil, actual["test"]
assert_equal nil, actual[:production]
assert_equal nil, actual[:development]
assert_equal nil, actual[:test]
@ -134,9 +153,9 @@ module ActiveRecord
def test_url_sub_key_with_database_url
ENV['DATABASE_URL'] = "NOT-POSTGRES://localhost/NOT_FOO"
config = { "production" => { "url" => "postgres://localhost/foo" } }
config = { "default_env" => { "url" => "postgres://localhost/foo" } }
actual = klass.new(config).resolve
expected = { "production" =>
expected = { "default_env" =>
{ "adapter" => "postgresql",
"database" => "foo",
"host" => "localhost"
@ -148,9 +167,9 @@ module ActiveRecord
def test_merge_no_conflicts_with_database_url
ENV['DATABASE_URL'] = "postgres://localhost/foo"
config = {"production" => { "pool" => "5" } }
config = {"default_env" => { "pool" => "5" } }
actual = klass.new(config).resolve
expected = { "production" =>
expected = { "default_env" =>
{ "adapter" => "postgresql",
"database" => "foo",
"host" => "localhost",
@ -163,9 +182,9 @@ module ActiveRecord
def test_merge_conflicts_with_database_url
ENV['DATABASE_URL'] = "postgres://localhost/foo"
config = {"production" => { "adapter" => "NOT-POSTGRES", "database" => "NOT-FOO", "pool" => "5" } }
config = {"default_env" => { "adapter" => "NOT-POSTGRES", "database" => "NOT-FOO", "pool" => "5" } }
actual = klass.new(config).resolve
expected = { "production" =>
expected = { "default_env" =>
{ "adapter" => "postgresql",
"database" => "foo",
"host" => "localhost",

View File

@ -250,4 +250,40 @@ class EnumTest < ActiveRecord::TestCase
valid_book = klass.new(status: "written")
assert valid_book.valid?
end
test "enums are distinct per class" do
klass1 = Class.new(ActiveRecord::Base) do
self.table_name = "books"
enum status: [:proposed, :written]
end
klass2 = Class.new(ActiveRecord::Base) do
self.table_name = "books"
enum status: [:drafted, :uploaded]
end
book1 = klass1.proposed.create!
book1.status = :written
assert_equal ['proposed', 'written'], book1.status_change
book2 = klass2.drafted.create!
book2.status = :uploaded
assert_equal ['drafted', 'uploaded'], book2.status_change
end
test "enums are inheritable" do
subklass1 = Class.new(Book)
subklass2 = Class.new(Book) do
enum status: [:drafted, :uploaded]
end
book1 = subklass1.proposed.create!
book1.status = :written
assert_equal ['proposed', 'written'], book1.status_change
book2 = subklass2.drafted.create!
book2.status = :uploaded
assert_equal ['drafted', 'uploaded'], book2.status_change
end
end

View File

@ -35,6 +35,14 @@ module ActiveRecord
assert_no_column TestModel, :last_name
end
def test_add_column_without_limit
# TODO: limit: nil should work with all adapters.
skip "MySQL wrongly enforces a limit of 255" if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
add_column :test_models, :description, :string, limit: nil
TestModel.reset_column_information
assert_nil TestModel.columns_hash["description"].limit
end
if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
def test_unabstracted_database_dependent_types
add_column :test_models, :intelligence_quotient, :tinyint

View File

@ -63,7 +63,7 @@ class ReflectionTest < ActiveRecord::TestCase
def test_column_string_type_and_limit
assert_equal :string, @first.column_for_attribute("title").type
assert_equal 255, @first.column_for_attribute("title").limit
assert_equal 250, @first.column_for_attribute("title").limit
end
def test_column_null_not_null
@ -192,7 +192,7 @@ class ReflectionTest < ActiveRecord::TestCase
end
def test_reflection_should_not_raise_error_when_compared_to_other_object
assert_nothing_raised { Firm.reflections[:clients] == Object.new }
assert_nothing_raised { Firm.reflections['clients'] == Object.new }
end
def test_has_many_through_reflection

View File

@ -107,10 +107,18 @@ module ActiveRecord
end
test 'reverse_order!' do
assert relation.reverse_order!.equal?(relation)
assert relation.reverse_order_value
relation = Post.order('title ASC, comments_count DESC')
relation.reverse_order!
assert !relation.reverse_order_value
assert_equal 'title DESC', relation.order_values.first
assert_equal 'comments_count ASC', relation.order_values.last
relation.reverse_order!
assert_equal 'title ASC', relation.order_values.first
assert_equal 'comments_count DESC', relation.order_values.last
end
test 'create_with!' do

View File

@ -573,6 +573,12 @@ class RelationTest < ActiveRecord::TestCase
assert_equal expected, actual
end
def test_to_sql_on_scoped_proxy
auth = Author.first
Post.where("1=1").written_by(auth)
assert_not auth.posts.to_sql.include?("1=1")
end
def test_loading_with_one_association_with_non_preload
posts = Post.eager_load(:last_comment).order('comments.id DESC')
post = posts.find { |p| p.id == 1 }
@ -1418,6 +1424,18 @@ class RelationTest < ActiveRecord::TestCase
assert_equal [], scope.references_values
end
def test_order_with_reorder_nil_removes_the_order
relation = Post.order(:title).reorder(nil)
assert_nil relation.order_values.first
end
def test_reverse_order_with_reorder_nil_removes_the_order
relation = Post.order(:title).reverse_order.reorder(nil)
assert_nil relation.order_values.first
end
def test_presence
topics = Topic.all

View File

@ -0,0 +1,3 @@
class Column < ActiveRecord::Base
belongs_to :record
end

View File

@ -149,6 +149,10 @@ class Post < ActiveRecord::Base
ranked_by_comments.limit_by(limit)
end
def self.written_by(author)
where(id: author.posts.pluck(:id))
end
def self.reset_log
@log = []
end

View File

@ -0,0 +1,2 @@
class Record < ActiveRecord::Base
end

View File

@ -3,5 +3,5 @@ class Tag < ActiveRecord::Base
has_many :taggables, :through => :taggings
has_one :tagging
has_many :tagged_posts, :through => :taggings, :source => :taggable, :source_type => 'Post'
end
has_many :tagged_posts, :through => :taggings, :source => 'taggable', :source_type => 'Post'
end

View File

@ -170,6 +170,10 @@ ActiveRecord::Schema.define do
t.integer :references, null: false
end
create_table :columns, force: true do |t|
t.references :record
end
create_table :comments, force: true do |t|
t.integer :post_id, null: false
# use VARCHAR2(4000) instead of CLOB datatype as CLOB data type has many limitations in
@ -682,7 +686,7 @@ ActiveRecord::Schema.define do
end
create_table :topics, force: true do |t|
t.string :title
t.string :title, limit: 250
t.string :author_name
t.string :author_email_address
if mysql_56?
@ -828,6 +832,8 @@ ActiveRecord::Schema.define do
t.integer :department_id
end
create_table :records, force: true do |t|
end
except 'SQLite' do
# fk_test_has_fk should be before fk_test_has_pk

View File

@ -3,6 +3,40 @@
*Roderick van Domburg*
* Fixed `ActiveSupport::Duration#eql?` so that `1.second.eql?(1.second)` is
true.
This fixes the current situation of:
1.second.eql?(1.second) #=> false
`eql?` also requires that the other object is an `ActiveSupport::Duration`.
This requirement makes `ActiveSupport::Duration`'s behavior consistent with
the behavior of Ruby's numeric types:
1.eql?(1.0) #=> false
1.0.eql?(1) #=> false
1.second.eql?(1) #=> false (was true)
1.eql?(1.second) #=> false
{ 1 => "foo", 1.0 => "bar" }
#=> { 1 => "foo", 1.0 => "bar" }
{ 1 => "foo", 1.second => "bar" }
# now => { 1 => "foo", 1.second => "bar" }
# was => { 1 => "bar" }
And though the behavior of these hasn't changed, for reference:
1 == 1.0 #=> true
1.0 == 1 #=> true
1 == 1.second #=> true
1.second == 1 #=> true
*Emily Dobervich*
* `ActiveSupport::SafeBuffer#prepend` acts like `String#prepend` and modifies
instance in-place, returning self. `ActiveSupport::SafeBuffer#prepend!` is
deprecated.

View File

@ -1,5 +1,6 @@
require 'active_support/core_ext/object/duplicable'
require 'active_support/core_ext/string/inflections'
require 'active_support/per_thread_registry'
module ActiveSupport
module Cache

View File

@ -131,8 +131,6 @@ module ActiveSupport
end
end
private
def self.halting_and_conditional(next_callback, user_callback, user_conditions, halted_lambda, filter)
lambda { |env|
target = env.target
@ -149,6 +147,7 @@ module ActiveSupport
next_callback.call env
}
end
private_class_method :halting_and_conditional
def self.halting(next_callback, user_callback, halted_lambda, filter)
lambda { |env|
@ -166,6 +165,7 @@ module ActiveSupport
next_callback.call env
}
end
private_class_method :halting
def self.conditional(next_callback, user_callback, user_conditions)
lambda { |env|
@ -178,6 +178,7 @@ module ActiveSupport
next_callback.call env
}
end
private_class_method :conditional
def self.simple(next_callback, user_callback)
lambda { |env|
@ -185,6 +186,7 @@ module ActiveSupport
next_callback.call env
}
end
private_class_method :simple
end
class After
@ -208,8 +210,6 @@ module ActiveSupport
end
end
private
def self.halting_and_conditional(next_callback, user_callback, user_conditions)
lambda { |env|
env = next_callback.call env
@ -223,6 +223,7 @@ module ActiveSupport
env
}
end
private_class_method :halting_and_conditional
def self.halting(next_callback, user_callback)
lambda { |env|
@ -233,6 +234,7 @@ module ActiveSupport
env
}
end
private_class_method :halting
def self.conditional(next_callback, user_callback, user_conditions)
lambda { |env|
@ -246,6 +248,7 @@ module ActiveSupport
env
}
end
private_class_method :conditional
def self.simple(next_callback, user_callback)
lambda { |env|
@ -254,6 +257,7 @@ module ActiveSupport
env
}
end
private_class_method :simple
end
class Around
@ -269,8 +273,6 @@ module ActiveSupport
end
end
private
def self.halting_and_conditional(next_callback, user_callback, user_conditions)
lambda { |env|
target = env.target
@ -288,6 +290,7 @@ module ActiveSupport
end
}
end
private_class_method :halting_and_conditional
def self.halting(next_callback, user_callback)
lambda { |env|
@ -305,6 +308,7 @@ module ActiveSupport
end
}
end
private_class_method :halting
def self.conditional(next_callback, user_callback, user_conditions)
lambda { |env|
@ -322,6 +326,7 @@ module ActiveSupport
end
}
end
private_class_method :conditional
def self.simple(next_callback, user_callback)
lambda { |env|
@ -332,6 +337,7 @@ module ActiveSupport
env
}
end
private_class_method :simple
end
end

View File

@ -49,6 +49,10 @@ module ActiveSupport
end
end
def eql?(other)
other.is_a?(Duration) && self == other
end
def self.===(other) #:nodoc:
other.is_a?(Duration)
rescue ::NoMethodError

View File

@ -31,6 +31,13 @@ class DurationTest < ActiveSupport::TestCase
assert !(1.day == 'foo')
end
def test_eql
assert 1.minute.eql?(1.minute)
assert 2.days.eql?(48.hours)
assert !1.second.eql?(1)
assert !1.eql?(1.second)
end
def test_inspect
assert_equal '0 seconds', 0.seconds.inspect
assert_equal '1 month', 1.month.inspect

View File

@ -1,6 +1,9 @@
require 'abstract_unit'
require 'active_support/xml_mini'
require 'active_support/builder'
require 'active_support/core_ext/array'
require 'active_support/core_ext/hash'
require 'active_support/core_ext/big_decimal'
module XmlMiniTest
class RenameKeyTest < ActiveSupport::TestCase
@ -88,6 +91,61 @@ module XmlMiniTest
assert_xml "<b>Howdy</b>"
end
test "#to_tag should use the type value in the options hash" do
@xml.to_tag(:b, "blue", @options.merge(type: 'color'))
assert_xml( "<b type=\"color\">blue</b>" )
end
test "#to_tag accepts symbol types" do
@xml.to_tag(:b, :name, @options)
assert_xml( "<b type=\"symbol\">name</b>" )
end
test "#to_tag accepts boolean types" do
@xml.to_tag(:b, true, @options)
assert_xml( "<b type=\"boolean\">true</b>")
end
test "#to_tag accepts float types" do
@xml.to_tag(:b, 3.14, @options)
assert_xml( "<b type=\"float\">3.14</b>")
end
test "#to_tag accepts decimal types" do
@xml.to_tag(:b, ::BigDecimal.new("1.2"), @options)
assert_xml( "<b type=\"decimal\">1.2</b>")
end
test "#to_tag accepts date types" do
@xml.to_tag(:b, Date.new(2001,2,3), @options)
assert_xml( "<b type=\"date\">2001-02-03</b>")
end
test "#to_tag accepts datetime types" do
@xml.to_tag(:b, DateTime.new(2001,2,3,4,5,6,'+7'), @options)
assert_xml( "<b type=\"dateTime\">2001-02-03T04:05:06+07:00</b>")
end
test "#to_tag accepts time types" do
@xml.to_tag(:b, Time.new(1993, 02, 24, 12, 0, 0, "+09:00"), @options)
assert_xml( "<b type=\"dateTime\">1993-02-24T12:00:00+09:00</b>")
end
test "#to_tag accepts array types" do
@xml.to_tag(:b, ["first_name", "last_name"], @options)
assert_xml( "<b type=\"array\"><b>first_name</b><b>last_name</b></b>" )
end
test "#to_tag accepts hash types" do
@xml.to_tag(:b, { first_name: "Bob", last_name: "Marley" }, @options)
assert_xml( "<b><first-name>Bob</first-name><last-name>Marley</last-name></b>" )
end
test "#to_tag should not add type when skip types option is set" do
@xml.to_tag(:b, "Bob", @options.merge(skip_types: 1))
assert_xml( "<b>Bob</b>" )
end
test "#to_tag should dasherize the space when passed a string with spaces as a key" do
@xml.to_tag("New York", 33, @options)
assert_xml "<New---York type=\"integer\">33</New---York>"
@ -97,7 +155,6 @@ module XmlMiniTest
@xml.to_tag(:"New York", 33, @options)
assert_xml "<New---York type=\"integer\">33</New---York>"
end
# TODO: test the remaining functions hidden in #to_tag.
end
class WithBackendTest < ActiveSupport::TestCase

View File

@ -1,3 +1,7 @@
* Updates the maintenance policy to match the latest versions of Rails
*Matias Korhonen*
* Switched the order of `Applying a default scope` and `Merging of scopes` subsections so default scopes are introduced first.
*Alex Riabov*

View File

@ -245,7 +245,7 @@ When a file is referenced from a manifest or a helper, Sprockets searches the
three default asset locations for it.
The default locations are: the `images`, `javascripts` and `stylesheets`
directories under the `apps/assets` folder, but these subdirectories
directories under the `app/assets` folder, but these subdirectories
are not special - any path under `assets/*` will be searched.
For example, these files:
@ -581,23 +581,8 @@ runtime. To disable this behavior you can set:
config.assets.raise_runtime_errors = false
```
When `raise_runtime_errors` is set to `false` sprockets will not check that dependencies of assets are declared properly. Here is a scenario where you must tell the asset pipeline about a dependency:
If you have `application.css.erb` that references `logo.png` like this:
```css
#logo { background: url(<%= asset_data_uri 'logo.png' %>) }
```
Then you must declare that `logo.png` is a dependency of `application.css.erb`, so when the image gets re-compiled, the css file does as well. You can do this using the `//= depend_on_asset` declaration:
```css
//= depend_on_asset "logo.png"
#logo { background: url(<%= asset_data_uri 'logo.png' %>) }
```
Without this declaration you may experience strange behavior when pushing to production that is difficult to debug. When you have `raise_runtime_errors` set to `true`, dependencies will be checked at runtime so you can ensure that all dependencies are met.
When this option is true asset pipeline will check if all the assets loaded in your application
are included in the `config.assets.precompile` list.
### Turning Debugging Off
@ -943,7 +928,7 @@ gem.
```ruby
config.assets.css_compressor = :yui
```
The other option for compressing CSS if you have the sass-rails gem installed is
The other option for compressing CSS if you have the sass-rails gem installed is
```ruby
config.assets.css_compressor = :sass
@ -1018,7 +1003,7 @@ The X-Sendfile header is a directive to the web server to ignore the response
from the application, and instead serve a specified file from disk. This option
is off by default, but can be enabled if your server supports it. When enabled,
this passes responsibility for serving the file to the web server, which is
faster. Have a look at [send_file](http://api.rubyonrails.org/classes/ActionController/DataStreaming.html#method-i-send_file)
faster. Have a look at [send_file](http://api.rubyonrails.org/classes/ActionController/DataStreaming.html#method-i-send_file)
on how to use this feature.
Apache and nginx support this option, which can be enabled in

View File

@ -117,7 +117,7 @@ This command will install all dependencies except the MySQL and PostgreSQL Ruby
NOTE: If you would like to run the tests that use memcached, you need to ensure that you have it installed and running.
You can use homebrew to install memcached on OSX:
You can use [Homebrew](http://brew.sh/) to install memcached on OSX:
```bash
$ brew install memcached
@ -210,6 +210,14 @@ FreeBSD users will have to run the following:
# pkg_add -r postgresql92-client postgresql92-server
```
You can use [Homebrew](http://brew.sh/) to install MySQL and PostgreSQL on OSX:
```bash
$ brew install mysql
$ brew install postgresql
```
Follow instructions given by [Homebrew](http://brew.sh/) to start these.
Or install them through ports (they are located under the `databases` folder).
If you run into troubles during the installation of MySQL, please see
[the MySQL documentation](http://dev.mysql.com/doc/refman/5.1/en/freebsd-installation.html).
@ -245,10 +253,15 @@ $ bundle exec rake mysql:build_databases
```
PostgreSQL's authentication works differently. A simple way to set up the development environment for example is to run with your development account
This is not needed when installed via [Homebrew](http://brew.sh).
```bash
$ sudo -u postgres createuser --superuser $USER
```
And for OS X (when installed via [Homebrew](http://brew.sh))
```bash
$ createuser --superuser $USER
```
and then create the test databases with

View File

@ -166,6 +166,7 @@ is called.
COMMAND_WHITELIST = %(plugin generate destroy console server dbconsole application runner new version help)
def run_command!(command)
command = parse_command(command)
if COMMAND_WHITELIST.include?(command)
send(command)
else
@ -178,8 +179,7 @@ With the `server` command, Rails will further run the following code:
```ruby
def set_application_directory!
Dir.chdir(File.expand_path('../../', APP_PATH)) unless
File.exist?(File.expand_path("config.ru"))
Dir.chdir(File.expand_path('../../', APP_PATH)) unless File.exist?(File.expand_path("config.ru"))
end
def server
@ -187,6 +187,8 @@ def server
require_command!("server")
Rails::Server.new.tap do |server|
# We need to require application after the server sets environment,
# otherwise the --environment option given to the server won't propagate.
require APP_PATH
Dir.chdir(Rails.application.root)
server.start
@ -207,6 +209,7 @@ sets up the `Rails::Server` class.
require 'fileutils'
require 'optparse'
require 'action_dispatch'
require 'rails'
module Rails
class Server < ::Rack::Server
@ -273,7 +276,7 @@ def parse_options(args)
# http://www.meb.uni-bonn.de/docs/cgi/cl.html
args.clear if ENV.include?("REQUEST_METHOD")
options.merge! opt_parser.parse! args
options.merge! opt_parser.parse!(args)
options[:config] = ::File.expand_path(options[:config])
ENV["RACK_ENV"] = options[:environment]
options
@ -284,13 +287,16 @@ With the `default_options` set to this:
```ruby
def default_options
environment = ENV['RACK_ENV'] || 'development'
default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
{
environment: ENV['RACK_ENV'] || "development",
pid: nil,
Port: 9292,
Host: "0.0.0.0",
AccessLog: [],
config: "config.ru"
:environment => environment,
:pid => nil,
:Port => 9292,
:Host => default_host,
:AccessLog => [],
:config => "config.ru"
}
end
```
@ -348,6 +354,7 @@ private
def print_boot_information
...
puts "=> Run `rails server -h` for more startup options"
...
puts "=> Ctrl-C to shutdown server" unless options[:daemonize]
end
@ -434,7 +441,11 @@ The `app` method here is defined like so:
```ruby
def app
@app ||= begin
@app ||= options[:builder] ? build_app_from_string : build_app_and_options_from_config
end
...
private
def build_app_and_options_from_config
if !::File.exist? options[:config]
abort "configuration #{options[:config]} not found"
end
@ -443,7 +454,10 @@ def app
self.options.merge! options
app
end
end
def build_app_from_string
Rack::Builder.new_from_string(self.options[:builder])
end
```
The `options[:config]` value defaults to `config.ru` which contains this:
@ -459,8 +473,14 @@ run <%= app_const %>
The `Rack::Builder.parse_file` method here takes the content from this `config.ru` file and parses it using this code:
```ruby
app = eval "Rack::Builder.new {( " + cfgfile + "\n )}.to_app",
TOPLEVEL_BINDING, config
app = new_from_string cfgfile, config
...
def self.new_from_string(builder_script, file="(rackup)")
eval "Rack::Builder.new {\n" + builder_script + "\n}.to_app",
TOPLEVEL_BINDING, file, 0
end
```
The `initialize` method of `Rack::Builder` will take the block here and execute it within an instance of `Rack::Builder`. This is where the majority of the initialization process of Rails happens. The `require` line for `config/environment.rb` in `config.ru` is the first to run:
@ -473,11 +493,22 @@ require ::File.expand_path('../config/environment', __FILE__)
This file is the common file required by `config.ru` (`rails server`) and Passenger. This is where these two ways to run the server meet; everything before this point has been Rack and Rails setup.
This file begins with requiring `config/application.rb`.
This file begins with requiring `config/application.rb`:
```ruby
require File.expand_path('../application', __FILE__)
```
### `config/application.rb`
This file requires `config/boot.rb`, but only if it hasn't been required before, which would be the case in `rails server` but **wouldn't** be the case with Passenger.
This file requires `config/boot.rb`:
```ruby
require File.expand_path('../boot', __FILE__)
```
But only if it hasn't been required before, which would be the case in `rails server`
but **wouldn't** be the case with Passenger.
Then the fun begins!
@ -498,11 +529,12 @@ This file is responsible for requiring all the individual frameworks of Rails:
require "rails"
%w(
active_record
action_controller
action_mailer
rails/test_unit
sprockets
active_record
action_controller
action_view
action_mailer
rails/test_unit
sprockets
).each do |framework|
begin
require "#{framework}/railtie"
@ -568,7 +600,7 @@ initializers (like building the middleware stack) are run last. The `railtie`
initializers are the initializers which have been defined on the `Rails::Application`
itself and are run between the `bootstrap` and `finishers`.
After this is done we go back to `Rack::Server`
After this is done we go back to `Rack::Server`.
### Rack: lib/rack/server.rb
@ -576,7 +608,11 @@ Last time we left when the `app` method was being defined:
```ruby
def app
@app ||= begin
@app ||= options[:builder] ? build_app_from_string : build_app_and_options_from_config
end
...
private
def build_app_and_options_from_config
if !::File.exist? options[:config]
abort "configuration #{options[:config]} not found"
end
@ -585,7 +621,10 @@ def app
self.options.merge! options
app
end
end
def build_app_from_string
Rack::Builder.new_from_string(self.options[:builder])
end
```
At this point `app` is the Rails app itself (a middleware), and what
@ -611,40 +650,50 @@ server.run wrapped_app, options, &blk
```
At this point, the implementation of `server.run` will depend on the
server you're using. For example, if you were using Mongrel, here's what
server you're using. For example, if you were using Puma, here's what
the `run` method would look like:
```ruby
def self.run(app, options={})
server = ::Mongrel::HttpServer.new(
options[:Host] || '0.0.0.0',
options[:Port] || 8080,
options[:num_processors] || 950,
options[:throttle] || 0,
options[:timeout] || 60)
# Acts like Rack::URLMap, utilizing Mongrel's own path finding methods.
# Use is similar to #run, replacing the app argument with a hash of
# { path=>app, ... } or an instance of Rack::URLMap.
if options[:map]
if app.is_a? Hash
app.each do |path, appl|
path = '/'+path unless path[0] == ?/
server.register(path, Rack::Handler::Mongrel.new(appl))
end
elsif app.is_a? URLMap
app.instance_variable_get(:@mapping).each do |(host, path, appl)|
next if !host.nil? && !options[:Host].nil? && options[:Host] != host
path = '/'+path unless path[0] == ?/
server.register(path, Rack::Handler::Mongrel.new(appl))
end
else
raise ArgumentError, "first argument should be a Hash or URLMap"
end
else
server.register('/', Rack::Handler::Mongrel.new(app))
...
DEFAULT_OPTIONS = {
:Host => '0.0.0.0',
:Port => 8080,
:Threads => '0:16',
:Verbose => false
}
def self.run(app, options = {})
options = DEFAULT_OPTIONS.merge(options)
if options[:Verbose]
app = Rack::CommonLogger.new(app, STDOUT)
end
if options[:environment]
ENV['RACK_ENV'] = options[:environment].to_s
end
server = ::Puma::Server.new(app)
min, max = options[:Threads].split(':', 2)
puts "Puma #{::Puma::Const::PUMA_VERSION} starting..."
puts "* Min threads: #{min}, max threads: #{max}"
puts "* Environment: #{ENV['RACK_ENV']}"
puts "* Listening on tcp://#{options[:Host]}:#{options[:Port]}"
server.add_tcp_listener options[:Host], options[:Port]
server.min_threads = min
server.max_threads = max
yield server if block_given?
server.run.join
begin
server.run.join
rescue Interrupt
puts "* Gracefully stopping, waiting for requests to finish"
server.stop(true)
puts "* Goodbye!"
end
end
```
@ -654,4 +703,4 @@ the last piece of our journey in the Rails initialization process.
This high level overview will help you understand when your code is
executed and how, and overall become a better Rails developer. If you
still want to know more, the Rails source code itself is probably the
best place to go next.
best place to go next.

View File

@ -20,7 +20,7 @@ Only the latest release series will receive bug fixes. When enough bugs are
fixed and its deemed worthy to release a new gem, this is the branch it happens
from.
**Currently included series:** 4.0.z
**Currently included series:** 4.1.z, 4.0.z
Security Issues
---------------
@ -35,7 +35,7 @@ be built from 1.2.2, and then added to the end of 1-2-stable. This means that
security releases are easy to upgrade to if you're running the latest version
of Rails.
**Currently included series:** 4.0.z, 3.2.z
**Currently included series:** 4.1.z, 4.0.z
Severe Security Issues
----------------------
@ -44,7 +44,7 @@ For severe security issues we will provide new versions as above, and also the
last major release series will receive patches and new versions. The
classification of the security issue is judged by the core team.
**Currently included series:** 4.0.z, 3.2.z
**Currently included series:** 4.1.z, 4.0.z, 3.2.z
Unsupported Release Series
--------------------------

View File

@ -1003,7 +1003,7 @@ _'1; mode=block' in Rails by default_ - use XSS Auditor and block page if XSS at
* X-Content-Type-Options
_'nosniff' in Rails by default_ - stops the browser from guessing the MIME type of a file.
* X-Content-Security-Policy
[A powerful mechanism for controlling which sites certain content types can be loaded from](http://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html)
[A powerful mechanism for controlling which sites certain content types can be loaded from](http://w3c.github.io/webappsec/specs/content-security-policy/csp-specification.dev.html)
* Access-Control-Allow-Origin
Used to control which sites are allowed to bypass same origin policies and send cross-origin requests.
* Strict-Transport-Security

View File

@ -25,8 +25,6 @@ TIP: Ruby 1.8.7 p248 and p249 have marshaling bugs that crash Rails. Ruby Enterp
Upgrading from Rails 4.0 to Rails 4.1
-------------------------------------
NOTE: This section is a work in progress.
### CSRF protection from remote `<script>` tags
Or, "whaaat my tests are failing!!!?"
@ -79,12 +77,15 @@ secrets, you need to:
secret_key_base:
production:
secret_key_base:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
```
2. Copy the existing `secret_key_base` from the `secret_token.rb` initializer to
`secrets.yml` under the `production` section.
2. Use your existing `secret_key_base` from the `secret_token.rb` initializer to
set the SECRET_KEY_BASE environment variable for whichever users run the Rails
app in production mode. Alternately, you can simply copy the existing
`secret_key_base` from the `secret_token.rb` initializer to `secrets.yml`
under the `production` section, replacing '<%= ENV["SECRET_KEY_BASE"] %>'.
3. Remove the `secret_token.rb` initializer.
4. Use `rake secret` to generate new keys for the `development` and `test` sections.
@ -463,7 +464,7 @@ being used, you can update your form to use the `PUT` method instead:
<%= form_for [ :update_name, @user ], method: :put do |f| %>
```
For more on PATCH and why this change was made, see [this post](http://weblog.rubyonrails.org/2012/2/26/edge-rails-patch-is-the-new-primary-http-method-for-updates/)
For more on PATCH and why this change was made, see [this post](http://weblog.rubyonrails.org/2012/2/25/edge-rails-patch-is-the-new-primary-http-method-for-updates/)
on the Rails blog.
#### A note about media types

View File

@ -27,5 +27,5 @@ Gem::Specification.new do |s|
s.add_dependency 'railties', version
s.add_dependency 'bundler', '>= 1.3.0', '< 2.0'
s.add_dependency 'sprockets-rails', '~> 2.0.0'
s.add_dependency 'sprockets-rails', '~> 2.1'
end

View File

@ -87,7 +87,7 @@ module Rails
class << self
def inherited(base)
super
Rails.application ||= base.instance
base.instance
end
# Makes the +new+ method public.
@ -117,6 +117,8 @@ module Rails
@railties = nil
@message_verifiers = {}
Rails.application ||= self
add_lib_to_load_path!
ActiveSupport.run_load_hooks(:before_configuration, self)
@ -151,14 +153,13 @@ module Rails
def key_generator
# number of iterations selected based on consultation with the google security
# team. Details at https://github.com/rails/rails/pull/6952#issuecomment-7661220
@caching_key_generator ||= begin
@caching_key_generator ||=
if secrets.secret_key_base
key_generator = ActiveSupport::KeyGenerator.new(secrets.secret_key_base, iterations: 1000)
ActiveSupport::CachingKeyGenerator.new(key_generator)
else
ActiveSupport::LegacyKeyGenerator.new(config.secret_token)
end
end
end
# Returns a message verifier object.

View File

@ -249,7 +249,7 @@ module Rails
'Use SCSS for stylesheets')
else
gems << GemfileEntry.version('sass-rails',
'~> 4.0.2',
'~> 4.0.3',
'Use SCSS for stylesheets')
end

View File

@ -4,8 +4,8 @@
<h2><%%= pluralize(@<%= singular_table_name %>.errors.count, "error") %> prohibited this <%= singular_table_name %> from being saved:</h2>
<ul>
<%% @<%= singular_table_name %>.errors.full_messages.each do |msg| %>
<li><%%= msg %></li>
<%% @<%= singular_table_name %>.errors.full_messages.each do |message| %>
<li><%%= message %></li>
<%% end %>
</ul>
</div>

View File

@ -23,7 +23,27 @@ test:
<<: *default
database: <%= app_name %>_test
# Do not keep production credentials in the repository,
# instead read the configuration from the environment.
# As with config/secrets.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password as a unix environment variable when you boot
# the app. Read http://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full rundown on how to provide these environment variables in a
# production deployment.
#
# On Heroku and other platform providers, you may have a full connection URL
# available as an environment variable. For example:
#
# DATABASE_URL="frontbase://myuser:mypass@localhost/somedatabase"
#
# You can use this database configuration with:
#
# production:
# url: <%%= ENV['DATABASE_URL'] %>
#
production:
url: <%%= ENV["DATABASE_URL"] %>
<<: *default
database: <%= app_name %>_production
username: <%= app_name %>
password: <%%= ENV['<%= app_name.upcase %>_DATABASE_PASSWORD'] %>

View File

@ -61,7 +61,27 @@ test:
<<: *default
database: <%= app_name[0,4] %>_tst
# Do not keep production credentials in the repository,
# instead read the configuration from the environment.
# As with config/secrets.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password as a unix environment variable when you boot
# the app. Read http://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full rundown on how to provide these environment variables in a
# production deployment.
#
# On Heroku and other platform providers, you may have a full connection URL
# available as an environment variable. For example:
#
# DATABASE_URL="ibm-db://myuser:mypass@localhost/somedatabase"
#
# You can use this database configuration with:
#
# production:
# url: <%%= ENV['DATABASE_URL'] %>
#
production:
url: <%%= ENV["DATABASE_URL"] %>
<<: *default
database: <%= app_name %>_production
username: <%= app_name %>
password: <%%= ENV['<%= app_name.upcase %>_DATABASE_PASSWORD'] %>

View File

@ -53,7 +53,16 @@ test:
<<: *default
url: jdbc:db://localhost/<%= app_name %>_test
# Do not keep production credentials in the repository,
# instead read the configuration from the environment.
# As with config/secrets.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password as a unix environment variable when you boot
# the app. Read http://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full rundown on how to provide these environment variables in a
# production deployment.
#
production:
url: <%%= ENV["DATABASE_URL"] %>
url: jdbc:db://localhost/<%= app_name %>_production
username: <%= app_name %>
password: <%%= ENV['<%= app_name.upcase %>_DATABASE_PASSWORD'] %>

View File

@ -26,6 +26,27 @@ test:
<<: *default
database: <%= app_name %>_test
# Do not keep production credentials in the repository,
# instead read the configuration from the environment.
production: <%%= ENV["DATABASE_URL"] %>
# As with config/secrets.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password as a unix environment variable when you boot
# the app. Read http://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full rundown on how to provide these environment variables in a
# production deployment.
#
# On Heroku and other platform providers, you may have a full connection URL
# available as an environment variable. For example:
#
# DATABASE_URL="mysql://myuser:mypass@localhost/somedatabase"
#
# You can use this database configuration with:
#
# production:
# url: <%%= ENV['DATABASE_URL'] %>
#
production:
<<: *default
database: <%= app_name %>_production
username: <%= app_name %>
password: <%%= ENV['<%= app_name.upcase %>_DATABASE_PASSWORD'] %>

View File

@ -42,7 +42,27 @@ test:
<<: *default
database: <%= app_name %>_test
# Do not keep production credentials in the repository,
# instead read the configuration from the environment.
# As with config/secrets.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password as a unix environment variable when you boot
# the app. Read http://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full rundown on how to provide these environment variables in a
# production deployment.
#
# On Heroku and other platform providers, you may have a full connection URL
# available as an environment variable. For example:
#
# DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase"
#
# You can use this database configuration with:
#
# production:
# url: <%%= ENV['DATABASE_URL'] %>
#
production:
url: <%%= ENV["DATABASE_URL"] %>
<<: *default
database: <%= app_name %>_production
username: <%= app_name %>
password: <%%= ENV['<%= app_name.upcase %>_DATABASE_PASSWORD'] %>

View File

@ -18,7 +18,6 @@ test:
<<: *default
database: db/test.sqlite3
# Do not keep production credentials in the repository,
# instead read the configuration from the environment.
production:
url: <%%= ENV["DATABASE_URL"] %>
<<: *default
database: db/production.sqlite3

View File

@ -32,11 +32,27 @@ test:
<<: *default
database: <%= app_name %>_test
# Avoid production credentials in the repository,
# instead read the configuration from the environment.
# As with config/secrets.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Example:
# mysql2://myuser:mypass@localhost/somedatabase
# Instead, provide the password as a unix environment variable when you boot
# the app. Read http://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full rundown on how to provide these environment variables in a
# production deployment.
#
# On Heroku and other platform providers, you may have a full connection URL
# available as an environment variable. For example:
#
# DATABASE_URL="mysql2://myuser:mypass@localhost/somedatabase"
#
# You can use this database configuration with:
#
# production:
# url: <%%= ENV['DATABASE_URL'] %>
#
production:
url: <%%= ENV["DATABASE_URL"] %>
<<: *default
database: <%= app_name %>_production
username: <%= app_name %>
password: <%%= ENV['<%= app_name.upcase %>_DATABASE_PASSWORD'] %>

View File

@ -32,7 +32,27 @@ test:
<<: *default
database: <%= app_name %>_test
# Do not keep production credentials in the repository,
# instead read the configuration from the environment.
# As with config/secrets.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password as a unix environment variable when you boot
# the app. Read http://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full rundown on how to provide these environment variables in a
# production deployment.
#
# On Heroku and other platform providers, you may have a full connection URL
# available as an environment variable. For example:
#
# DATABASE_URL="oracle://myuser:mypass@localhost/somedatabase"
#
# You can use this database configuration with:
#
# production:
# url: <%%= ENV['DATABASE_URL'] %>
#
production:
url: <%%= ENV["DATABASE_URL"] %>
<<: *default
database: <%= app_name %>_production
username: <%= app_name %>
password: <%%= ENV['<%= app_name.upcase %>_DATABASE_PASSWORD'] %>

View File

@ -59,11 +59,27 @@ test:
<<: *default
database: <%= app_name %>_test
# Do not keep production credentials in the repository,
# instead read the configuration from the environment.
# As with config/secrets.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Example:
# postgres://myuser:mypass@localhost/somedatabase
# Instead, provide the password as a unix environment variable when you boot
# the app. Read http://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full rundown on how to provide these environment variables in a
# production deployment.
#
# On Heroku and other platform providers, you may have a full connection URL
# available as an environment variable. For example:
#
# DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase"
#
# You can use this database configuration with:
#
# production:
# url: <%%= ENV['DATABASE_URL'] %>
#
production:
url: <%%= ENV["DATABASE_URL"] %>
<<: *default
database: <%= app_name %>_production
username: <%= app_name %>
password: <%%= ENV['<%= app_name.upcase %>_DATABASE_PASSWORD'] %>

View File

@ -20,13 +20,6 @@ test:
<<: *default
database: db/test.sqlite3
# Do not keep production credentials in the repository,
# instead read the configuration from the environment.
#
# Examples:
# sqlite3::memory:
# sqlite3:db/production.sqlite3
# sqlite3:/full/path/to/database.sqlite3
#
production:
url: <%%= ENV["DATABASE_URL"] %>
<<: *default
database: db/production.sqlite3

View File

@ -42,7 +42,27 @@ test:
<<: *default
database: <%= app_name %>_test
# Do not keep production credentials in the repository,
# instead read the configuration from the environment.
# As with config/secrets.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password as a unix environment variable when you boot
# the app. Read http://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full rundown on how to provide these environment variables in a
# production deployment.
#
# On Heroku and other platform providers, you may have a full connection URL
# available as an environment variable. For example:
#
# DATABASE_URL="sqlserver://myuser:mypass@localhost/somedatabase"
#
# You can use this database configuration with:
#
# production:
# url: <%%= ENV['DATABASE_URL'] %>
#
production:
url: <%%= ENV["DATABASE_URL"] %>
<<: *default
database: <%= app_name %>_production
username: <%= app_name %>
password: <%%= ENV['<%= app_name.upcase %>_DATABASE_PASSWORD'] %>

View File

@ -1,3 +1,3 @@
# Be sure to restart your server when you modify this file.
Rails.application.config.action_dispatch.cookies_serializer = :json
Rails.application.config.action_dispatch.cookies_serializer = :json

View File

@ -2,4 +2,3 @@
# Add new mime types for use in respond_to blocks:
# Mime::Type.register "text/richtext", :rtf
# Mime::Type.register_alias "text/html", :iphone

View File

@ -31,7 +31,7 @@ class <%= controller_class_name %>Controller < ApplicationController
if @<%= orm_instance.save %>
redirect_to @<%= singular_table_name %>, notice: <%= "'#{human_name} was successfully created.'" %>
else
render action: 'new'
render :new
end
end
@ -40,7 +40,7 @@ class <%= controller_class_name %>Controller < ApplicationController
if @<%= orm_instance.update("#{singular_table_name}_params") %>
redirect_to @<%= singular_table_name %>, notice: <%= "'#{human_name} was successfully updated.'" %>
else
render action: 'edit'
render :edit
end
end

View File

@ -4,6 +4,7 @@ abort("Abort testing: Your Rails environment is running in production mode!") if
require 'active_support/testing/autorun'
require 'active_support/test_case'
require 'action_controller'
require 'action_controller/test_case'
require 'action_dispatch/testing/integration'
require 'rails/generators/test_case'

View File

@ -199,6 +199,7 @@ module ApplicationTests
end
test "precompile creates a manifest file with all the assets listed" do
app_file "app/assets/images/rails.png", "notactuallyapng"
app_file "app/assets/stylesheets/application.css.erb", "<%= asset_path('rails.png') %>"
app_file "app/assets/javascripts/application.js", "alert();"
# digest is default in false, we must enable it for test environment
@ -260,7 +261,7 @@ module ApplicationTests
test "precompile shouldn't use the digests present in manifest.json" do
app_file "app/assets/images/rails.png", "notactuallyapng"
app_file "app/assets/stylesheets/application.css.erb", "//= depend_on rails.png\np { url: <%= asset_path('rails.png') %> }"
app_file "app/assets/stylesheets/application.css.erb", "p { url: <%= asset_path('rails.png') %> }"
ENV["RAILS_ENV"] = "production"
precompile!
@ -448,23 +449,23 @@ module ApplicationTests
test "asset urls should be protocol-relative if no request is in scope" do
app_file "app/assets/images/rails.png", "notreallyapng"
app_file "app/assets/javascripts/image_loader.js.erb", 'var src="<%= image_path("rails.png") %>";'
app_file "app/assets/javascripts/image_loader.js.erb", "var src='<%= image_path('rails.png') %>';"
add_to_config "config.assets.precompile = %w{image_loader.js}"
add_to_config "config.asset_host = 'example.com'"
precompile!
assert_match 'src="//example.com/assets/rails.png"', File.read(Dir["#{app_path}/public/assets/image_loader-*.js"].first)
assert_match "src='//example.com/assets/rails.png'", File.read(Dir["#{app_path}/public/assets/image_loader-*.js"].first)
end
test "asset paths should use RAILS_RELATIVE_URL_ROOT by default" do
ENV["RAILS_RELATIVE_URL_ROOT"] = "/sub/uri"
app_file "app/assets/images/rails.png", "notreallyapng"
app_file "app/assets/javascripts/app.js.erb", 'var src="<%= image_path("rails.png") %>";'
app_file "app/assets/javascripts/app.js.erb", "var src='<%= image_path('rails.png') %>';"
add_to_config "config.assets.precompile = %w{app.js}"
precompile!
assert_match 'src="/sub/uri/assets/rails.png"', File.read(Dir["#{app_path}/public/assets/app-*.js"].first)
assert_match "src='/sub/uri/assets/rails.png'", File.read(Dir["#{app_path}/public/assets/app-*.js"].first)
end
test "assets:cache:clean should clean cache" do

View File

@ -21,6 +21,12 @@ module ApplicationTests
assert_equal Rails.application.config.secret_key_base, clone.config.secret_key_base, "The base secret key on the config should be the same"
end
def test_inheriting_multiple_times_from_application
new_application_class = Class.new(Rails::Application)
assert_not_equal Rails.application.object_id, new_application_class.instance.object_id
end
def test_initialization_of_multiple_copies_of_same_application
application1 = AppTemplate::Application.new
application2 = AppTemplate::Application.new

View File

@ -160,13 +160,6 @@ class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase
Unknown::Generators.send :remove_const, :ActiveModel
end
def test_new_hash_style
run_generator
assert_file "app/controllers/users_controller.rb" do |content|
assert_match(/render action: 'new'/, content)
end
end
def test_model_name_option
run_generator ["Admin::User", "--model-name=User"]
assert_file "app/controllers/admin/users_controller.rb" do |content|

View File

@ -72,6 +72,14 @@ module RailtiesTest
assert $to_prepare
end
test "railtie have access to application in before_configuration callbacks" do
$after_initialize = false
class Foo < Rails::Railtie ; config.before_configuration { $before_configuration = Rails.root.to_path } ; end
assert_not $before_configuration
require "#{app_path}/config/environment"
assert_equal app_path, $before_configuration
end
test "railtie can add after_initialize callbacks" do
$after_initialize = false
class Foo < Rails::Railtie ; config.after_initialize { $after_initialize = true } ; end