1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Implement mattr_acessor :default option

This commit is contained in:
Genadi Samokovarov 2017-05-30 16:16:19 +03:00
parent ab4f811d09
commit a5b0c60714
3 changed files with 65 additions and 25 deletions

View file

@ -1,3 +1,12 @@
* Add default option to module and class attribute accessors.
mattr_accessor :settings, default: {}
Works for `mattr_reader`, `mattr_writer`, `cattr_accessor`, `cattr_reader`,
and `cattr_writer` as well.
*Genadi Samokovarov*
* Add `Date#prev_occurring` and `Date#next_occurring` to return specified next/previous occurring day of week.
*Shota Iguchi*

View file

@ -38,13 +38,10 @@ class Module
#
# Person.new.hair_colors # => NoMethodError
#
#
# Also, you can pass a block to set up the attribute with a default value.
# You can set a default value for the attribute.
#
# module HairColors
# mattr_reader :hair_colors do
# [:brown, :black, :blonde, :red]
# end
# mattr_reader :hair_colors, default: [:brown, :black, :blonde, :red]
# end
#
# class Person
@ -52,8 +49,7 @@ class Module
# end
#
# Person.new.hair_colors # => [:brown, :black, :blonde, :red]
def mattr_reader(*syms)
options = syms.extract_options!
def mattr_reader(*syms, instance_reader: true, instance_accessor: true, default: nil)
syms.each do |sym|
raise NameError.new("invalid attribute name: #{sym}") unless /\A[_A-Za-z]\w*\z/.match?(sym)
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
@ -64,14 +60,16 @@ class Module
end
EOS
unless options[:instance_reader] == false || options[:instance_accessor] == false
if instance_reader && instance_accessor
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
def #{sym}
@@#{sym}
end
EOS
end
class_variable_set("@@#{sym}", yield) if block_given?
sym_default_value = (block_given? && default.nil?) ? yield : default
class_variable_set("@@#{sym}", sym_default_value) unless sym_default_value.nil?
end
end
alias :cattr_reader :mattr_reader
@ -107,12 +105,10 @@ class Module
#
# Person.new.hair_colors = [:blonde, :red] # => NoMethodError
#
# Also, you can pass a block to set up the attribute with a default value.
# You can set a default value for the attribute.
#
# module HairColors
# mattr_writer :hair_colors do
# [:brown, :black, :blonde, :red]
# end
# mattr_writer :hair_colors, default: [:brown, :black, :blonde, :red]
# end
#
# class Person
@ -120,8 +116,7 @@ class Module
# end
#
# Person.class_variable_get("@@hair_colors") # => [:brown, :black, :blonde, :red]
def mattr_writer(*syms)
options = syms.extract_options!
def mattr_writer(*syms, instance_writer: true, instance_accessor: true, default: nil)
syms.each do |sym|
raise NameError.new("invalid attribute name: #{sym}") unless /\A[_A-Za-z]\w*\z/.match?(sym)
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
@ -132,14 +127,16 @@ class Module
end
EOS
unless options[:instance_writer] == false || options[:instance_accessor] == false
if instance_writer && instance_accessor
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
def #{sym}=(obj)
@@#{sym} = obj
end
EOS
end
send("#{sym}=", yield) if block_given?
sym_default_value = (block_given? && default.nil?) ? yield : default
send("#{sym}=", sym_default_value) unless sym_default_value.nil?
end
end
alias :cattr_writer :mattr_writer
@ -197,12 +194,10 @@ class Module
# Person.new.hair_colors = [:brown] # => NoMethodError
# Person.new.hair_colors # => NoMethodError
#
# Also you can pass a block to set up the attribute with a default value.
# You can set a default value for the attribute.
#
# module HairColors
# mattr_accessor :hair_colors do
# [:brown, :black, :blonde, :red]
# end
# mattr_accessor :hair_colors, default: [:brown, :black, :blonde, :red]
# end
#
# class Person
@ -210,9 +205,9 @@ class Module
# end
#
# Person.class_variable_get("@@hair_colors") # => [:brown, :black, :blonde, :red]
def mattr_accessor(*syms, &blk)
mattr_reader(*syms, &blk)
mattr_writer(*syms)
def mattr_accessor(*syms, instance_reader: true, instance_writer: true, instance_accessor: true, default: nil, &blk)
mattr_reader(*syms, instance_reader: instance_reader, instance_accessor: instance_accessor, default: default, &blk)
mattr_writer(*syms, instance_writer: instance_writer, instance_accessor: instance_accessor, default: default)
end
alias :cattr_accessor :mattr_accessor
end

View file

@ -12,7 +12,14 @@ class ModuleAttributeAccessorTest < ActiveSupport::TestCase
cattr_accessor(:defa) { "default_accessor_value" }
cattr_reader(:defr) { "default_reader_value" }
cattr_writer(:defw) { "default_writer_value" }
cattr_accessor(:deff) { false }
cattr_accessor(:quux) { :quux }
cattr_accessor :def_accessor, default: "default_accessor_value"
cattr_reader :def_reader, default: "default_reader_value"
cattr_writer :def_writer, default: "default_writer_value"
cattr_accessor :def_false, default: false
cattr_accessor(:def_priority, default: false) { :no_priority }
end
@class = Class.new
@class.instance_eval { include m }
@ -24,6 +31,21 @@ class ModuleAttributeAccessorTest < ActiveSupport::TestCase
assert_nil @object.foo
end
def test_mattr_default_keyword_arguments
assert_equal "default_accessor_value", @module.def_accessor
assert_equal "default_reader_value", @module.def_reader
assert_equal "default_writer_value", @module.class_variable_get(:@@def_writer)
end
def test_mattr_can_default_to_false
assert_equal false, @module.def_false
assert_equal false, @module.deff
end
def test_mattr_default_priority
assert_equal false, @module.def_priority
end
def test_should_set_mattr_value
@module.foo = :test
assert_equal :test, @object.foo
@ -91,9 +113,23 @@ class ModuleAttributeAccessorTest < ActiveSupport::TestCase
assert_equal "default_writer_value", @module.class_variable_get("@@defw")
end
def test_should_not_invoke_default_value_block_multiple_times
def test_method_invocation_should_not_invoke_the_default_block
count = 0
@module.cattr_accessor(:defcount) { count += 1 }
assert_equal 1, count
assert_no_difference "count" do
@module.defcount
end
end
def test_declaring_multiple_attributes_at_once_invokes_the_block_multiple_times
count = 0
@module.cattr_accessor(:defn1, :defn2) { count += 1 }
assert_equal 1, @module.defn1
assert_equal 2, @module.defn2
end
end