Created
February 23, 2019 14:46
-
-
Save schmidt/c05b90a881856e45a3cba46fc25de858 to your computer and use it in GitHub Desktop.
Meta programming challenge
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Class | |
def reader(*names) | |
names.each do |name| | |
module_eval <<~CODE | |
def #{name} | |
@#{name} | |
end | |
CODE | |
end | |
end | |
end | |
class A | |
def initialize | |
@a = :a | |
@b = :b | |
end | |
private | |
attr_reader :a | |
reader :b | |
end | |
p A.new.a # => test.rb:25:in `<main>': private method `a' called for #<A:0x00007fb5e90b42e8 @a=:a, @b=:b> (NoMethodError) | |
p A.new.b # => :b | |
__END__ | |
How can I achieve, that my newly defined reader methods are also private. | |
I could not figure out how to detect the private block or which API to use, | |
so that the newly defined methods are private by default. |
class Class
def reader(&block)
names = Array(block.call)
names.each do |name|
eval <<~CODE, block.binding
def #{name}
@#{name}
end
CODE
end
end
end
class A
def initialize
@a = :a
@b = :b
end
private
attr_reader :a
reader { :b }
end
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is the only way I could find to make it work:
or, using the
bindings
Gem this can be simplified to