如何使用helper对象扩展Ruby库
我正在和你一起扩展。我希望这些方法只能在给它们一些上下文的块中使用。例如,my extension的用法可能如下所示:如何使用helper对象扩展Ruby库,ruby,Ruby,我正在和你一起扩展。我希望这些方法只能在给它们一些上下文的块中使用。例如,my extension的用法可能如下所示: field_row height: 25, units: 8 do text_field field: 'Favorite fruit', # ... end 在我的库中,它的工作方式是field\u row方法实例化一个helper对象,没有它,其他方法,如text\u field,就不会运行: class FieldRow # ... end class Pra
field_row height: 25, units: 8 do
text_field field: 'Favorite fruit', # ...
end
在我的库中,它的工作方式是field\u row
方法实例化一个helper对象,没有它,其他方法,如text\u field
,就不会运行:
class FieldRow
# ...
end
class PrawnRails::Document
attr_accessor :field_row # my helper object
def field_row(height:, units:, &block)
@field_row = FieldRow.new #...
block.call
@field_row = nil
end
def text_field(**args)
unless @field_row.present?
raise ArgumentError, 'Must be inside a field row'
end
# implementation which relies on @field_row...
end
end
是否有更好的方法确保我的方法仅在FieldRow
对象可用时运行?特别是,在block.call
之后必须写入@field\u row=nil
,这让我觉得自己做得不对
是否有更好的方法确保我的方法仅在适当的上下文中运行,例如当FieldRow
对象可用时
这样的API通常用于在实例化对象上调用块内的方法:
module PrawnRailsForms
class FieldRow
def initialize(height:, units:, **)
# ...
end
def text_field(field:, **)
# ...
end
end
module Document
def field_row(**args, &block)
@field_row = FieldRow.new(**args)
@field_row.instance_eval(&block) unless block.nil?
@field_row
end
end
::PrawnRails::Document.include(Document)
end
现在,当您执行此操作时:
doc.field_row(height: 25, units: 8) do
text_field field: 'Favorite fruit'
end
…它将实例化一个具有高度:
和单位:
的FieldRow对象,然后在该对象上调用text\u field
如果需要FieldRow对文档本身进行操作,可以采取以下几种方法。一种方法是将
self
(文档对象)传递给FieldRow的构造函数,并将其存储在其中的实例变量中,供text\u field
等使用:
def field_row(**args, &block)
row = FieldRow.new(self, **args)
row.instance_eval(&block) unless block.nil?
end
您还可以在FieldRow上定义一个方法,将文档对象传递给该方法。在这种情况下,FieldRow的方法(例如,text\u field
)“配置”输出,并render
(或您选择的任何方法)实际创建输出
def field_row(**args, &block)
row = FieldRow.new(**args)
row.instance_eval(&block) unless block.nil?
row.render(self)
end
我要提醒大家不要在文档中添加一堆方法。由于
text\u字段
仅在field\u行
的上下文中起作用,因此将text\u字段
作为文档的实例方法是没有意义的(并且,正如您所发现的,它有一些缺陷)。Hmm,除了text\u字段
需要是PrawnRails::Document
的实例方法之外,因此,它可以对文档进行操作(创建框、添加文本、样式等)。@dfaulken您可能希望探索Prawn本身是如何实现类似方法的,因为它可能有一个既定的约定(甚至是一些方便的功能,您可以借助它),但是我编辑了我的答案,加入了一些可能的解决方案。这是一个很好的建议。谢谢你分享这么多的想法!