Permalink
Browse files

Merge branch 'master' into rm-uuid-fixtures

Conflicts:
	activerecord/CHANGELOG.md
	activesupport/CHANGELOG.md
  • Loading branch information...
2 parents 54d8c81 + 53610e5 commit 085ce4f1411238a6109fb9c22fdb2c46b27c2c0e @rafaelfranca rafaelfranca committed Apr 10, 2014
Showing with 783 additions and 287 deletions.
  1. +1 −0 .travis.yml
  2. +1 −0 Gemfile
  3. +1 −1 README.md
  4. +8 −5 actionpack/lib/action_dispatch/middleware/ssl.rb
  5. +16 −7 actionpack/test/controller/flash_test.rb
  6. +7 −0 actionpack/test/dispatch/ssl_test.rb
  7. +1 −1 activemodel/lib/active_model/validations/with.rb
  8. +28 −0 activerecord/CHANGELOG.md
  9. +6 −6 activerecord/lib/active_record/associations/collection_association.rb
  10. +5 −6 activerecord/lib/active_record/associations/collection_proxy.rb
  11. +3 −3 activerecord/lib/active_record/associations/singular_association.rb
  12. +2 −2 activerecord/lib/active_record/attribute_methods/dirty.rb
  13. +2 −2 activerecord/lib/active_record/callbacks.rb
  14. +3 −3 activerecord/lib/active_record/connection_adapters/connection_specification.rb
  15. +2 −2 activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
  16. +1 −1 activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
  17. +1 −1 activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
  18. +6 −29 activerecord/lib/active_record/connection_handling.rb
  19. +11 −6 activerecord/lib/active_record/enum.rb
  20. +1 −1 activerecord/lib/active_record/locking/optimistic.rb
  21. +4 −4 activerecord/lib/active_record/persistence.rb
  22. +5 −5 activerecord/lib/active_record/reflection.rb
  23. +1 −1 activerecord/lib/active_record/relation.rb
  24. +1 −1 activerecord/lib/active_record/relation/calculations.rb
  25. +0 −1 activerecord/lib/active_record/relation/merger.rb
  26. +3 −3 activerecord/lib/active_record/relation/query_methods.rb
  27. +2 −2 activerecord/lib/active_record/timestamp.rb
  28. +1 −1 activerecord/lib/active_record/validations/uniqueness.rb
  29. +1 −1 activerecord/test/cases/adapters/postgresql/array_test.rb
  30. +17 −0 activerecord/test/cases/adapters/postgresql/bytea_test.rb
  31. +8 −0 activerecord/test/cases/associations/belongs_to_associations_test.rb
  32. +14 −0 activerecord/test/cases/calculations_test.rb
  33. +45 −26 activerecord/test/cases/connection_adapters/connection_handler_test.rb
  34. +36 −0 activerecord/test/cases/enum_test.rb
  35. +8 −0 activerecord/test/cases/migration/column_attributes_test.rb
  36. +2 −2 activerecord/test/cases/reflection_test.rb
  37. +11 −3 activerecord/test/cases/relation/mutation_test.rb
  38. +18 −0 activerecord/test/cases/relations_test.rb
  39. +3 −0 activerecord/test/models/column.rb
  40. +4 −0 activerecord/test/models/post.rb
  41. +2 −0 activerecord/test/models/record.rb
  42. +2 −2 activerecord/test/models/tag.rb
  43. +7 −1 activerecord/test/schema/schema.rb
  44. +34 −0 activesupport/CHANGELOG.md
  45. +1 −0 activesupport/lib/active_support/cache/strategy/local_cache.rb
  46. +12 −6 activesupport/lib/active_support/callbacks.rb
  47. +4 −0 activesupport/lib/active_support/duration.rb
  48. +7 −0 activesupport/test/core_ext/duration_test.rb
  49. +58 −1 activesupport/test/xml_mini_test.rb
  50. +4 −0 guides/CHANGELOG.md
  51. +5 −20 guides/source/asset_pipeline.md
  52. +14 −1 guides/source/development_dependencies_install.md
  53. +102 −53 guides/source/initialization.md
  54. +3 −3 guides/source/maintenance_policy.md
  55. +1 −1 guides/source/security.md
  56. +8 −7 guides/source/upgrading_ruby_on_rails.md
  57. +1 −1 rails.gemspec
  58. +4 −3 railties/lib/rails/application.rb
  59. +1 −1 railties/lib/rails/generators/app_base.rb
  60. +2 −2 railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb
  61. +23 −3 railties/lib/rails/generators/rails/app/templates/config/databases/frontbase.yml
  62. +23 −3 railties/lib/rails/generators/rails/app/templates/config/databases/ibm_db.yml
  63. +12 −3 railties/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml
  64. +24 −3 railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml
  65. +23 −3 railties/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml
  66. +2 −3 railties/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml
  67. +21 −5 railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml
  68. +23 −3 railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml
  69. +21 −5 railties/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml
  70. +2 −9 railties/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml
  71. +23 −3 railties/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml
  72. +1 −1 railties/lib/rails/generators/rails/app/templates/config/initializers/cookies_serializer.rb
  73. +0 −1 railties/lib/rails/generators/rails/app/templates/config/initializers/mime_types.rb
  74. +2 −2 railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb
  75. +1 −0 railties/lib/rails/test_help.rb
  76. +6 −5 railties/test/application/assets_test.rb
  77. +6 −0 railties/test/application/multiple_applications_test.rb
  78. +0 −7 railties/test/generators/scaffold_controller_generator_test.rb
  79. +8 −0 railties/test/railties/railtie_test.rb
View
1 .travis.yml
@@ -1,3 +1,4 @@
+services: memcache
script: 'ci/travis.rb'
before_install:
- travis_retry gem install bundler
View
1 Gemfile
@@ -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
2 README.md
@@ -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
13 actionpack/lib/action_dispatch/middleware/ssl.rb
@@ -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
View
23 actionpack/test/controller/flash_test.rb
@@ -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
View
7 actionpack/test/dispatch/ssl_test.rb
@@ -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"
View
2 activemodel/lib/active_model/validations/with.rb
@@ -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>).
View
28 activerecord/CHANGELOG.md
@@ -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
12 activerecord/lib/active_record/associations/collection_association.rb
@@ -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|
View
11 activerecord/lib/active_record/associations/collection_proxy.rb
@@ -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
View
6 activerecord/lib/active_record/associations/singular_association.rb
@@ -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
View
4 activerecord/lib/active_record/attribute_methods/dirty.rb
@@ -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
View
4 activerecord/lib/active_record/callbacks.rb
@@ -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
View
6 activerecord/lib/active_record/connection_adapters/connection_specification.rb
@@ -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
View
4 activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
@@ -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.
View
2 activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -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" },
View
2 activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
@@ -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" },
View
35 activerecord/lib/active_record/connection_handling.rb
@@ -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
View
17 activerecord/lib/active_record/enum.rb
@@ -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 @@ 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]
View
2 activerecord/lib/active_record/locking/optimistic.rb
@@ -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?
View
8 activerecord/lib/active_record/persistence.rb
@@ -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
View
10 activerecord/lib/active_record/reflection.rb
@@ -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:
View
2 activerecord/lib/active_record/relation.rb
@@ -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)
View
2 activerecord/lib/active_record/relation/calculations.rb
@@ -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
View
1 activerecord/lib/active_record/relation/merger.rb
@@ -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])
View
6 activerecord/lib/active_record/relation/query_methods.rb
@@ -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
View
4 activerecord/lib/active_record/timestamp.rb
@@ -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
View
2 activerecord/lib/active_record/validations/uniqueness.rb
@@ -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
View
2 activerecord/test/cases/adapters/postgresql/array_test.rb
@@ -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?
View
17 activerecord/test/cases/adapters/postgresql/bytea_test.rb
@@ -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)
View
8 activerecord/test/cases/associations/belongs_to_associations_test.rb
@@ -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
View
14 activerecord/test/cases/calculations_test.rb
@@ -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)
View
71 activerecord/test/cases/connection_adapters/connection_handler_test.rb
@@ -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",
View
36 activerecord/test/cases/enum_test.rb
@@ -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
View
8 activerecord/test/cases/migration/column_attributes_test.rb
@@ -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
View
4 activerecord/test/cases/reflection_test.rb
@@ -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
View
14 activerecord/test/cases/relation/mutation_test.rb
@@ -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
View
18 activerecord/test/cases/relations_test.rb
@@ -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
View
3 activerecord/test/models/column.rb
@@ -0,0 +1,3 @@
+class Column < ActiveRecord::Base
+ belongs_to :record
+end
View
4 activerecord/test/models/post.rb
@@ -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
View
2 activerecord/test/models/record.rb
@@ -0,0 +1,2 @@
+class Record < ActiveRecord::Base
+end
View
4 activerecord/test/models/tag.rb
@@ -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
8 activerecord/test/schema/schema.rb
@@ -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
View
34 activesupport/CHANGELOG.md
@@ -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
1 activesupport/lib/active_support/cache/strategy/local_cache.rb
@@ -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
18 activesupport/lib/active_support/callbacks.rb
@@ -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,13 +178,15 @@ 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|
user_callback.call env.target, env.value
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
View
4 activesupport/lib/active_support/duration.rb
@@ -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
View
7 activesupport/test/core_ext/duration_test.rb
@@ -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
View
59 activesupport/test/xml_mini_test.rb
@@ -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 @@ 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
View
4 guides/CHANGELOG.md
@@ -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
25 guides/source/asset_pipeline.md
@@ -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
15 guides/source/development_dependencies_install.md
@@ -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
155 guides/source/initialization.md
@@ -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,15 +179,16 @@ 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
set_application_directory!
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,15 +600,19 @@ 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
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.