Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions demo/core/module/cattr.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,20 @@
t.c = 50
t.c.assert == 50

## Block defaults

c = Class.new do
cattr_accessor(:setting) { :default }
end

c.setting.assert == :default
c.new.setting.assert == :default

Existing values are left in place.

c = Class.new do
class_variable_set(:@@setting, :existing)
cattr_accessor(:setting) { :default }
end

c.setting.assert == :existing
49 changes: 49 additions & 0 deletions demo/core/module/mattr.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
## Module#mattr

require 'facets/module/mattr'

c = Class.new do
mattr :setting do
:default
end
end

c.setting.assert == :default
c.new.setting.assert == :default

## Module#mattr_reader

c = Class.new do
mattr_reader(:setting) { :default }
end

c.setting.assert == :default
c.new.setting.assert == :default

## Module#mattr_writer

c = Class.new do
mattr_writer(:setting) { :default }
end

c.class_variable_get(:@@setting).assert == :default
c.setting = :changed
c.class_variable_get(:@@setting).assert == :changed

## Module#mattr_accessor

c = Class.new do
mattr_accessor(:setting) { :default }
end

c.setting.assert == :default
c.new.setting.assert == :default

Existing values are left in place.

c = Class.new do
class_variable_set(:@@setting, :existing)
mattr_accessor(:setting) { :default }
end

c.setting.assert == :existing
71 changes: 41 additions & 30 deletions lib/core/facets/module/mattr.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,19 @@ class Module
# @uncommon
# require 'facets/module/cattr'
#
def cattr(*syms)
def cattr(*syms, &block)
writers, readers = syms.flatten.partition{ |a| a.to_s =~ /=$/ }
writers = writers.map{ |e| e.to_s.chomp('=').to_sym }
##readers.concat( writers ) # writers also get readers

cattr_reader(*readers)
cattr_writer(*writers)
cattr_reader(*readers, &block)

if block
cattr_writer(*(writers - readers), &block)
cattr_writer(*(writers & readers))
else
cattr_writer(*writers)
end

return readers + writers
end
Expand All @@ -49,13 +55,13 @@ def cattr(*syms)
# @uncommon
# require 'facets/module/cattr'
#
def cattr_reader(*syms)
def cattr_reader(*syms, &block)
syms.flatten.each do |sym|
module_eval(<<-EOS, __FILE__, __LINE__)
unless defined? @@#{sym}
@@#{sym} = nil
end
unless class_variable_defined?("@@#{sym}")
class_variable_set("@@#{sym}", block ? block.call : nil)
end

module_eval(<<-EOS, __FILE__, __LINE__)
def self.#{sym}
@@#{sym}
end
Expand Down Expand Up @@ -91,13 +97,13 @@ def #{sym}
# @uncommon
# require 'facets/module/cattr'
#
def cattr_writer(*syms)
def cattr_writer(*syms, &block)
syms.flatten.each do |sym|
module_eval(<<-EOS, __FILE__, __LINE__)
unless defined? @@#{sym}
@@#{sym} = nil
end
unless class_variable_defined?("@@#{sym}")
class_variable_set("@@#{sym}", block ? block.call : nil)
end

module_eval(<<-EOS, __FILE__, __LINE__)
def self.#{sym}=(obj)
@@#{sym} = obj
end
Expand Down Expand Up @@ -130,8 +136,8 @@ def #{sym}=(obj)
# @uncommon
# require 'facets/module/cattr'
#
def cattr_accessor(*syms)
cattr_reader(*syms) + cattr_writer(*syms)
def cattr_accessor(*syms, &block)
cattr_reader(*syms, &block) + cattr_writer(*syms)
end

# Creates a class-variable attribute that can
Expand Down Expand Up @@ -159,13 +165,18 @@ def cattr_accessor(*syms)
# @uncommon
# require 'facets/module/mattr'
#
def mattr(*syms)
def mattr(*syms, &block)
writers, readers = syms.flatten.partition{ |a| a.to_s =~ /=$/ }
writers = writers.collect{ |e| e.to_s.chomp('=').to_sym }
##readers.concat( writers ) # writers also get readers

mattr_writer( *writers )
mattr_reader( *readers )
if block
mattr_writer( *(writers - readers), &block )
mattr_writer( *(writers & readers) )
else
mattr_writer( *writers )
end
mattr_reader( *readers, &block )

return readers + writers
end
Expand All @@ -189,13 +200,13 @@ def mattr(*syms)
# @uncommon
# require 'facets/module/mattr'
#
def mattr_reader( *syms )
def mattr_reader( *syms, &block )
syms.flatten.each do |sym|
module_eval(<<-EOS, __FILE__, __LINE__)
unless defined? @@#{sym}
@@#{sym} = nil
end
unless class_variable_defined?("@@#{sym}")
class_variable_set("@@#{sym}", block ? block.call : nil)
end

module_eval(<<-EOS, __FILE__, __LINE__)
def self.#{sym}
@@#{sym}
end
Expand Down Expand Up @@ -232,13 +243,13 @@ def #{sym}
# @uncommon
# require 'facets/module/mattr'
#
def mattr_writer(*syms)
def mattr_writer(*syms, &block)
syms.flatten.each do |sym|
module_eval(<<-EOS, __FILE__, __LINE__)
unless defined? @@#{sym}
@@#{sym} = nil
end
unless class_variable_defined?("@@#{sym}")
class_variable_set("@@#{sym}", block ? block.call : nil)
end

module_eval(<<-EOS, __FILE__, __LINE__)
def self.#{sym}=(obj)
@@#{sym} = obj
end
Expand Down Expand Up @@ -272,8 +283,8 @@ def #{sym}=(obj)
# @uncommon
# require 'facets/module/mattr'
#
def mattr_accessor(*syms)
mattr_reader(*syms) + mattr_writer(*syms)
def mattr_accessor(*syms, &block)
mattr_reader(*syms, &block) + mattr_writer(*syms)
end

end
Expand Down
113 changes: 113 additions & 0 deletions test/core/module/test_mattr.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
covers 'facets/module/mattr'

test_case Module do

method :cattr_reader do

test "uses a block default" do
c = Class.new do
cattr_reader(:setting) { :default }
end

c.setting.assert == :default
c.new.setting.assert == :default
end

test "does not replace an existing value" do
c = Class.new do
class_variable_set(:@@existing_cattr_reader_setting, :existing)
cattr_reader(:existing_cattr_reader_setting) { :default }
end

c.existing_cattr_reader_setting.assert == :existing
end

end

method :cattr_writer do

test "uses a block default for writer-only attributes" do
c = Class.new do
cattr_writer(:setting) { :default }
end

c.class_variable_get(:@@setting).assert == :default
c.setting = :changed
c.class_variable_get(:@@setting).assert == :changed
end

end

method :cattr_accessor do

test "uses a block default once" do
calls = 0
c = Class.new do
cattr_accessor(:cattr_accessor_setting) do
calls += 1
:default
end
end

c.cattr_accessor_setting.assert == :default
c.new.cattr_accessor_setting.assert == :default
calls.assert == 1
end

end

method :mattr_reader do

test "uses a block default" do
c = Class.new do
mattr_reader(:setting) { :default }
end

c.setting.assert == :default
c.new.setting.assert == :default
end

test "does not replace an existing value" do
c = Class.new do
class_variable_set(:@@existing_mattr_reader_setting, :existing)
mattr_reader(:existing_mattr_reader_setting) { :default }
end

c.existing_mattr_reader_setting.assert == :existing
end

end

method :mattr_writer do

test "uses a block default for writer-only attributes" do
c = Class.new do
mattr_writer(:setting) { :default }
end

c.class_variable_get(:@@setting).assert == :default
c.setting = :changed
c.class_variable_get(:@@setting).assert == :changed
end

end

method :mattr_accessor do

test "uses a block default once" do
calls = 0
c = Class.new do
mattr_accessor(:mattr_accessor_setting) do
calls += 1
:default
end
end

c.mattr_accessor_setting.assert == :default
c.new.mattr_accessor_setting.assert == :default
calls.assert == 1
end

end

end