Skip to content
This repository
Browse code

Add Module#attr_accessor_with_default to initialize value of attribut…

…e before setting it. Closes #6538. [Stuart Halloway, Marcel Molina Jr.]

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@5539 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
commit 309a6bd550281b60f25be28ea76a5cce5f9b377b 1 parent 0100a79
Marcel Molina authored
2  activesupport/CHANGELOG
... ... @@ -1,5 +1,7 @@
1 1 *SVN*
2 2
  3 +* Add Module#attr_accessor_with_default to initialize value of attribute before setting it. Closes #6538. [Stuart Halloway, Marcel Molina Jr.]
  4 +
3 5 * Hash#to_xml handles keys with the same name as Kernel methods. #6613 [Catfish]
4 6
5 7 * Added Time#end_of_day to get 23:59:59 of that day [DHH]
1  activesupport/lib/active_support/core_ext/module.rb
... ... @@ -1,6 +1,7 @@
1 1 require File.dirname(__FILE__) + '/module/inclusion'
2 2 require File.dirname(__FILE__) + '/module/attribute_accessors'
3 3 require File.dirname(__FILE__) + '/module/attr_internal'
  4 +require File.dirname(__FILE__) + '/module/attr_accessor_with_default'
4 5 require File.dirname(__FILE__) + '/module/delegation'
5 6 require File.dirname(__FILE__) + '/module/introspection'
6 7 require File.dirname(__FILE__) + '/module/loading'
31 activesupport/lib/active_support/core_ext/module/attr_accessor_with_default.rb
... ... @@ -0,0 +1,31 @@
  1 +class Module
  2 + # Declare an attribute accessor with an initial default return value.
  3 + #
  4 + # To give attribute <tt>:age</tt> the initial value <tt>25</tt>:
  5 + #
  6 + # class Person
  7 + # attr_accessor_with_default :age, 25
  8 + # end
  9 + #
  10 + # some_person.age
  11 + # => 25
  12 + # some_person.age = 26
  13 + # some_person.age
  14 + # => 26
  15 + #
  16 + # To give attribute <tt>:element_name</tt> a dynamic default value, evaluated
  17 + # in scope of self:
  18 + #
  19 + # attr_accessor_with_default(:element_name) { name.underscore }
  20 + #
  21 + def attr_accessor_with_default(sym, default = nil, &block)
  22 + raise 'Default value or block required' unless default || block
  23 + define_method(sym, block_given? ? block : Proc.new { default })
  24 + module_eval(<<-EVAL, __FILE__, __LINE__)
  25 + def #{sym}=(value)
  26 + class << self; attr_reader :#{sym} end
  27 + @#{sym} = value
  28 + end
  29 + EVAL
  30 + end
  31 +end
30 activesupport/test/core_ext/module/attr_accessor_with_default.rb
... ... @@ -0,0 +1,30 @@
  1 +require File.dirname(__FILE__) + '/../../abstract_unit'
  2 +
  3 +class AttrWithDefaultTest < Test::Unit::TestCase
  4 + def setup
  5 + @target = Class.new do
  6 + def helper
  7 + 'helper'
  8 + end
  9 + end
  10 + @instance = @target.new
  11 + end
  12 +
  13 + def test_default_arg
  14 + @target.attr_accessor_with_default :foo, :bar
  15 + assert_equal(:bar, @instance.foo)
  16 + @instance.foo = nil
  17 + assert_nil(@instance.foo)
  18 + end
  19 +
  20 + def test_default_proc
  21 + @target.attr_accessor_with_default(:foo) {helper.upcase}
  22 + assert_equal('HELPER', @instance.foo)
  23 + @instance.foo = nil
  24 + assert_nil(@instance.foo)
  25 + end
  26 +
  27 + def test_invalid_args
  28 + assert_raise(RuntimeError) {@target.attr_accessor_with_default :foo}
  29 + end
  30 +end

0 comments on commit 309a6bd

Please sign in to comment.
Something went wrong with that request. Please try again.