0

我想跳转到一个“导入函数”,它可以是我已经在 lib/import/... 中编写的文件之一。

用户在选择框中选择一个选项,从这个选择中,我想在一个上传的文件上执行特定部分的代码(导入具有不同可能布局的 excel)

我写了这个:

# Loading and executing the template chosen by user at step 1
template_path = 'import/'+params[:template]+'/import.rb'
require template_path
Import.action(filename, session, params, current_project)   

我有几个 import.rb 文件,每个文件都位于一个单独的目录中。其中之一是:

module Import
require 'spreadsheet'

     def Import.action(filepath, session, params, project)
            # My import code
     end
 end

问题是 Rails 总是从lib/firstdirectory/import.rb的第一个目录调用 action 方法

我从来没有到达位于 lib/otherdirectory/import.rb 中的另一个 import.rb 文件

  • 有没有更好的方法来实时执行“跳转到”功能?
  • 为什么 Rails 总是跳转到相同的功能?

编辑 :

我的 application.rb 配置文件包含

config.autoload_paths += Dir["#{config.root}/lib/import/**/"]

编辑 2:

# lib/importer/importer.rb
module Importer
  class Base
    # Whatever common logic the import.rb files have.
  end
end

#lib/importer/Import_test/import_test.rb    Note the Big letter for the directory (constant)
module Importer
  class Import_test < Base
    def self.import
        logger.debug(">>>>>>>>>>>>>  special function Test <<<<<<<<<<<<<<<<<<<<")   
    end
  end
end

# Call from controller
logger.debug "------------------>> "+params[:template]
raise "Invalid input" unless params[:template].constantize.superclass == Importer::Base
params[:template].constantize.import()

params[:template] 返回字符串 Importer::Import_test(大写字母)

我收到错误:NoMethodError(Importer::Import_test:Module 的未定义方法“超类”):app/controllers/import_controller.rb:57:in `step2'

4

2 回答 2

2

您使用第一个目录条目的代码是有意义的。当您引用一个尚未加载其定义的常量时,Rails 会检查autoload_paths相应文件的条目。由于您已经import.rb在第一个目录中拥有该文件,因此您的应用程序会加载该文件。

恕我直言,更好的设计将是:

config.autoload_paths += ["#{config.root}/lib"]

# lib/importer.rb
module Importer
  class Base
    # Whatever common logic the import.rb files have.
  end
end

# lib/importer/foo.rb
module Importer
  class Foo < Base
    def self.import
      # ...
    end
  end
end

# lib/importer/bar.rb
module Importer
  class Bar < Base
    def self.import
      # ...
    end
  end
end

# In your view, a way to identify these:
select_tag :layout, options_for_select({
  "Foo" => "Importer::Foo",
  "Bar" => "Importer::Bar"
})

# In your controller:
raise "Invalid input" unless params[:layout].constantize.superclass == Importer::Base
params[:layout].constantize.import( ... )

更新

Rails 以这种方式查找文件:假设您要使用FooBar::Baz. 如果还FooBar没有,它将加载lib/foo_bar.rb并且应该有一些东西。接下来,它将尝试访问FooBar::Baz. 只有当它还没有(已经在加载之后lib/foo_bar.rb)时,它才会加载lib/foo_bar/baz.rb并且应该有一些东西在那里。

如果您想自己使用autoload_paths而不需要 ruby​​ 文件,请使用 Rails 可以轻松更改为下划线的正确驼峰式大小写的约定。例如,使用不带下划线的驼峰式 ImporterTest 和 havelib/importer/importer_test.rb这样框架将能够找到正确的文件和您的定义。

:-) 祝你好运。

于 2013-02-19T15:57:42.200 回答
0

还有很多更好的方法。我建议对执行操作的对象使用模板名称的哈希值。导入所有导入器,并构造散列。比使用哈希来获取函数并执行它。

于 2013-02-19T15:30:13.273 回答