让我试着解释一下我需要什么,然后也许有人可能会告诉我该怎么做。
我的系统中有一系列实体。它们列在数组中
@entities = [ :component, :email, :form, :library, :page, :project, :resource, :template ]
我使用Slop gem解析命令行,然后我获得 opts 哈希中的所有解析选项以及 args 数组中的其余命令行参数。
args 数组的第一个元素始终是我需要创建来处理命令行输入的实体。为了这个推理,我们假设我正在创建:项目。
现在,我有一个 project.rb 文件,其中包含:
entity_block = lambda { |ent|
ent.entity_type = :project
# All other initialization options
.
.
.
}
在我的主要模块中,我有以下方法:
def self.start(args,opts)
# Saves arguments and options
@arguments = args
@options = opts
# Isolates the entity which will handle the command line request
@entity = @arguments[0]
exit_error(103,@entites) if not @entities.include?(@entity.to_sym)
# Requires the correct block for the entity type
require "entities/#{@entity}"
# Creates the entity class
EmeraldFW::Entity.new(@arguments,@options) do
entity_block
end
end
这是我的 entity.rb 文件:
module EmeraldFW
class Entity
attr_accessor :entity_type, :entity_base_dir
def initialize(args,opts)
@args = args
@opts = opts
end
def execute
puts entity_base_dir
puts "Do something..."
end
end
end
正如您所看到的,我打算做的是在<entity_name>.rb
文件中要求包含该特定实体的特定初始值的文件。
例如,在运行代码后初始化entity_type
。不只是他的,而是所有其他参数,用于识别用户在命令行中提到的特定实体。
碰巧这不起作用。如果是的话,我当然不会在这里打扰你。
我尝试使用#tap
将新创建的Entity对象注入entity_block
定义的lambda块中,如下所示:
EmeraldFW::Entity.new(@arguments,@options).tap do
entity_block
end
我还试图像这样做&entity_block
?
EmeraldFW::Entity.new(@arguments,@options).tap do
&entity_block
end
摘要:那么,我的问题是如何以动态创建实体?
当然我考虑过做
这样的事情的可能性entity_class = "EmeraldFW::#{@entity.capitalize}".split('::').inject(Object) {|o,c| o.const_get c}.new(@arguments,@options)
但首先我想知道这种方式是否可能,以及我在这里缺少什么。
顺便说一句,这是我经常得到的错误:
/home/edvaldo/software/github/emeraldfw21/lib/emeraldfw.rb:34:in `block in start': undefined local variable or method `entity_block' for EmeraldFW:Module (NameError)
答案 0 :(得分:1)
entity_block
是project.rb
中的局部变量。局部变量无法通过require
生存。您必须定义常量(ENTITY_BLOCK
),模块(Entity
),实例变量(@entity_block
)或全局变量($entity_block
)。
其中,模块(或类,作为一种特殊模块)最好。
答案 1 :(得分:1)
如果entity_block
是proc或lambda,如果你只用括号输入它的名字就不会被调用(不像一个典型的方法,它会被调用)。
所以我认为你的问题是你的块永远不会被调用。
请尝试一下:
entity = EmeraldFW::Entity.new(@arguments,@options)
entity_block.call(entity)
# similarly
entity.instance_eval { entity_block.call(self) }
顺便说一句,关于你对tap
的使用 - 看起来你正试图实现一些动态范围,它不会为你做。如果你问我,那真的只是分配变量的语法糖。要获得块的动态范围,您可以使用class_exec
或instance_exec
。但是,如果您明确地将对象作为参数传递并且不尝试重新定义self
,则不必执行此操作。