我需要初始化一些我以前不知道它在Ruby中的含义

时间:2016-10-28 05:07:27

标签: ruby class

让我试着解释一下我需要什么,然后也许有人可能会告诉我该怎么做。

我的系统中有一系列实体。它们列在数组中

@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)

2 个答案:

答案 0 :(得分:1)

entity_blockproject.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_execinstance_exec。但是,如果您明确地将对象作为参数传递并且不尝试重新定义self,则不必执行此操作。