Rails / libモジュールと


83

open_flash_chartプラグインのカスタムラッパーを書いています。に配置さ/libれ、モジュールとしてにロードされますApplicationController

ただし、クラス階層またはsmthの問題があります。

どのコントローラーからでも、などのopen_flash_chart機能にアクセスできますOpenFlashChartLine

ただし、/libモジュール内のクラスでは機能しません。

何か案は?


これはあなたが役立つことを願っstackoverflow.com/questions/17304110/...
S.Yadav

回答:


147

Railsにファイルをロードする方法は2つあります。

  • 自動ロードプロセスに登録され、ファイル名に対応する定数を参照します。たとえば、app/controllers/pages_controller.rbPagesControllerを持っていて参照している場合、app/controllers/pages_controller.rbは自動的に読み込まれます。これは、ロードパス内のディレクトリのプリセットリストで発生します。これはRailsの機能であり、通常のRubyロードプロセスの一部ではありません。
  • ファイルは明示的にrequiredです。ファイルがrequiredの場合、Rubyはロードパス内のパスのリスト全体を調べ、dファイルがロードパス内にある最初のケースを見つけrequireます。$ LOAD_PATH($:のエイリアス)を調べると、ロードパス全体を確認できます。

以来lib、あなたのロードパスにある、2つのオプションがあります。Railsは自動的にあなたが質問に定数を参照するときにそれらを拾う、または明示的にモジュールが必要になりますので、どちらか、定数と同じ名前のファイルに名前を付けます。

また、あなたが別のことについて混乱しているかもしれないことに気づきました。ApplicationControllerは、システムのルートオブジェクトではありません。観察する:

module MyModule
  def im_awesome
    puts "#{self} is so awesome"
  end
end

class ApplicationController < ActionController::Base
  include MyModule
end

class AnotherClass
end

AnotherClass.new.im_awesome
# NoMethodError: undefined method `im_awesome' for #<AnotherClass:0x101208ad0>

モジュールを使用するクラスに含める必要があります。

class AnotherClass
  include MyModule
end

AnotherClass.new.im_awesome
# AnotherClass is so awesome

もちろん、そもそもモジュールを含めることができるようにするには、モジュールを使用可能にする必要があります(上記のいずれかの手法を使用)。


2
追加したかっただけです:/ lib(またはautoloadディレクトリの1つ)にあるモジュールの1つがすでに定義されている場合; たとえば、ActiveRecordまたはStringをオーバーロードする場合は、明示的に要求する必要があります。そうしないと、ロードされません
Mike

1
奇妙なことに、事前に「ga_client」が必要でない限り、初期化されていない定数GaClient(NameError)が発生します(クラスはlib / ga_client.rbで定義されています)。自動ロード命名スキームのドキュメントはありますか?
mkirk 2011

87

Rails 3では、/ libモジュールは自動的にロードされません。

これは、次の行が原因です。

# config.autoload_paths += %W(#{config.root}/extras)

config /application.rb内にコメントがあります。

この行のコメントを解除するか、(私にとってはさらにうまく機能しました)、これをコメントのままにして(将来の参照用に)、次の2行を追加してみてください。

config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]

これにより../libApplicationName::Application.config.autoload_paths配列内のパスが複製されます。
jibiel 2012年

1
@jibielでは、ここでの解決策は何ですか?
イルミネート2012

4
なぜ後者のオプションがあなたにとってよりうまく機能したのですか?また、なぜデフォルトが変更されたのですか...多くの人が回避策を見つけているにもかかわらず、理由があるに違いありません。
ckarbass 2012年

@ylluminateだから、シングルconfig.autoload_paths += Dir["#{config.root}/lib/**/"]で十分なはずです。@ckarbass 2行目では、ユーティリティをサブフォルダに整理して、モジュールを名前空間で自由に整理できます。それはほとんどそれです。そして、これがデフォルトが変更された理由です。決して遅くなるよりはましだ:)
jibiel 2014年

これは私には少し厄介なようです。これは、レーキタスクを不必要に自動ロードしませんか?
デニス

22

config.autoload_pathsのコメントを外す(私はRails 3.1.3を使用しています)以外に、私にとってうまくいったのは、次のような初期化子を作成することでした。

#config/initializers/myapp_init.rb
require 'my_module'    
include MyModule

このようにして、mymoduleメソッドをどこからでも、クラスメソッドModel.mymodule_methodまたはインスタンスメソッドとして呼び出すことができます。mymodel.mymodule_method

たぶん、一部の専門家はこれの意味を説明するかもしれません。今では、自己責任で使用してください。

編集:その後、私はより良いアプローチは次のようになると思います:

次のような初期化子を作成します。

#config/initializers/myapp_init.rb
require ‘my_module’

次のように、必要に応じてモジュールを含めます。

1)「クラスメソッド」として使用する場合は、「extend」を使用します。

class Myclass < ActiveRecord::Base
   extend MyModule
   def self.method1
      Myclass.my_module_method
   end
end

2)「インスタンスメソッド」として使用する場合は、クラス定義内に含めます。

class Myclass < ActiveRecord::Base
include MyModule
   def method1
      self.my_module_method 
   end
end

3)最初に必要となるロードパスinclude MyModule内のファイルを参照していることを忘れないmy_module.rbでください


3
モジュールをlibフォルダに作成したのでconfig.autoload_paths += %W(#{config.root}/lib)config/application.rbファイルに追加しました。その後、私はあなたの提案に従ってconfig/initializers/myapp_init.rbファイルとその内容を追加しました。すべてが良いです。
どうも

にもかかわらず、require私のために動作し、オートローディングは、(未定義のモジュール方式)しません、このコメントは、あなたが使うべきではないと言いますrequire
デニス

3

lib/my_module.rbモデルとコントローラーでモジュールを使用するには:

config/application.rb

config.watchable_dirs['lib'] = [:rb]

モデル内(コントローラーの同様のアイデア):

require_dependency 'my_module'

class MyModel < ActiveRecord::Base
  include MyModule

  MyModule.some_method
end

この方法については、http://hakunin.com/rails3-load-pathsで詳しく説明されています。


0

アプリケーションの初期化時に、libディレクトリの下のファイルを明示的にロードしたい場合があります。
私のconfig / application.rbには、次のようなエントリ
config.autoload_paths += %W(#{config.root}/lib)

があります。また、モジュール名/階層がファイル内と同じでない場合や、ファイルの場所/名前がその階層と同じでない場合もあるため、自動ロードします。そのファイルのも不可能です。したがって、config / application.rbの下部にとしてエントリを追加すると、
require "./lib/file_name_without_extention
正常に機能しました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.