161

私のモデルがいくつかの特別なメソッドを持つように、 ActiveRecord:Base クラスを拡張する方法についていくつか読んだことがあります。それを拡張する簡単な方法は何ですか (ステップバイステップのチュートリアル)?

4

9 に答える 9

337

いくつかのアプローチがあります:

ActiveSupport :: Concernの使用(推奨)

詳細については、ActiveSupport::Concernのドキュメントをお読みください。

active_record_extension.rbディレクトリにというファイルを作成しますlib

require 'active_support/concern'

module ActiveRecordExtension

  extend ActiveSupport::Concern

  # add your instance methods here
  def foo
     "foo"
  end

  # add your static(class) methods here
  class_methods do
    #E.g: Order.top_ten        
    def top_ten
      limit(10)
    end
  end
end

# include the extension 
ActiveRecord::Base.send(:include, ActiveRecordExtension)

config/initializersというディレクトリにファイルを作成し、ファイルにextensions.rb次の行を追加します。

require "active_record_extension"

継承(推奨)

Tobyの回答を参照してください。

モンキーパッチ(避けるべき)

config/initializersというディレクトリにファイルを作成しますactive_record_monkey_patch.rb

class ActiveRecord::Base     
  #instance method, E.g: Order.new.foo       
  def foo
   "foo"
  end

  #class method, E.g: Order.top_ten        
  def self.top_ten
    limit(10)
  end
end

ジェイミー・ザウィンスキーによる正規表現に関する有名な引用は、モンキーパッチに関連する問題を説明するために再利用できます。

問題に直面したとき、「わかっている、モンキーパッチを使う」と考える人もいます。今、彼らは2つの問題を抱えています。

モンキーパッチは簡単かつ迅速です。しかし、節約された時間と労力は常に将来いつか引き戻されます。複利で。最近では、モンキーパッチを制限して、レールコンソールでソリューションのプロトタイプをすばやく作成しています。

于 2010-02-24T20:48:40.130 に答える
69

クラスを拡張して、継承を使用するだけです。

class AbstractModel < ActiveRecord::Base  
  self.abstract_class = true
end

class Foo < AbstractModel
end

class Bar < AbstractModel
end
于 2010-02-24T23:40:47.833 に答える
21

ActiveSupport::Concern次のように、Railsコアをより慣用的に使用して使用することもできます。

module MyExtension
  extend ActiveSupport::Concern

  def foo
  end

  module ClassMethods
    def bar
    end
  end
end

ActiveRecord::Base.send(:include, MyExtension)

[編集]@danielからのコメントに続いて

次に、すべてのモデルに、メソッドfooがインスタンスメソッドとして含まれ、メソッドが ClassMethodsクラスメソッドとして含まれるようになります。たとえば、次のようになりFooBar < ActiveRecord::Baseます。FooBar.barFooBar#foo

http://api.rubyonrails.org/classes/ActiveSupport/Concern.html

于 2012-02-08T19:36:51.973 に答える
21

Rails 4 では、モデルをモジュール化して DRY アップするために懸念を使用するという概念が注目されています。

懸念事項を使用すると、基本的に、モデルの類似コードまたは複数のモデルを 1 つのモジュールにグループ化し、このモジュールをモデルで使用できます。次に例を示します。

Article モデル、Event モデル、Comment モデルを考えてみましょう。記事やイベントには多くのコメントがあります。コメントは、記事またはイベントのいずれかに属します。

伝統的に、モデルは次のようになります。

コメント モデル:

class Comment < ActiveRecord::Base
  belongs_to :commentable, polymorphic: true
end

記事のモデル:

class Article < ActiveRecord::Base
  has_many :comments, as: :commentable 

  def find_first_comment
    comments.first(created_at DESC)
  end

  def self.least_commented
   #return the article with least number of comments
  end
end

イベント モデル

class Event < ActiveRecord::Base
  has_many :comments, as: :commentable 

  def find_first_comment
    comments.first(created_at DESC)
  end

  def self.least_commented
   #returns the event with least number of comments
  end
end

お気づきのように、イベント モデルと記事モデルの両方に共通する重要なコードがあります。懸念を使用して、この共通コードを別のモジュール Commentable に抽出できます。

このために、app/model/concerns に commentable.rb ファイルを作成します。

module Commentable
    extend ActiveSupport::Concern

    included do 
        has_many :comments, as: :commentable 
    end

    # for the given article/event returns the first comment
    def find_first_comment
        comments.first(created_at DESC)
    end

    module ClassMethods     
        def least_commented
           #returns the article/event which has the least number of comments
        end
    end 
end

そして今、あなたのモデルは次のようになります:

コメント モデル:

    class Comment < ActiveRecord::Base
      belongs_to :commentable, polymorphic: true
    end

記事のモデル:

class Article < ActiveRecord::Base
    include Commentable
end

イベント モデル

class Event < ActiveRecord::Base    
    include Commentable
end

懸念を使用する際に強調したい点の 1 つは、懸念は「技術的な」グループ化ではなく、「ドメイン ベースの」グループ化に使用する必要があるということです。たとえば、ドメインのグループ化は「コメント可能」、「タグ付け可能」などです。技術ベースのグループ化は「FinderMethods」、「ValidationMethods」のようになります。

モデルの懸念事項を理解するのに非常に役立つ投稿へのリンクを次に示します。

記事が役立つことを願っています:)

于 2014-09-15T20:59:10.837 に答える
8

ステップ1

module FooExtension
  def foo
    puts "bar :)"
  end
end
ActiveRecord::Base.send :include, FooExtension

ステップ2

# Require the above file in an initializer (in config/initializers)
require 'lib/foo_extension.rb'

ステップ 3

There is no step 3 :)
于 2010-02-24T20:15:45.207 に答える
4

このトピックに追加するために、私はそのような拡張機能をテストする方法を検討するのにしばらく時間を費やしました (私はActiveSupport::Concern道をたどりました.)

拡張機能をテストするためのモデルをセットアップする方法を次に示します。

describe ModelExtensions do
  describe :some_method do
    it 'should return the value of foo' do
      ActiveRecord::Migration.create_table :test_models do |t|
        t.string :foo
      end

      test_model_class = Class.new(ActiveRecord::Base) do
        def self.name
          'TestModel'
        end

        attr_accessible :foo
      end

      model = test_model_class.new(:foo => 'bar')

      model.some_method.should == 'bar'
    end
  end
end
于 2012-10-31T11:22:18.537 に答える
0

私は持っている

ActiveRecord::Base.extend Foo::Bar

イニシャライザで

以下のようなモジュールの場合

module Foo
  module Bar
  end
end
于 2013-03-01T02:03:05.130 に答える