diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index bb66b0ffa2dc3b452eaf0cec13a2b5f439a27fdf..95253567c08a27d596dbed389efc6ba9c0ec4203 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,14 @@ +* Unify `cattr_*` interface: allow to pass a block to `cattr_reader`. + + Example: + + class A + cattr_reader(:defr) { 'default_reader_value' } + end + A.defr # => 'default_reader_value' + + *Alexey Chernenkov* + * Improved compatibility with the stdlib JSON gem. Previously, calling `::JSON.{generate,dump}` sometimes causes unexpected diff --git a/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb b/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb index 34859617c98572f936572755d0ac98b4f7de4932..6daa828b24e7f4ee52d0069666d2a3b3ca52b3d5 100644 --- a/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb +++ b/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb @@ -29,6 +29,16 @@ class Class # end # # Person.new.hair_colors # => NoMethodError + # + # Also, you can pass a block to set up the attribute with a default value. + # + # class Person + # cattr_reader :hair_colors do + # [:brown, :black, :blonde, :red] + # end + # end + # + # Person.hair_colors # => [:brown, :black, :blonde, :red] def cattr_reader(*syms) options = syms.extract_options! syms.each do |sym| @@ -50,6 +60,7 @@ def #{sym} end EOS end + class_variable_set("@@#{sym}", yield) if block_given? end end diff --git a/activesupport/test/core_ext/class/attribute_accessor_test.rb b/activesupport/test/core_ext/class/attribute_accessor_test.rb index 0d5f39a72b4241b27c5155f754970d7d324d8d48..3bc948f3a64a886aaffbdaf7d1d4b71a9249c503 100644 --- a/activesupport/test/core_ext/class/attribute_accessor_test.rb +++ b/activesupport/test/core_ext/class/attribute_accessor_test.rb @@ -8,6 +8,9 @@ def setup cattr_accessor :bar, :instance_writer => false cattr_reader :shaq, :instance_reader => false cattr_accessor :camp, :instance_accessor => false + cattr_accessor(:defa) { 'default_accessor_value' } + cattr_reader(:defr) { 'default_reader_value' } + cattr_writer(:defw) { 'default_writer_value' } end @object = @class.new end @@ -58,4 +61,10 @@ def test_should_raise_name_error_if_attribute_name_is_invalid end assert_equal "invalid class attribute name: 1nvalid", exception.message end + + def test_should_use_default_value_if_block_passed + assert_equal 'default_accessor_value', @class.defa + assert_equal 'default_reader_value', @class.defr + assert_equal 'default_writer_value', @class.class_variable_get('@@defw') + end end diff --git a/guides/source/active_support_core_extensions.md b/guides/source/active_support_core_extensions.md index 648036fb3fd47e3c4f31f5c441f948f5d280ea56..84a169b3b93cdc4de7a4ad26d5bebc3242b6ca12 100644 --- a/guides/source/active_support_core_extensions.md +++ b/guides/source/active_support_core_extensions.md @@ -1093,6 +1093,15 @@ end we can access `field_error_proc` in views. +Also, you can pass a block to `cattr_*` to set up the attribute with a default value: + +```ruby +class MysqlAdapter < AbstractAdapter + # Generates class methods to access @@emulate_booleans with default value of true. + cattr_accessor(:emulate_booleans) { true } +end +``` + The generation of the reader instance method can be prevented by setting `:instance_reader` to `false` and the generation of the writer instance method can be prevented by setting `:instance_writer` to `false`. Generation of both methods can be prevented by setting `:instance_accessor` to `false`. In all cases, the value must be exactly `false` and not any false value. ```ruby