diff options
17 files changed, 62 insertions, 41 deletions
diff --git a/activerecord/lib/active_record/associations/join_dependency.rb b/activerecord/lib/active_record/associations/join_dependency.rb index 9f183c3e7e..0e4e951269 100644 --- a/activerecord/lib/active_record/associations/join_dependency.rb +++ b/activerecord/lib/active_record/associations/join_dependency.rb @@ -32,7 +32,7 @@ module ActiveRecord @alias_cache[node][column] end - class Table < Struct.new(:node, :columns) + class Table < Struct.new(:node, :columns) # :nodoc: def table Arel::Nodes::TableAlias.new node.table, node.aliased_table_name end diff --git a/activerecord/lib/active_record/enum.rb b/activerecord/lib/active_record/enum.rb index 8fba6fcc35..7ded96f8fb 100644 --- a/activerecord/lib/active_record/enum.rb +++ b/activerecord/lib/active_record/enum.rb @@ -104,7 +104,7 @@ module ActiveRecord super end - class EnumType < Type::Value + class EnumType < Type::Value # :nodoc: def initialize(name, mapping) @name = name @mapping = mapping diff --git a/activerecord/lib/active_record/model_schema.rb b/activerecord/lib/active_record/model_schema.rb index a9bd094a66..e3f304b0af 100644 --- a/activerecord/lib/active_record/model_schema.rb +++ b/activerecord/lib/active_record/model_schema.rb @@ -339,6 +339,9 @@ module ActiveRecord @columns = nil @columns_hash = nil @attribute_names = nil + direct_descendants.each do |descendant| + descendant.send(:reload_schema_from_cache) + end end # Guesses the table name, but does not decorate it with prefix and suffix information. diff --git a/activerecord/lib/active_record/relation/record_fetch_warning.rb b/activerecord/lib/active_record/relation/record_fetch_warning.rb index 14e1bf89fa..0a1814b3dd 100644 --- a/activerecord/lib/active_record/relation/record_fetch_warning.rb +++ b/activerecord/lib/active_record/relation/record_fetch_warning.rb @@ -23,11 +23,13 @@ module ActiveRecord end end + # :stopdoc: ActiveSupport::Notifications.subscribe("sql.active_record") do |*args| payload = args.last QueryRegistry.queries << payload[:sql] end + # :startdoc: class QueryRegistry # :nodoc: extend ActiveSupport::PerThreadRegistry diff --git a/activerecord/lib/active_record/type_caster.rb b/activerecord/lib/active_record/type_caster.rb index 63ba10c289..accc339d00 100644 --- a/activerecord/lib/active_record/type_caster.rb +++ b/activerecord/lib/active_record/type_caster.rb @@ -2,6 +2,6 @@ require 'active_record/type_caster/map' require 'active_record/type_caster/connection' module ActiveRecord - module TypeCaster + module TypeCaster # :nodoc: end end diff --git a/activerecord/lib/active_record/type_caster/connection.rb b/activerecord/lib/active_record/type_caster/connection.rb index 868d08ed44..7ed8dcc313 100644 --- a/activerecord/lib/active_record/type_caster/connection.rb +++ b/activerecord/lib/active_record/type_caster/connection.rb @@ -1,6 +1,6 @@ module ActiveRecord module TypeCaster - class Connection + class Connection # :nodoc: def initialize(klass, table_name) @klass = klass @table_name = table_name diff --git a/activerecord/lib/active_record/type_caster/map.rb b/activerecord/lib/active_record/type_caster/map.rb index 4b1941351c..3a367b3999 100644 --- a/activerecord/lib/active_record/type_caster/map.rb +++ b/activerecord/lib/active_record/type_caster/map.rb @@ -1,6 +1,6 @@ module ActiveRecord module TypeCaster - class Map + class Map # :nodoc: def initialize(types) @types = types end diff --git a/activerecord/test/cases/attributes_test.rb b/activerecord/test/cases/attributes_test.rb index 264b275181..2991ca8b76 100644 --- a/activerecord/test/cases/attributes_test.rb +++ b/activerecord/test/cases/attributes_test.rb @@ -172,5 +172,18 @@ module ActiveRecord assert_equal int_range, klass.type_for_attribute("my_int_range") end end + + test "attributes added after subclasses load are inherited" do + parent = Class.new(ActiveRecord::Base) do + self.table_name = "topics" + end + + child = Class.new(parent) + child.new # => force a schema load + + parent.attribute(:foo, Type::Value.new) + + assert_equal(:bar, child.new(foo: :bar).foo) + end end end diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb index acc3103ac6..b2e59e3970 100644 --- a/activerecord/test/cases/persistence_test.rb +++ b/activerecord/test/cases/persistence_test.rb @@ -966,4 +966,17 @@ class PersistenceTest < ActiveRecord::TestCase widget.reset_column_information end end + + def test_reset_column_information_resets_children + child = Class.new(Topic) + child.new # force schema to load + + ActiveRecord::Base.connection.add_column(:topics, :foo, :string) + Topic.reset_column_information + + assert_equal "bar", child.new(foo: :bar).foo + ensure + ActiveRecord::Base.connection.remove_column(:topics, :foo) + Topic.reset_column_information + end end diff --git a/activesupport/lib/active_support/cache/strategy/local_cache.rb b/activesupport/lib/active_support/cache/strategy/local_cache.rb index 4e2d3e9875..d521061004 100644 --- a/activesupport/lib/active_support/cache/strategy/local_cache.rb +++ b/activesupport/lib/active_support/cache/strategy/local_cache.rb @@ -48,10 +48,6 @@ module ActiveSupport @data.clear end - def fetch(*args, &block) - @data.fetch(*args, &block) - end - def read_entry(key, options) @data[key] end @@ -64,6 +60,10 @@ module ActiveSupport def delete_entry(key, options) !!@data.delete(key) end + + def fetch_entry(key, options = nil) # :nodoc: + @data.fetch(key) { @data[key] = yield } + end end # Use a local cache for the duration of block. @@ -103,11 +103,7 @@ module ActiveSupport protected def read_entry(key, options) # :nodoc: if cache = local_cache - cache.fetch(key) do - entry = super - cache.write_entry(key, entry, options) - entry - end + cache.fetch_entry(key) { super } else super end diff --git a/activesupport/lib/active_support/core_ext/hash/keys.rb b/activesupport/lib/active_support/core_ext/hash/keys.rb index 07a282e8b6..8b2366c4b3 100644 --- a/activesupport/lib/active_support/core_ext/hash/keys.rb +++ b/activesupport/lib/active_support/core_ext/hash/keys.rb @@ -10,7 +10,7 @@ class Hash # # hash.transform_keys.with_index { |k, i| [k, i].join } # => {"name0"=>"Rob", "age1"=>"28"} def transform_keys - return enum_for(:transform_keys) unless block_given? + return enum_for(:transform_keys) { size } unless block_given? result = self.class.new each_key do |key| result[yield(key)] = self[key] @@ -21,7 +21,7 @@ class Hash # Destructively converts all keys using the +block+ operations. # Same as +transform_keys+ but modifies +self+. def transform_keys! - return enum_for(:transform_keys!) unless block_given? + return enum_for(:transform_keys!) { size } unless block_given? keys.each do |key| self[yield(key)] = delete(key) end diff --git a/activesupport/lib/active_support/core_ext/hash/transform_values.rb b/activesupport/lib/active_support/core_ext/hash/transform_values.rb index 9ddb838774..7d507ac998 100644 --- a/activesupport/lib/active_support/core_ext/hash/transform_values.rb +++ b/activesupport/lib/active_support/core_ext/hash/transform_values.rb @@ -9,7 +9,7 @@ class Hash # # { a: 1, b: 2 }.transform_values.with_index { |v, i| [v, i].join.to_i } # => { a: 10, b: 21 } def transform_values - return enum_for(:transform_values) unless block_given? + return enum_for(:transform_values) { size } unless block_given? return {} if empty? result = self.class.new each do |key, value| @@ -21,7 +21,7 @@ class Hash # Destructively converts all values using the +block+ operations. # Same as +transform_values+ but modifies +self+. def transform_values! - return enum_for(:transform_values!) unless block_given? + return enum_for(:transform_values!) { size } unless block_given? each do |key, value| self[key] = yield(value) end diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb index 94e73b6df3..3629f5e64b 100644 --- a/activesupport/test/caching_test.rb +++ b/activesupport/test/caching_test.rb @@ -633,6 +633,13 @@ module LocalCacheBehavior end end + def test_local_cache_fetch + @cache.with_local_cache do + @cache.send(:local_cache).write 'foo', 'bar' + assert_equal 'bar', @cache.send(:local_cache).fetch('foo') + end + end + def test_local_cache_of_write_nil @cache.with_local_cache do assert @cache.write('foo', nil) @@ -1102,11 +1109,11 @@ class CacheStoreLoggerTest < ActiveSupport::TestCase def test_log_with_proc_namespace proc = Proc.new do "proc_namespace" - end + end @cache.fetch('foo', {:namespace => proc}) { 'bar' } assert_match %r{proc_namespace:foo}, @buffer.string end - + def test_mute_logging @cache.mute { @cache.fetch('foo') { 'bar' } } assert @buffer.string.blank? diff --git a/activesupport/test/core_ext/hash/transform_keys_test.rb b/activesupport/test/core_ext/hash/transform_keys_test.rb index 5a0b99e22c..99af274614 100644 --- a/activesupport/test/core_ext/hash/transform_keys_test.rb +++ b/activesupport/test/core_ext/hash/transform_keys_test.rb @@ -18,15 +18,17 @@ class TransformKeysTest < ActiveSupport::TestCase assert_same original, mapped end - test "transform_keys returns an Enumerator if no block is given" do + test "transform_keys returns a sized Enumerator if no block is given" do original = { a: 'a', b: 'b' } enumerator = original.transform_keys + assert_equal original.size, enumerator.size assert_equal Enumerator, enumerator.class end - test "transform_keys! returns an Enumerator if no block is given" do + test "transform_keys! returns a sized Enumerator if no block is given" do original = { a: 'a', b: 'b' } enumerator = original.transform_keys! + assert_equal original.size, enumerator.size assert_equal Enumerator, enumerator.class end diff --git a/activesupport/test/core_ext/hash/transform_values_test.rb b/activesupport/test/core_ext/hash/transform_values_test.rb index 7c33227dc0..114022fbaf 100644 --- a/activesupport/test/core_ext/hash/transform_values_test.rb +++ b/activesupport/test/core_ext/hash/transform_values_test.rb @@ -47,15 +47,17 @@ class TransformValuesTest < ActiveSupport::TestCase assert_nil mapped[:b] end - test "transform_values returns an Enumerator if no block is given" do + test "transform_values returns a sized Enumerator if no block is given" do original = { a: 'a', b: 'b' } enumerator = original.transform_values + assert_equal original.size, enumerator.size assert_equal Enumerator, enumerator.class end - test "transform_values! returns an Enumerator if no block is given" do + test "transform_values! returns a sized Enumerator if no block is given" do original = { a: 'a', b: 'b' } enumerator = original.transform_values! + assert_equal original.size, enumerator.size assert_equal Enumerator, enumerator.class end diff --git a/guides/source/active_record_migrations.md b/guides/source/active_record_migrations.md index 67881e6087..5aa5dc4f60 100644 --- a/guides/source/active_record_migrations.md +++ b/guides/source/active_record_migrations.md @@ -454,8 +454,6 @@ number of digits after the decimal point. are using a dynamic value (such as a date), the default will only be calculated the first time (i.e. on the date the migration is applied). * `index` Adds an index for the column. -* `required` Adds `required: true` for `belongs_to` associations and -`null: false` to the column in the migration. Some adapters may support additional options; see the adapter specific API docs for further information. diff --git a/guides/source/active_record_validations.md b/guides/source/active_record_validations.md index dd4d9f55fa..fe42cec158 100644 --- a/guides/source/active_record_validations.md +++ b/guides/source/active_record_validations.md @@ -457,21 +457,6 @@ class Person < ActiveRecord::Base end ``` -This helper counts characters by default, but you can split the value in a -different way using the `:tokenizer` option: - -```ruby -class Essay < ActiveRecord::Base - validates :content, length: { - minimum: 300, - maximum: 400, - tokenizer: lambda { |str| str.split(/\s+/) }, - too_short: "must have at least %{count} words", - too_long: "must have at most %{count} words" - } -end -``` - Note that the default error messages are plural (e.g., "is too short (minimum is %{count} characters)"). For this reason, when `:minimum` is 1 you should provide a personalized message or use `presence: true` instead. When |