【发布时间】:2023-04-03 21:55:02
【问题描述】:
我有一个允许我动态编写 ruby 代码的 DSL。
Outer 类采用要处理的自定义代码块。
还有一种众所周知的 DSL 方法称为 settings,它可以采用自己的代码块进行配置。
我希望能够在另一个块中创建可重用的方法,并让它们在内部块中可用。
在为这篇文章编写示例代码时,我偶然发现了一种用法,它通过将 self 分配给外部作用域中的 variable 并在子作用域中调用 variable 上的方法。
我宁愿不需要将 self 分配给变量,我注意到如果我尝试在 RSPEC 中做类似的事情,那么我不需要使用 variable = self,我可以在父块,它们在子块中可用,请参见最后一个示例。
类
class Settings
attr_accessor :a
attr_accessor :b
attr_accessor :c
def initialize(&block)
instance_eval(&block)
end
end
class Outer
def initialize(&block)
instance_eval(&block)
end
def build_settings(&block)
Settings.new(&block)
end
end
运行代码
Outer.new do
# Create a method dynamically in the main block
def useful_method
'** result of the useful_method **'
end
x = self
settings = build_settings do
self.a = 'aaaa'
self.b = useful_method() # Throws exception
self.c = x.useful_method() # Works
end
end
运行代码(带有详细的日志记录)
# Helper to colourize the console log
class String
def error; "\033[31m#{self}\033[0m" end
def success; "\033[32m#{self}\033[0m" end
end
# Run code with detailed logging
Outer.new do
# Create a method dynamically in the main block
def useful_method
'** result of the useful_method **'
end
puts "respond?: #{respond_to?(:useful_method).to_s.success}"
x = self
settings = build_settings do
puts "respond?: #{respond_to?(:useful_method).to_s.error}"
self.a = 'aaaa'
begin
self.b = useful_method().success
rescue
self.b = 'bbbb'.error
end
begin
self.c = x.useful_method().success
rescue
self.c = 'cccc'.error
end
end
puts "a: #{settings.a}"
puts "b: #{settings.b}"
puts "c: #{settings.c}"
end
来自运行代码的控制台日志
- 分配给
b会引发异常 - 分配给
c工作正常
RSpec 中不需要指定self 的示例
为什么我可以访问 RSpec DSL 中的有用方法,但不能访问我自己的。
RSpec.describe 'SomeTestSuite' do
context 'create method in this outer block' do
def useful_method
'david'
end
it 'use outer method in this inner block' do
expect(useful_method).to eq('david')
end
end
end
【问题讨论】:
标签: ruby