2

いくつかのレールモデルに、個別のファイルに分割したいロジックがいくつかあります。

具体的には、これはこれらのモデルに固有のロジックであり、モデル間で共有されるものではありません。その場合、私はこのような懸念/ミックスインと質問を知っています。

ここではRubyを扱っているので、複数のクラス定義を用意するのがよいようです。例えば:

# in app/models/user.rb
class User < ActiveRecord::Base
  ...
end

# in app/lib/integrations/ext/user.rb
class User
  ...
end

私がここで直面している問題は、現在、適切な場所にモデル拡張を必要としていることです。自動読み込みのため、モデルと拡張機能を明示的に要求する必要があります。私の現在の最善の努力は、初期化子の内部にユーザーモデルとその拡張機能をプリロードすることです。

# in config/initializers/model_extensions.rb
require_dependency 'models/user'
require_dependency 'integrations/ext/user.rb'

ただし、これにより他のgemで問題が発生します(たとえば、ユーザーモデルがロードされたときにDeviseがロードされない)。

これを行うための良い方法はありますか、それとも私はここでキールを外していますか?Rubyのオープンクラスを利用することは、Rails以外の一般的なイディオムです。

4

3 に答える 3

2

以下を追加しますconfig/application.rb

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

integrations/extこれにより、Railsが必要とするクラスがから自動ロードされます。(これは、DHHの要点にもapp/model/concernsファイルが含まれている方法とまったく同じです)。

(@ denis.pelinが持っているものと一致するように自動ロードを変更しました。これが含まれているのを見逃したintegrations/のでlib/、上記で自動ロードするのに十分なはずです)

于 2012-08-05T02:26:57.450 に答える
1

私が正しく理解していれば、あなたがやろうとしているのはモデルに固有のコード(ミックスインが正しい方法であることを示唆する複数のモデル間では一般的ではありません)をモデルから移動 して、モデルを「薄く」保つことです。モデルに存在する「オフ」に見えるコード。

モデルに少し複雑になりすぎているコードや、モデルに直接座っているだけで間違っているように見えるタスクが含まれているコードを見つけた場合は、でファイルを作成しますlib/(簡略化された)例として、次のようなモデルが与えられます

class User < ActiveRecord::Base

  def self.create_admin!(attrs)
    # complex logic to setup admin user account here
    newly_created_user.deliver_confirmation_email!
  end

  def deliver_confirmation_email!
    # sends email off to user represented by this class instance
  end
end

これは私がモデルにいるのは悪いことのように見えます。しかし、コントローラーのアクションに上記のメソッドのコードが数十行あると、createさらに見栄えが悪くなり、テストが難しくなります。

このコードをに移動しますlib/MyNamespace/user_repo.rb

module MyNamespace
  module UserRepo
    extend self

    def create_admin!(attrs)
      # complex logic to setup admin user account here
      deliver_confirmation_email!(newly_created_user)
    end

    private
      def deliver_confirmation_email!(user)
        # sends email off to user represented by this class instance
      end
  end
end

さて、create私のコントローラーでの私の行動では、呼び出す代わりに

User.create_admin!(params[:user])

代わりに電話します

MyNamespace::UserRepo::create_admin!(params[:user])

は、管理者アカウントMyNamespace::UserRepoのレコードに何が起こるかを管理する責任がUserあり、コントローラーのアクションモデルの両方をきれいに保ちます。MyNamespace::UserRepoこの分離により、テストも簡単になります。

これでも、探しているコードを必要とするレールを取得する際に発生している問題は解決されませんが、おそらく、達成しようとしていることに代わる解決策が提供されます。

于 2012-08-05T19:30:05.900 に答える
0

私のアプリケーションの 1 つで、application.rb次の autoload 行のコメントを外しました。

# config/application.rb
config.autoload_paths += %W(#{config.root}/lib)

lib ディレクトリ内のいくつかのモジュール:

# lib/some_module.rb
module SomeModule
  def some_method
  end
end

モデルへの組み込み:

# app/models/user.rb
class User < ActiveRecord::Base
  include SomeModule
end

現在、ユーザー インスタンスはsome_method

于 2012-08-05T08:27:39.400 に答える