提交 085ce4f1 编写于 作者: R Rafael Mendonça França

Merge branch 'master' into rm-uuid-fixtures

Conflicts:
	activerecord/CHANGELOG.md
	activesupport/CHANGELOG.md
services: memcache
script: 'ci/travis.rb'
before_install:
- travis_retry gem install bundler
......
......@@ -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)
......
......@@ -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
......
......@@ -32,11 +32,14 @@ def call(env)
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
......
......@@ -210,20 +210,29 @@ def test_redirect_to_with_other_flashes
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
......
......@@ -196,6 +196,13 @@ def test_redirect_to_host_and_port
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"
......
......@@ -53,7 +53,7 @@ module ClassMethods
#
# 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>).
......
......@@ -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:
......
......@@ -134,11 +134,11 @@ def build(attributes = {}, &block)
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 @@ def transaction(*args)
#
# 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 @@ def merge_target_lists(persisted, memory)
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|
......
......@@ -357,7 +357,7 @@ def replace(other_array)
# 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 @@ def replace(other_array)
# # ]
#
# 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 @@ def include?(record)
!!@association.include?(record)
end
def arel
scope.arel
end
def proxy_association
@association
end
......
......@@ -18,11 +18,11 @@ def writer(record)
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 @@ def set_new_record(record)
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
......
......@@ -79,11 +79,11 @@ def save_changed_attribute(attr, value)
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
......
......@@ -302,11 +302,11 @@ def create_or_update #:nodoc:
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
......
......@@ -33,7 +33,7 @@ class ConnectionUrlResolver # :nodoc:
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 @@ def resolve_string_connection(spec)
# 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
......
......@@ -4,14 +4,14 @@ class PostgreSQLAdapter < AbstractAdapter
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.
......
......@@ -209,7 +209,7 @@ class Table < ActiveRecord::ConnectionAdapters::Table
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" },
......
......@@ -63,7 +63,7 @@ class SQLite3Adapter < AbstractAdapter
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" },
......
......@@ -58,9 +58,9 @@ def establish_connection(spec = nil)
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 @@ def resolve
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
......
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 @@ def enum(definitions)
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 @@ def _enum_methods_module
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]
......
......@@ -66,7 +66,7 @@ def increment_lock
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?
......
......@@ -484,24 +484,24 @@ def relation_for_destroy
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
......
......@@ -22,11 +22,11 @@ def self.create(macro, name, scope, options, ar)
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 @@ def reflect_on_all_aggregations
# 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 @@ def reflect_on_all_associations(macro = nil)
# 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 @@ def association_primary_key(klass = nil)
# # => [: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:
......
......@@ -70,7 +70,7 @@ def insert(values) # :nodoc:
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)
......
......@@ -231,7 +231,7 @@ def operation_over_aggregate_column(column, operation, distinct)
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
......
......@@ -139,7 +139,6 @@ def merge_multi_values
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])
......
......@@ -825,7 +825,9 @@ def reverse_order
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 @@ def symbol_unscoping(scope)
case scope
when :order
self.reverse_order_value = false
result = []
else
result = [] unless single_val_method
......@@ -1031,7 +1032,6 @@ def array_of_strings?(o)
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
......
......@@ -43,7 +43,7 @@ def initialize_dup(other) # :nodoc:
private
def create_record
def _create_record
if self.record_timestamps
current_time = current_time_from_proper_timezone
......@@ -57,7 +57,7 @@ def create_record
super
end
def update_record(*args)
def _update_record(*args)
if should_record_timestamps?
current_time = current_time_from_proper_timezone
......
......@@ -93,7 +93,7 @@ def deserialize_attribute(record, attribute, value)
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
......
......@@ -25,7 +25,7 @@ def setup
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?
......
......@@ -70,6 +70,23 @@ def test_write_value
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)
......
......@@ -16,6 +16,8 @@
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 @@ def test_reflect_the_most_recent_change
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
......@@ -387,6 +387,20 @@ def test_count_with_too_many_parameters_raises
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)
......
......@@ -25,35 +25,45 @@ def spec(spec, config)
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_unknown_symbol_key
def test_resolver_with_database_uri_and_known_key
ENV['DATABASE_URL'] = "postgres://localhost/foo"
config = { "not_production" => { "adapter" => "not_postgres", "database" => "not_foo" } }
config = { "production" => { "adapter" => "not_postgres", "database" => "not_foo", "host" => "localhost" } }
actual = resolve(:production, config)
expected = { "adapter"=>"postgresql", "database"=>"foo", "host"=>"localhost" }
expected = { "adapter"=>"not_postgres", "database"=>"not_foo", "host"=>"localhost" }
assert_equal expected, actual
end
def test_resolver_with_database_uri_and_unknown_string_key
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" } }
assert_raises AdapterNotSpecified do
spec("production", config)
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_deprecated do
assert_raises AdapterNotSpecified do
spec("production", config)
end
end
end
......@@ -73,16 +83,24 @@ def test_jdbc_url
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 @@ def test_string_connection
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 @@ def test_blank_with_database_url
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 @@ def test_blank_with_database_url
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 @@ def test_url_sub_key_with_database_url
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 @@ def test_merge_no_conflicts_with_database_url
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",
......
......@@ -250,4 +250,40 @@ def self.name; 'Book'; end
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
......@@ -35,6 +35,14 @@ def test_add_remove_single_field_using_symbol_arguments
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
......
......@@ -63,7 +63,7 @@ def test_content_columns
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 @@ def test_association_reflection_in_modules
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
......
......@@ -107,10 +107,18 @@ def relation
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_equal 'title DESC', relation.order_values.first
assert_equal 'comments_count ASC', relation.order_values.last
relation.reverse_order!
assert !relation.reverse_order_value
assert_equal 'title ASC', relation.order_values.first
assert_equal 'comments_count DESC', relation.order_values.last
end
test 'create_with!' do
......
......@@ -573,6 +573,12 @@ def test_to_sql_on_eager_join
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 @@ def test_automatically_added_reorder_references
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
......
class Column < ActiveRecord::Base
belongs_to :record
end
......@@ -149,6 +149,10 @@ def self.top(limit)
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
......
class Record < ActiveRecord::Base
end
......@@ -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
\ No newline at end of file
has_many :tagged_posts, :through => :taggings, :source => 'taggable', :source_type => 'Post'
end
......@@ -170,6 +170,10 @@ def create_table(*args, &block)
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 @@ def create_table(*args, &block)
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 @@ def create_table(*args, &block)
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
......
......@@ -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.
......
require 'active_support/core_ext/object/duplicable'
require 'active_support/core_ext/string/inflections'
require 'active_support/per_thread_registry'
module ActiveSupport
module Cache
......
......@@ -131,8 +131,6 @@ def self.build(next_callback, user_callback, user_conditions, chain_config, filt
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 @@ def self.halting_and_conditional(next_callback, user_callback, user_conditions,
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 @@ def self.halting(next_callback, user_callback, halted_lambda, filter)
next_callback.call env
}
end
private_class_method :halting
def self.conditional(next_callback, user_callback, user_conditions)
lambda { |env|
......@@ -178,6 +178,7 @@ def self.conditional(next_callback, user_callback, user_conditions)
next_callback.call env
}
end
private_class_method :conditional
def self.simple(next_callback, user_callback)
lambda { |env|
......@@ -185,6 +186,7 @@ def self.simple(next_callback, user_callback)
next_callback.call env
}
end
private_class_method :simple
end
class After
......@@ -208,8 +210,6 @@ def self.build(next_callback, user_callback, user_conditions, chain_config)
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 @@ def self.halting_and_conditional(next_callback, user_callback, user_conditions)
env
}
end
private_class_method :halting_and_conditional
def self.halting(next_callback, user_callback)
lambda { |env|
......@@ -233,6 +234,7 @@ def self.halting(next_callback, user_callback)
env
}
end
private_class_method :halting
def self.conditional(next_callback, user_callback, user_conditions)
lambda { |env|
......@@ -246,6 +248,7 @@ def self.conditional(next_callback, user_callback, user_conditions)
env
}
end
private_class_method :conditional
def self.simple(next_callback, user_callback)
lambda { |env|
......@@ -254,6 +257,7 @@ def self.simple(next_callback, user_callback)
env
}
end
private_class_method :simple
end
class Around
......@@ -269,8 +273,6 @@ def self.build(next_callback, user_callback, user_conditions, chain_config)
end
end
private
def self.halting_and_conditional(next_callback, user_callback, user_conditions)
lambda { |env|
target = env.target
......@@ -288,6 +290,7 @@ def self.halting_and_conditional(next_callback, user_callback, user_conditions)
end
}
end
private_class_method :halting_and_conditional
def self.halting(next_callback, user_callback)
lambda { |env|
......@@ -305,6 +308,7 @@ def self.halting(next_callback, user_callback)
end
}
end
private_class_method :halting
def self.conditional(next_callback, user_callback, user_conditions)
lambda { |env|
......@@ -322,6 +326,7 @@ def self.conditional(next_callback, user_callback, user_conditions)
end
}
end
private_class_method :conditional
def self.simple(next_callback, user_callback)
lambda { |env|
......@@ -332,6 +337,7 @@ def self.simple(next_callback, user_callback)
env
}
end
private_class_method :simple
end
end
......
......@@ -49,6 +49,10 @@ def ==(other)
end
end
def eql?(other)
other.is_a?(Duration) && self == other
end
def self.===(other) #:nodoc:
other.is_a?(Duration)
rescue ::NoMethodError
......
......@@ -31,6 +31,13 @@ def test_equals
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
......
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 @@ def to_xml(options) options[:builder].yo(options[:root].to_s) end
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 @@ def to_xml(options) options[:builder].yo(options[:root].to_s) end
@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
......
* 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*
......
......@@ -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
......
......@@ -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
......
......@@ -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.
\ No newline at end of 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
--------------------------
......
......@@ -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
......
......@@ -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
......
......@@ -27,5 +27,5 @@
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
......@@ -87,7 +87,7 @@ class Application < Engine
class << self
def inherited(base)
super
Rails.application ||= base.instance
base.instance
end
# Makes the +new+ method public.
......@@ -117,6 +117,8 @@ def initialize(initial_variable_values = {}, &block)
@railties = nil
@message_verifiers = {}
Rails.application ||= self
add_lib_to_load_path!
ActiveSupport.run_load_hooks(:before_configuration, self)
......@@ -151,14 +153,13 @@ def reload_routes!
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.
......
......@@ -249,7 +249,7 @@ def assets_gemfile_entry
'Use SCSS for stylesheets')
else
gems << GemfileEntry.version('sass-rails',
'~> 4.0.2',
'~> 4.0.3',
'Use SCSS for stylesheets')
end
......
......@@ -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>
......
......@@ -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'] %>
......@@ -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'] %>
......@@ -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'] %>
......@@ -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'] %>
......@@ -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'] %>
......@@ -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
......@@ -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'] %>
......@@ -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'] %>
......@@ -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'] %>
......@@ -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
......@@ -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'] %>
# Be sure to restart your server when you modify this file.
Rails.application.config.action_dispatch.cookies_serializer = :json
\ No newline at end of file
Rails.application.config.action_dispatch.cookies_serializer = :json
......@@ -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
......@@ -31,7 +31,7 @@ def create
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 @@ def update
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
......
......@@ -4,6 +4,7 @@
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'
......
......@@ -199,6 +199,7 @@ class User < ActiveRecord::Base; raise 'should not be reached'; end
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 @@ class User < ActiveRecord::Base; raise 'should not be reached'; end
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 @@ class ::PostsController < ActionController::Base; end
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
......
......@@ -21,6 +21,12 @@ def test_cloning_an_application_makes_a_shallow_copy_of_config
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
......
......@@ -160,13 +160,6 @@ def self.all(klass)
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|
......
......@@ -72,6 +72,14 @@ class Foo < Rails::Railtie ; config.to_prepare { $to_prepare = true } ; end
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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册