aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Patterson <aaron.patterson@gmail.com>2012-02-09 13:50:08 -0800
committerAaron Patterson <aaron.patterson@gmail.com>2012-02-09 13:50:08 -0800
commite0cba3a0fab28f96dc9b5d3a714886583873a7d3 (patch)
tree8712fd8f0b53b7916ae8549decb86928302f00dc
parent6c50c07d8dbb0b014e68608fe72f807cbe7f5c45 (diff)
parente6c98b83cbf4eab8944601754cc8d0e627b55d6f (diff)
downloadrails-e0cba3a0fab28f96dc9b5d3a714886583873a7d3.tar.gz
rails-e0cba3a0fab28f96dc9b5d3a714886583873a7d3.tar.bz2
rails-e0cba3a0fab28f96dc9b5d3a714886583873a7d3.zip
Merge branch 'master' into instance_reader
* master: (30 commits) Bump tzinfo. 0.3.31 was released on November 6, 2011. Fix GH #4909. Dependency on TZInfo move from AR to AS. moving ordered hash to normal hash because ruby 1.9.3 hash defaultly ordered one Refactored the OrderedHash related stuff Replaced OrderedHash usage with Ruby 1.9 Hash Replaced OrderedHash with Hash for ruby 1.9 series removed unnecessary code replacing the orderhash with hash for ruby-1.9 Clean up some wording. Fix typo. test title changed corresponding to the test replaced active support ordered hash to ruby hash on active resource PostgreSQL does not work in the same way of the other adapters AR::Relation#pluck: improve to work with joins Fix match docs Fix attribute_before_type_cast for serialized attributes. Fixes #4837. Fix failing request test Fixes in AMo README Update README to mention lint. Trim down Active Model API by removing valid? and errors.full_messages ...
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb2
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions/selector.rb6
-rw-r--r--actionpack/lib/action_view/helpers/active_model_helper.rb2
-rw-r--r--actionpack/lib/action_view/helpers/asset_tag_helper.rb2
-rw-r--r--actionpack/test/controller/test_case_test.rb5
-rw-r--r--actionpack/test/dispatch/request_test.rb2
-rw-r--r--actionpack/test/template/url_helper_test.rb1
-rw-r--r--activemodel/CHANGELOG.md2
-rw-r--r--activemodel/README.rdoc17
-rw-r--r--activemodel/lib/active_model/errors.rb7
-rw-r--r--activemodel/lib/active_model/lint.rb40
-rw-r--r--activemodel/lib/active_model/validations.rb2
-rw-r--r--activemodel/test/cases/errors_test.rb4
-rw-r--r--activemodel/test/cases/lint_test.rb6
-rw-r--r--activemodel/test/cases/serializers/json_serialization_test.rb4
-rw-r--r--activemodel/test/cases/validations_test.rb2
-rw-r--r--activerecord/activerecord.gemspec1
-rw-r--r--activerecord/lib/active_record/attribute_methods/serialization.rb8
-rw-r--r--activerecord/lib/active_record/core.rb4
-rw-r--r--activerecord/lib/active_record/fixtures.rb3
-rw-r--r--activerecord/lib/active_record/relation/calculations.rb3
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb4
-rw-r--r--activerecord/test/cases/base_test.rb15
-rw-r--r--activerecord/test/cases/calculations_test.rb15
-rw-r--r--activerecord/test/cases/migration_test.rb10
-rw-r--r--activeresource/test/cases/base_test.rb4
-rw-r--r--activesupport/CHANGELOG.md2
-rw-r--r--activesupport/activesupport.gemspec1
-rw-r--r--activesupport/lib/active_support/core_ext/integer/inflections.rb14
-rw-r--r--activesupport/lib/active_support/inflector/methods.rb34
-rw-r--r--activesupport/lib/active_support/json/encoding.rb4
-rw-r--r--activesupport/test/core_ext/integer_ext_test.rb5
-rw-r--r--activesupport/test/inflector_test.rb6
-rw-r--r--railties/guides/rails_guides/indexer.rb3
-rw-r--r--railties/guides/source/action_view_overview.textile4
-rw-r--r--railties/guides/source/active_support_core_extensions.textile17
-rw-r--r--railties/guides/source/layouts_and_rendering.textile6
-rw-r--r--railties/guides/source/testing.textile15
38 files changed, 175 insertions, 107 deletions
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index ae67b71a27..cf9c0d7b6a 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -1250,7 +1250,7 @@ module ActionDispatch
end
# match 'path' => 'controller#action'
- # match 'path', as: 'controller#action'
+ # match 'path', to: 'controller#action'
# match 'path', 'otherpath', on: :member, via: :get
def match(path, *rest)
if rest.empty? && Hash === path
diff --git a/actionpack/lib/action_dispatch/testing/assertions/selector.rb b/actionpack/lib/action_dispatch/testing/assertions/selector.rb
index 33796008bd..8eed85bce2 100644
--- a/actionpack/lib/action_dispatch/testing/assertions/selector.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions/selector.rb
@@ -340,8 +340,8 @@ module ActionDispatch
# element +encoded+. It then calls the block with all un-encoded elements.
#
# ==== Examples
- # # Selects all bold tags from within the title of an ATOM feed's entries (perhaps to nab a section name prefix)
- # assert_select_feed :atom, 1.0 do
+ # # Selects all bold tags from within the title of an Atom feed's entries (perhaps to nab a section name prefix)
+ # assert_select "feed[xmlns='http://www.w3.org/2005/Atom']" do
# # Select each entry item and then the title item
# assert_select "entry>title" do
# # Run assertions on the encoded title elements
@@ -353,7 +353,7 @@ module ActionDispatch
#
#
# # Selects all paragraph tags from within the description of an RSS feed
- # assert_select_feed :rss, 2.0 do
+ # assert_select "rss[version=2.0]" do
# # Select description element of each feed item.
# assert_select "channel>item>description" do
# # Run assertions on the encoded elements.
diff --git a/actionpack/lib/action_view/helpers/active_model_helper.rb b/actionpack/lib/action_view/helpers/active_model_helper.rb
index 1187956081..e27111012d 100644
--- a/actionpack/lib/action_view/helpers/active_model_helper.rb
+++ b/actionpack/lib/action_view/helpers/active_model_helper.rb
@@ -39,7 +39,7 @@ module ActionView
private
def object_has_errors?
- object.respond_to?(:errors) && object.errors.respond_to?(:full_messages) && error_message.any?
+ object.respond_to?(:errors) && object.errors.respond_to?(:[]) && error_message.present?
end
def tag_generate_errors?(options)
diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
index c035dde51e..662adbe183 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
@@ -198,7 +198,7 @@ module ActionView
include JavascriptTagHelpers
include StylesheetTagHelpers
# Returns a link tag that browsers and news readers can use to auto-detect
- # an RSS or ATOM feed. The +type+ can either be <tt>:rss</tt> (default) or
+ # an RSS or Atom feed. The +type+ can either be <tt>:rss</tt> (default) or
# <tt>:atom</tt>. Control the link options in url_for format using the
# +url_options+. You can modify the LINK tag itself in +tag_options+.
#
diff --git a/actionpack/test/controller/test_case_test.rb b/actionpack/test/controller/test_case_test.rb
index caf76c7e61..c957df88b3 100644
--- a/actionpack/test/controller/test_case_test.rb
+++ b/actionpack/test/controller/test_case_test.rb
@@ -1,6 +1,5 @@
require 'abstract_unit'
require 'controller/fake_controllers'
-require 'active_support/ordered_hash'
class TestCaseTest < ActionController::TestCase
class TestController < ActionController::Base
@@ -155,14 +154,14 @@ XML
end
def test_raw_post_handling
- params = ActiveSupport::OrderedHash[:page, {:name => 'page name'}, 'some key', 123]
+ params = Hash[:page, {:name => 'page name'}, 'some key', 123]
post :render_raw_post, params.dup
assert_equal params.to_query, @response.body
end
def test_body_stream
- params = ActiveSupport::OrderedHash[:page, { :name => 'page name' }, 'some key', 123]
+ params = Hash[:page, { :name => 'page name' }, 'some key', 123]
post :render_body, params.dup
diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb
index c5e3525d84..8f0ac5310e 100644
--- a/actionpack/test/dispatch/request_test.rb
+++ b/actionpack/test/dispatch/request_test.rb
@@ -127,7 +127,7 @@ class RequestTest < ActiveSupport::TestCase
'HTTP_X_FORWARDED_FOR' => '3.4.5.6'
assert_equal '3.4.5.6', request.remote_ip
- request = stub_request 'HTTP_X_FORWARDED_FOR' => '9.9.9.9, 3.4.5.6, 10.0.0.1, 67.205.106.73'
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => '67.205.106.73, 10.0.0.1, 9.9.9.9, 3.4.5.6'
assert_equal '10.0.0.1', request.remote_ip
end
diff --git a/actionpack/test/template/url_helper_test.rb b/actionpack/test/template/url_helper_test.rb
index 37ec0e323d..b482bd3251 100644
--- a/actionpack/test/template/url_helper_test.rb
+++ b/actionpack/test/template/url_helper_test.rb
@@ -1,6 +1,5 @@
# encoding: utf-8
require 'abstract_unit'
-require 'active_support/ordered_hash'
require 'controller/fake_controllers'
class UrlHelperTest < ActiveSupport::TestCase
diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md
index a7a40ee03d..258c3681f6 100644
--- a/activemodel/CHANGELOG.md
+++ b/activemodel/CHANGELOG.md
@@ -1,3 +1,5 @@
+* Trim down Active Model API by removing `valid?` and `errors.full_messages` *José Valim*
+
## Rails 3.2.0 (January 20, 2012) ##
* Deprecated `define_attr_method` in `ActiveModel::AttributeMethods`, because this only existed to
diff --git a/activemodel/README.rdoc b/activemodel/README.rdoc
index 9208145507..a7ba27ba73 100644
--- a/activemodel/README.rdoc
+++ b/activemodel/README.rdoc
@@ -9,10 +9,12 @@ Prior to Rails 3.0, if a plugin or gem developer wanted to have an object
interact with Action Pack helpers, it was required to either copy chunks of
code from Rails, or monkey patch entire helpers to make them handle objects
that did not exactly conform to the Active Record interface. This would result
-in code duplication and fragile applications that broke on upgrades.
+in code duplication and fragile applications that broke on upgrades. Active
+Model solves this by defining an explicit API. You can read more about the
+API in ActiveModel::Lint::Tests.
-Active Model solves this. You can include functionality from the following
-modules:
+Active Model also provides the following functionality to have ORM-like
+behavior out of the box:
* Add attribute magic to objects
@@ -87,10 +89,9 @@ modules:
errors.add(:name, "can not be nil") if name.nil?
end
- def ErrorsPerson.human_attribute_name(attr, options = {})
+ def self.human_attribute_name(attr, options = {})
"Name"
end
-
end
person.errors.full_messages
@@ -163,7 +164,7 @@ modules:
* Custom validators
- class Person
+ class ValidatorPerson
include ActiveModel::Validations
validates_with HasNameValidator
attr_accessor :name
@@ -171,7 +172,7 @@ modules:
class HasNameValidator < ActiveModel::Validator
def validate(record)
- record.errors[:name] = "must exist" if record.name.blank?
+ record.errors[:name] = "must exist" if record.name.blank?
end
end
@@ -182,7 +183,7 @@ modules:
p.valid? # => true
{Learn more}[link:classes/ActiveModel/Validator.html]
-
+
== Download and installation
diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb
index 75feba1fe7..e548aa975d 100644
--- a/activemodel/lib/active_model/errors.rb
+++ b/activemodel/lib/active_model/errors.rb
@@ -4,12 +4,11 @@ require 'active_support/core_ext/array/conversions'
require 'active_support/core_ext/string/inflections'
require 'active_support/core_ext/object/blank'
require 'active_support/core_ext/hash/reverse_merge'
-require 'active_support/ordered_hash'
module ActiveModel
# == Active Model Errors
#
- # Provides a modified +OrderedHash+ that you can include in your object
+ # Provides a modified +Hash+ that you can include in your object
# for handling error messages and interacting with Action Pack helpers.
#
# A minimal implementation could be:
@@ -75,7 +74,7 @@ module ActiveModel
# end
def initialize(base)
@base = base
- @messages = ActiveSupport::OrderedHash.new
+ @messages = {}
end
def initialize_dup(other)
@@ -206,7 +205,7 @@ module ActiveModel
to_a.to_xml options.reverse_merge(:root => "errors", :skip_types => true)
end
- # Returns an ActiveSupport::OrderedHash that can be used as the JSON representation for this object.
+ # Returns an Hash that can be used as the JSON representation for this object.
def as_json(options=nil)
to_hash
end
diff --git a/activemodel/lib/active_model/lint.rb b/activemodel/lib/active_model/lint.rb
index bfe7ea1869..49ea894150 100644
--- a/activemodel/lib/active_model/lint.rb
+++ b/activemodel/lib/active_model/lint.rb
@@ -3,9 +3,13 @@ module ActiveModel
# == Active Model Lint Tests
#
# You can test whether an object is compliant with the Active Model API by
- # including <tt>ActiveModel::Lint::Tests</tt> in your TestCase. It will include
- # tests that tell you whether your object is fully compliant, or if not,
- # which aspects of the API are not implemented.
+ # including <tt>ActiveModel::Lint::Tests</tt> in your TestCase. It will
+ # include tests that tell you whether your object is fully compliant,
+ # or if not, which aspects of the API are not implemented.
+ #
+ # Note an object is not required to implement all APIs in order to work
+ # with Action Pack. This module only intends to provide guidance in case
+ # you want all features out of the box.
#
# These tests do not attempt to determine the semantic correctness of the
# returned values. For instance, you could implement valid? to always
@@ -19,7 +23,8 @@ module ActiveModel
# == Responds to <tt>to_key</tt>
#
# Returns an Enumerable of all (primary) key attributes
- # or nil if model.persisted? is false
+ # or nil if model.persisted? is false. This is used by
+ # dom_id to generate unique ids for the object.
def test_to_key
assert model.respond_to?(:to_key), "The model should respond to to_key"
def model.persisted?() false end
@@ -53,15 +58,6 @@ module ActiveModel
assert_kind_of String, model.to_partial_path
end
- # == Responds to <tt>valid?</tt>
- #
- # Returns a boolean that specifies whether the object is in a valid or invalid
- # state.
- def test_valid?
- assert model.respond_to?(:valid?), "The model should respond to valid?"
- assert_boolean model.valid?, "valid?"
- end
-
# == Responds to <tt>persisted?</tt>
#
# Returns a boolean that specifies whether the object has been persisted yet.
@@ -90,25 +86,15 @@ module ActiveModel
# == Errors Testing
#
- # Returns an object that has :[] and :full_messages defined on it. See below
- # for more details.
- #
- # Returns an Array of Strings that are the errors for the attribute in
- # question. If localization is used, the Strings should be localized
- # for the current locale. If no error is present, this method should
- # return an empty Array.
+ # Returns an object that implements [](attribute) defined which returns an
+ # Array of Strings that are the errors for the attribute in question.
+ # If localization is used, the Strings should be localized for the current
+ # locale. If no error is present, this method should return an empty Array.
def test_errors_aref
assert model.respond_to?(:errors), "The model should respond to errors"
assert model.errors[:hello].is_a?(Array), "errors#[] should return an Array"
end
- # Returns an Array of all error messages for the object. Each message
- # should contain information about the field, if applicable.
- def test_errors_full_messages
- assert model.respond_to?(:errors), "The model should respond to errors"
- assert model.errors.full_messages.is_a?(Array), "errors#full_messages should return an Array"
- end
-
private
def model
assert @model.respond_to?(:to_model), "The object should respond_to to_model"
diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb
index 15b8e824ac..0e15155b85 100644
--- a/activemodel/lib/active_model/validations.rb
+++ b/activemodel/lib/active_model/validations.rb
@@ -33,7 +33,7 @@ module ActiveModel
# person.first_name = 'zoolander'
# person.valid? # => false
# person.invalid? # => true
- # person.errors # => #<OrderedHash {:first_name=>["starts with z."]}>
+ # person.errors # => #<Hash {:first_name=>["starts with z."]}>
#
# Note that <tt>ActiveModel::Validations</tt> automatically adds an +errors+ method
# to your instances initialized with a new <tt>ActiveModel::Errors</tt> object, so
diff --git a/activemodel/test/cases/errors_test.rb b/activemodel/test/cases/errors_test.rb
index ab80f193b6..7a610e0c2c 100644
--- a/activemodel/test/cases/errors_test.rb
+++ b/activemodel/test/cases/errors_test.rb
@@ -151,10 +151,10 @@ class ErrorsTest < ActiveModel::TestCase
assert_equal ["name can not be blank", "name can not be nil"], person.errors.to_a
end
- test 'to_hash should return an ordered hash' do
+ test 'to_hash should return a hash' do
person = Person.new
person.errors.add(:name, "can not be blank")
- assert_instance_of ActiveSupport::OrderedHash, person.errors.to_hash
+ assert_instance_of ::Hash, person.errors.to_hash
end
test 'full_messages should return an array of error messages, with the attribute name included' do
diff --git a/activemodel/test/cases/lint_test.rb b/activemodel/test/cases/lint_test.rb
index 68372160cd..8faf93c056 100644
--- a/activemodel/test/cases/lint_test.rb
+++ b/activemodel/test/cases/lint_test.rb
@@ -7,14 +7,10 @@ class LintTest < ActiveModel::TestCase
extend ActiveModel::Naming
include ActiveModel::Conversion
- def valid?() true end
def persisted?() false end
def errors
- obj = Object.new
- def obj.[](key) [] end
- def obj.full_messages() [] end
- obj
+ Hash.new([])
end
end
diff --git a/activemodel/test/cases/serializers/json_serialization_test.rb b/activemodel/test/cases/serializers/json_serialization_test.rb
index 4ac5fb1779..7160635eb4 100644
--- a/activemodel/test/cases/serializers/json_serialization_test.rb
+++ b/activemodel/test/cases/serializers/json_serialization_test.rb
@@ -130,13 +130,13 @@ class JsonSerializationTest < ActiveModel::TestCase
assert_match %r{"favorite_quote":"Constraints are liberating"}, methods_json
end
- test "should return OrderedHash for errors" do
+ test "should return Hash for errors" do
contact = Contact.new
contact.errors.add :name, "can't be blank"
contact.errors.add :name, "is too short (minimum is 2 characters)"
contact.errors.add :age, "must be 16 or over"
- hash = ActiveSupport::OrderedHash.new
+ hash = {}
hash[:name] = ["can't be blank", "is too short (minimum is 2 characters)"]
hash[:age] = ["must be 16 or over"]
assert_equal hash.to_json, contact.errors.to_json
diff --git a/activemodel/test/cases/validations_test.rb b/activemodel/test/cases/validations_test.rb
index 0b1de62a48..a716d0896e 100644
--- a/activemodel/test/cases/validations_test.rb
+++ b/activemodel/test/cases/validations_test.rb
@@ -180,7 +180,7 @@ class ValidationsTest < ActiveModel::TestCase
assert_match %r{<error>Title can't be blank</error>}, xml
assert_match %r{<error>Content can't be blank</error>}, xml
- hash = ActiveSupport::OrderedHash.new
+ hash = {}
hash[:title] = ["can't be blank"]
hash[:content] = ["can't be blank"]
assert_equal t.errors.to_json, hash.to_json
diff --git a/activerecord/activerecord.gemspec b/activerecord/activerecord.gemspec
index 8484e1093e..8f4c957dbd 100644
--- a/activerecord/activerecord.gemspec
+++ b/activerecord/activerecord.gemspec
@@ -22,5 +22,4 @@ Gem::Specification.new do |s|
s.add_dependency('activesupport', version)
s.add_dependency('activemodel', version)
s.add_dependency('arel', '~> 3.0.0')
- s.add_dependency('tzinfo', '~> 0.3.29')
end
diff --git a/activerecord/lib/active_record/attribute_methods/serialization.rb b/activerecord/lib/active_record/attribute_methods/serialization.rb
index 1fe5d9de20..9b1bfa1145 100644
--- a/activerecord/lib/active_record/attribute_methods/serialization.rb
+++ b/activerecord/lib/active_record/attribute_methods/serialization.rb
@@ -110,6 +110,14 @@ module ActiveRecord
super
end
end
+
+ def read_attribute_before_type_cast(attr_name)
+ if serialized_attributes.include?(attr_name)
+ super.unserialized_value
+ else
+ super
+ end
+ end
end
end
end
diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb
index 28f52bd270..c4a4c0ad9a 100644
--- a/activerecord/lib/active_record/core.rb
+++ b/activerecord/lib/active_record/core.rb
@@ -212,6 +212,8 @@ module ActiveRecord
# The dup method does not preserve the timestamps (created|updated)_(at|on).
def initialize_dup(other)
cloned_attributes = other.clone_attributes(:read_attribute_before_type_cast)
+ self.class.initialize_attributes(cloned_attributes)
+
cloned_attributes.delete(self.class.primary_key)
@attributes = cloned_attributes
@@ -246,7 +248,7 @@ module ActiveRecord
# end
# coder = {}
# Post.new.encode_with(coder)
- # coder # => { 'id' => nil, ... }
+ # coder # => {"attributes" => {"id" => nil, ... }}
def encode_with(coder)
coder['attributes'] = attributes
end
diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb
index cf315b687c..b82d5b5621 100644
--- a/activerecord/lib/active_record/fixtures.rb
+++ b/activerecord/lib/active_record/fixtures.rb
@@ -3,7 +3,6 @@ require 'yaml'
require 'zlib'
require 'active_support/dependencies'
require 'active_support/core_ext/object/blank'
-require 'active_support/ordered_hash'
require 'active_record/fixtures/file'
if defined? ActiveRecord
@@ -508,7 +507,7 @@ module ActiveRecord
@name = fixture_name
@class_name = class_name
- @fixtures = ActiveSupport::OrderedHash.new
+ @fixtures = {}
# Should be an AR::Base type class
if class_name.is_a?(Class)
diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb
index 6bf3050af9..50239f7cb2 100644
--- a/activerecord/lib/active_record/relation/calculations.rb
+++ b/activerecord/lib/active_record/relation/calculations.rb
@@ -177,6 +177,9 @@ module ActiveRecord
# Person.where(:confirmed => true).limit(5).pluck(:id)
#
def pluck(column_name)
+ if column_name.is_a?(Symbol) && column_names.include?(column_name.to_s)
+ column_name = "#{table_name}.#{column_name}"
+ end
klass.connection.select_all(select(column_name).arel).map! do |attributes|
klass.type_cast_attribute(attributes.keys.first, klass.initialize_attributes(attributes))
end
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index b6d762c2e2..87dd513880 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -206,8 +206,8 @@ module ActiveRecord
# Any subsequent condition chained to the returned relation will continue
# generating an empty relation and will not fire any query to the database.
#
- # This is useful in scenarios where you need a chainable response to a method
- # or a scope that could return zero results.
+ # Used in cases where a method or scope could return zero records but the
+ # result needs to be chainable.
#
# For example:
#
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index acc0f272c1..698c3d0cb1 100644
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -1281,6 +1281,21 @@ class BasicsTest < ActiveRecord::TestCase
assert_equal(hash, important_topic.content)
end
+ # This test was added to fix GH #4004. Obviously the value returned
+ # is not really the value 'before type cast' so we should maybe think
+ # about changing that in the future.
+ def test_serialized_attribute_before_type_cast_returns_unserialized_value
+ klass = Class.new(ActiveRecord::Base)
+ klass.table_name = "topics"
+ klass.serialize :content, Hash
+
+ t = klass.new(:content => { :foo => :bar })
+ assert_equal({ :foo => :bar }, t.content_before_type_cast)
+ t.save!
+ t.reload
+ assert_equal({ :foo => :bar }, t.content_before_type_cast)
+ end
+
def test_serialized_attribute_declared_in_subclass
hash = { 'important1' => 'value1', 'important2' => 'value2' }
important_topic = ImportantTopic.create("important" => hash)
diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb
index 7c9ebf528e..e1544b3b00 100644
--- a/activerecord/test/cases/calculations_test.rb
+++ b/activerecord/test/cases/calculations_test.rb
@@ -478,4 +478,19 @@ class CalculationsTest < ActiveRecord::TestCase
def test_pluck_with_qualified_column_name
assert_equal [1,2,3,4], Topic.order(:id).pluck("topics.id")
end
+
+ def test_pluck_auto_table_name_prefix
+ c = Company.create!(:name => "test", :contracts => [Contract.new])
+ assert_equal [c.id], Company.joins(:contracts).pluck(:id)
+ end
+
+ def test_pluck_not_auto_table_name_prefix_if_column_joined
+ Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
+ # FIXME: PostgreSQL should works in the same way of the other adapters
+ if current_adapter?(:PostgreSQLAdapter)
+ assert_equal ["7"], Company.joins(:contracts).pluck(:developer_id)
+ else
+ assert_equal [7], Company.joins(:contracts).pluck(:developer_id)
+ end
+ end
end
diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb
index 575df2f84b..92dc150104 100644
--- a/activerecord/test/cases/migration_test.rb
+++ b/activerecord/test/cases/migration_test.rb
@@ -800,7 +800,7 @@ class CopyMigrationsTest < ActiveRecord::TestCase
@migrations_path = MIGRATIONS_ROOT + "/valid"
@existing_migrations = Dir[@migrations_path + "/*.rb"]
- sources = ActiveSupport::OrderedHash.new
+ sources = {}
sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy"
sources[:omg] = MIGRATIONS_ROOT + "/to_copy2"
ActiveRecord::Migration.copy(@migrations_path, sources)
@@ -841,7 +841,7 @@ class CopyMigrationsTest < ActiveRecord::TestCase
@migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
@existing_migrations = Dir[@migrations_path + "/*.rb"]
- sources = ActiveSupport::OrderedHash.new
+ sources = {}
sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps"
sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_timestamps2"
@@ -882,8 +882,8 @@ class CopyMigrationsTest < ActiveRecord::TestCase
def test_skipping_migrations
@migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
@existing_migrations = Dir[@migrations_path + "/*.rb"]
-
- sources = ActiveSupport::OrderedHash.new
+
+ sources = {}
sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps"
sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_name_collision"
@@ -902,7 +902,7 @@ class CopyMigrationsTest < ActiveRecord::TestCase
@migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps"
@existing_migrations = Dir[@migrations_path + "/*.rb"]
- sources = ActiveSupport::OrderedHash.new
+ sources = {}
sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps"
skipped = []
diff --git a/activeresource/test/cases/base_test.rb b/activeresource/test/cases/base_test.rb
index c3b963844c..f5a58793d1 100644
--- a/activeresource/test/cases/base_test.rb
+++ b/activeresource/test/cases/base_test.rb
@@ -8,7 +8,6 @@ require "fixtures/proxy"
require "fixtures/address"
require "fixtures/subscription_plan"
require 'active_support/json'
-require 'active_support/ordered_hash'
require 'active_support/core_ext/hash/conversions'
require 'mocha'
@@ -464,8 +463,7 @@ class BaseTest < ActiveSupport::TestCase
assert Person.collection_path(:gender => 'male', :student => true).include?('student=true')
assert_equal '/people.json?name%5B%5D=bob&name%5B%5D=your+uncle%2Bme&name%5B%5D=&name%5B%5D=false', Person.collection_path(:name => ['bob', 'your uncle+me', nil, false])
-
- assert_equal '/people.json?struct%5Ba%5D%5B%5D=2&struct%5Ba%5D%5B%5D=1&struct%5Bb%5D=fred', Person.collection_path(:struct => ActiveSupport::OrderedHash[:a, [2,1], 'b', 'fred'])
+ assert_equal '/people.json?struct%5Ba%5D%5B%5D=2&struct%5Ba%5D%5B%5D=1&struct%5Bb%5D=fred', Person.collection_path(:struct => {:a => [2,1], 'b' => 'fred'})
end
def test_custom_element_path
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index c929ae0ae5..29109ea64d 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,5 +1,7 @@
## Rails 4.0.0 (unreleased) ##
+* Adds Integer#ordinal to get the ordinal suffix string of an integer. *Tim Gildea*
+
* AS::Callbacks: `:per_key` option is no longer supported
* `AS::Callbacks#define_callbacks`: add `:skip_after_callbacks_if_terminated` option.
diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec
index 61a88bd65b..d26d71b615 100644
--- a/activesupport/activesupport.gemspec
+++ b/activesupport/activesupport.gemspec
@@ -20,4 +20,5 @@ Gem::Specification.new do |s|
s.add_dependency('i18n', '~> 0.6')
s.add_dependency('multi_json', '~> 1.0')
+ s.add_dependency('tzinfo', '~> 0.3.31')
end
diff --git a/activesupport/lib/active_support/core_ext/integer/inflections.rb b/activesupport/lib/active_support/core_ext/integer/inflections.rb
index 0e606056c0..1e30687166 100644
--- a/activesupport/lib/active_support/core_ext/integer/inflections.rb
+++ b/activesupport/lib/active_support/core_ext/integer/inflections.rb
@@ -14,4 +14,18 @@ class Integer
def ordinalize
ActiveSupport::Inflector.ordinalize(self)
end
+
+ # Ordinal returns the suffix used to denote the position
+ # in an ordered sequence such as 1st, 2nd, 3rd, 4th.
+ #
+ # 1.ordinal # => "st"
+ # 2.ordinal # => "nd"
+ # 1002.ordinal # => "nd"
+ # 1003.ordinal # => "rd"
+ # -11.ordinal # => "th"
+ # -1001.ordinal # => "st"
+ #
+ def ordinal
+ ActiveSupport::Inflector.ordinal(self)
+ end
end
diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb
index 12dc86aeac..4b7c36f839 100644
--- a/activesupport/lib/active_support/inflector/methods.rb
+++ b/activesupport/lib/active_support/inflector/methods.rb
@@ -250,6 +250,29 @@ module ActiveSupport
end
end
+ # Returns the suffix that should be added to a number to denote the position
+ # in an ordered sequence such as 1st, 2nd, 3rd, 4th.
+ #
+ # Examples:
+ # ordinal(1) # => "st"
+ # ordinal(2) # => "nd"
+ # ordinal(1002) # => "nd"
+ # ordinal(1003) # => "rd"
+ # ordinal(-11) # => "th"
+ # ordinal(-1021) # => "st"
+ def ordinal(number)
+ if (11..13).include?(number.to_i.abs % 100)
+ "th"
+ else
+ case number.to_i.abs % 10
+ when 1; "st"
+ when 2; "nd"
+ when 3; "rd"
+ else "th"
+ end
+ end
+ end
+
# Turns a number into an ordinal string used to denote the position in an
# ordered sequence such as 1st, 2nd, 3rd, 4th.
#
@@ -261,16 +284,7 @@ module ActiveSupport
# ordinalize(-11) # => "-11th"
# ordinalize(-1021) # => "-1021st"
def ordinalize(number)
- if (11..13).include?(number.to_i.abs % 100)
- "#{number}th"
- else
- case number.to_i.abs % 10
- when 1; "#{number}st"
- when 2; "#{number}nd"
- when 3; "#{number}rd"
- else "#{number}th"
- end
- end
+ "#{number}#{ordinal(number)}"
end
private
diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb
index fcd83f8dea..b2adfea273 100644
--- a/activesupport/lib/active_support/json/encoding.rb
+++ b/activesupport/lib/active_support/json/encoding.rb
@@ -1,7 +1,6 @@
require 'active_support/core_ext/object/to_json'
require 'active_support/core_ext/module/delegation'
require 'active_support/json/variable'
-require 'active_support/ordered_hash'
require 'bigdecimal'
require 'active_support/core_ext/big_decimal/conversions' # for #to_s
@@ -239,8 +238,7 @@ class Hash
# use encoder as a proxy to call as_json on all values in the subset, to protect from circular references
encoder = options && options[:encoder] || ActiveSupport::JSON::Encoding::Encoder.new(options)
- result = self.is_a?(ActiveSupport::OrderedHash) ? ActiveSupport::OrderedHash : Hash
- result[subset.map { |k, v| [k.to_s, encoder.as_json(v, options)] }]
+ Hash[subset.map { |k, v| [k.to_s, encoder.as_json(v, options)] }]
end
def encode_json(encoder)
diff --git a/activesupport/test/core_ext/integer_ext_test.rb b/activesupport/test/core_ext/integer_ext_test.rb
index 7597f9c6f5..41736fb672 100644
--- a/activesupport/test/core_ext/integer_ext_test.rb
+++ b/activesupport/test/core_ext/integer_ext_test.rb
@@ -22,4 +22,9 @@ class IntegerExtTest < ActiveSupport::TestCase
assert_equal '1st', 1.ordinalize
assert_equal '8th', 8.ordinalize
end
+
+ def test_ordinal
+ assert_equal 'st', 1.ordinal
+ assert_equal 'th', 8.ordinal
+ end
end
diff --git a/activesupport/test/inflector_test.rb b/activesupport/test/inflector_test.rb
index 3311d58254..e7c671778a 100644
--- a/activesupport/test/inflector_test.rb
+++ b/activesupport/test/inflector_test.rb
@@ -304,6 +304,12 @@ class InflectorTest < ActiveSupport::TestCase
def test_ordinal
OrdinalNumbers.each do |number, ordinalized|
+ assert_equal(ordinalized, number + ActiveSupport::Inflector.ordinal(number))
+ end
+ end
+
+ def test_ordinalize
+ OrdinalNumbers.each do |number, ordinalized|
assert_equal(ordinalized, ActiveSupport::Inflector.ordinalize(number))
end
end
diff --git a/railties/guides/rails_guides/indexer.rb b/railties/guides/rails_guides/indexer.rb
index fb46491817..89fbccbb1d 100644
--- a/railties/guides/rails_guides/indexer.rb
+++ b/railties/guides/rails_guides/indexer.rb
@@ -1,5 +1,4 @@
require 'active_support/core_ext/object/blank'
-require 'active_support/ordered_hash'
require 'active_support/core_ext/string/inflections'
module RailsGuides
@@ -21,7 +20,7 @@ module RailsGuides
def process(string, current_level=3, counters=[1])
s = StringScanner.new(string)
- level_hash = ActiveSupport::OrderedHash.new
+ level_hash = {}
while !s.eos?
re = %r{^h(\d)(?:\((#.*?)\))?\s*\.\s*(.*)$}
diff --git a/railties/guides/source/action_view_overview.textile b/railties/guides/source/action_view_overview.textile
index 3b0fbfb464..2c0b81121f 100644
--- a/railties/guides/source/action_view_overview.textile
+++ b/railties/guides/source/action_view_overview.textile
@@ -570,7 +570,7 @@ stylesheet_link_tag :monkey # =>
h5. auto_discovery_link_tag
-Returns a link tag that browsers and news readers can use to auto-detect an RSS or ATOM feed.
+Returns a link tag that browsers and news readers can use to auto-detect an RSS or Atom feed.
<ruby>
auto_discovery_link_tag(:rss, "http://www.example.com/feed.rss", {:title => "RSS Feed"}) # =>
@@ -687,7 +687,7 @@ h4. AtomFeedHelper
h5. atom_feed
-This helper makes building an ATOM feed easy. Here's a full usage example:
+This helper makes building an Atom feed easy. Here's a full usage example:
*config/routes.rb*
diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile
index c30902c237..61fdb5ccc6 100644
--- a/railties/guides/source/active_support_core_extensions.textile
+++ b/railties/guides/source/active_support_core_extensions.textile
@@ -1872,9 +1872,24 @@ The method +multiple_of?+ tests whether an integer is multiple of the argument:
NOTE: Defined in +active_support/core_ext/integer/multiple.rb+.
+h4. +ordinal+
+
+The method +ordinal+ returns the ordinal suffix string corresponding to the receiver integer:
+
+<ruby>
+1.ordinal # => "st"
+2.ordinal # => "nd"
+53.ordinal # => "rd"
+2009.ordinal # => "th"
+-21.ordinal # => "st"
+-134.ordinal # => "th"
+</ruby>
+
+NOTE: Defined in +active_support/core_ext/integer/inflections.rb+.
+
h4. +ordinalize+
-The method +ordinalize+ returns the ordinal string corresponding to the receiver integer:
+The method +ordinalize+ returns the ordinal string corresponding to the receiver integer. In comparison, note that the +ordinal+ method returns *only* the suffix string.
<ruby>
1.ordinalize # => "1st"
diff --git a/railties/guides/source/layouts_and_rendering.textile b/railties/guides/source/layouts_and_rendering.textile
index 5cff2d0893..6ac9645917 100644
--- a/railties/guides/source/layouts_and_rendering.textile
+++ b/railties/guides/source/layouts_and_rendering.textile
@@ -656,7 +656,7 @@ WARNING: The asset tag helpers do _not_ verify the existence of the assets at th
h5. Linking to Feeds with the +auto_discovery_link_tag+
-The +auto_discovery_link_tag+ helper builds HTML that most browsers and newsreaders can use to detect the presences of RSS or ATOM feeds. It takes the type of the link (+:rss+ or +:atom+), a hash of options that are passed through to url_for, and a hash of options for the tag:
+The +auto_discovery_link_tag+ helper builds HTML that most browsers and newsreaders can use to detect the presence of RSS or Atom feeds. It takes the type of the link (+:rss+ or +:atom+), a hash of options that are passed through to url_for, and a hash of options for the tag:
<erb>
<%= auto_discovery_link_tag(:rss, {:action => "feed"},
@@ -667,7 +667,7 @@ There are three tag options available for the +auto_discovery_link_tag+:
* +:rel+ specifies the +rel+ value in the link. The default value is "alternate".
* +:type+ specifies an explicit MIME type. Rails will generate an appropriate MIME type automatically.
-* +:title+ specifies the title of the link. The default value is the upshifted +:type+ value, for example, "ATOM" or "RSS".
+* +:title+ specifies the title of the link. The default value is the uppercased +:type+ value, for example, "ATOM" or "RSS".
h5. Linking to JavaScript Files with the +javascript_include_tag+
@@ -724,7 +724,7 @@ Outputting +script+ tags such as this:
These two files for jQuery, +jquery.js+ and +jquery_ujs.js+ must be placed inside +public/javascripts+ if the application doesn't use the asset pipeline. These files can be downloaded from the "jquery-rails repository on GitHub":https://github.com/indirect/jquery-rails/tree/master/vendor/assets/javascripts
-WARNING: If you are using the asset pipeline, this tag will render a +script+ tag for an asset called +defaults.js+, which would not exist in your application unless you've explicitly defined it to be.
+WARNING: If you are using the asset pipeline, this tag will render a +script+ tag for an asset called +defaults.js+, which would not exist in your application unless you've explicitly created it.
And you can in any case override the +:defaults+ expansion in <tt>config/application.rb</tt>:
diff --git a/railties/guides/source/testing.textile b/railties/guides/source/testing.textile
index e0386b95b4..1e6b92f45c 100644
--- a/railties/guides/source/testing.textile
+++ b/railties/guides/source/testing.textile
@@ -114,25 +114,18 @@ Rails by default automatically loads all fixtures from the +test/fixtures+ folde
* Load the fixture data into the table
* Dump the fixture data into a variable in case you want to access it directly
-h5. Hashes with Special Powers
+h5. Fixtures are ActiveRecord objects
-Fixtures are basically Hash objects. As mentioned in point #3 above, you can access the hash object directly because it is automatically setup as a local variable of the test case. For example:
+Fixtures are instances of ActiveRecord. As mentioned in point #3 above, you can access the object directly because it is automatically setup as a local variable of the test case. For example:
<ruby>
-# this will return the Hash for the fixture named david
+# this will return the User object for the fixture named david
users(:david)
# this will return the property for david called id
users(:david).id
-</ruby>
-
-Fixtures can also transform themselves into the form of the original class. Thus, you can get at the methods only available to that class.
-
-<ruby>
-# using the find method, we grab the "real" david as a User
-david = users(:david).find
-# and now we have access to methods only available to a User class
+# one can also access methods available on the User class
email(david.girlfriend.email, david.location_tonight)
</ruby>