0

lib/import/...

ユーザーが選択ボックスでオプションを選択し、この選択から、アップロードされた 1 つのファイルでコードの特定の部分を実行したい (さまざまなレイアウトで 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 ファイルがあります。これらの1つは次のとおりです。

module Import
require 'spreadsheet'

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

問題は、Rails が常にlib/firstdirectory/import.rbの最初のディレクトリからアクション メソッドを呼び出していることです。

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れ、そこに何かがあるはずです。

ruby ファイルを自分で使用したいがautoload_paths必要としない場合は、Rails が簡単にアンダースコアに変更できる適切なキャメルケースを使用するという規則を使用してください。たとえば、アンダースコアなしで camelcase ImporterTest を使用するとlib/importer/importer_test.rb、フレームワークが正しいファイルと定義を見つけられるようになります。

:-) 幸運を。

于 2013-02-19T15:57:42.200 に答える
0

はるかに良い方法があります。アクションを実行するオブジェクトへのテンプレート名のハッシュを持つことをお勧めします。すべてのインポーターをインポートし、ハッシュを構築します。ハッシュを使用して関数を取得し、実行します。

于 2013-02-19T15:30:13.273 に答える