2012-02-13 7 views
1

application_controller.rbは、このクラスからすべて継承しているので、すべてのコントローラで使用可能にしたいすべてのメソッドなどを置くことができると思います。すばらしいです。モデルのApplicationControllerに相当するRails

しかし、モデルと同等のものは何ですか?言い換えれば、私は、私のモデルが継承するいくつかのスーパークラスを作ることができる場所がほしいと思う。

たとえば、私は、MYSqlのREGEXPを介してすべてのCAPSのエントリの異なるテーブルを検索するメソッドを持っています。メソッドを一度しか作成せずに、別のテーブルやモデルを呼び出すことができるようにしたいと思います。

これを行うRailsの方法は何ですか?

ActiveRecord :: Base(すべてのモデルがそうであるように)から継承するクラスを作成し、メソッドをそこに配置し、そのクラスからすべてのモデルを継承できると思っていました。しかし、確かにそれを行うためのより良い方法だろうと思った。

ありがとうございました。セミヨンの答えパー

編集

私が使用していたルートを表示するポストを編集しています。それが動作するようになりました:Configで

# models/dvd.rb 
require 'ModelFunctions' 
class Dvd < ActiveRecord::Base 
    extend ModelFunctions 
    ... 
end 

# lib/ModelFunctions.rb 
module ModelFunctions 
    def detect_uppercase(object) 
     case object 
     ... 
     where("(#{field} COLLATE utf8_bin) REGEXP '^[\w[:upper:]]{5,}' ").not_locked.reorder("LENGTH(#{field}), #{table}.#{field} ASC") 
    end 
end 

/application.rb

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

'require 'を使わないでくださいmodel_common'' - ' include ModelCommon'; http://stackoverflow.com/questions/318144/what-is-the-difference-between-include-and-require-in-ruby – Thilo

+0

Thiloさん、ありがとうございました。あなたの答えのリンクはrequireを使用すると言いました。それが私が試した理由ですそれ。しかし、ModelCommonを含めると、このエラーが発生します: 'ModelCommon'を定義するために'期待される.../app/models/model_common.rb '。私はあなたがファイルを '必要とする 'と思って、メソッドを'インクルード'しました。それは間違っていますか? – kakubei

答えて

1

Dvdクラスの横のモジュールに再利用可能なメソッドを配置します。後で別のファイルに移動することができます。

# app/models/dvd.rb 
module CaseInsensitiveSearch 
    def case_insensitive_search(field, value) 
    # searching field for value goes here 
    end 
end 

class Dvd 
end 

モジュールでクラスを拡張した後、クラスでcase_insensitive_searchを使用できます。モジュールを含めることで、case_insensitive_searchはあなたが望むものではないインスタンスメソッドになります。

class Dvd 
    extend CaseInsensitiveSearch 
end 

Dvd.case_insensitive_search("title", "foo") 

もちろんDvdクラス内で使用できます。

class Dvd 
    def self.search(query) 
    case_insensitive_search("title", query) 
    end 
end 

Dvd.search("foo") 

これが機能することを確認したら、別のファイルに移動して複数のクラスにまたがって使用することをお勧めします。 lib/case_insensitive_search.rbに置き、config/applicationにこの行があることを確認してください。RB:

require 'case_insensitive_search' 

class Dvd 
    extend CaseInsensitiveSearch 
end 

私がお勧めしたい最後のことを:

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

今、あなたはどこでもあなたがそれを使用することを要求することができます。意味のある名前で複数のモジュールを作成します。したがって、CommonModelの代わりにCaseInsensitiveSearchなどがあります。

+0

これは最初の考え方に戻ります:これらのメソッドを使ってファイルを作成し、すべてのモデルがそのファイル/クラスから継承します。これは正しいです? – kakubei

+0

いいえ、クラスだけでなく、ファイルに必要なコードを置くことができます。メソッドをファイルの外部で使用できるようにするには、モジュールを定義し、内部にメソッドを配置します。 –

+0

ここにメソッドを置くことはできません。同じモジュールにそれらをラップする必要があります。CaseInsensitiveSearch;終わりの事。そして、あなたはDvdクラスで同じ 'extend CaseInsensitiveSearch'を行います。新しいクラスも継承もありません。 –

2

がここたとえば、ミックスインを見てみましょう:

http://ruby-doc.org/docs/ProgrammingRuby/html/tut_modules.html

を作成した可能性がRailsのアプリであなたのメソッドを定義するlibディレクトリ内のモジュールと、それからあなたのモデルのincludeです。

EDIT:具体例として、クラスメソッドを定義しようとしています。あなたは、モデル内のinclude Common、そのモデルのクラスは、新しいクラスのメソッドを含むように拡張されたときに今

module Common 
    module ClassMethods 
    def detect_uppercase(object) 
     case object 
     when 'dvd' 
      field = 'title' 
     ... 
     end  
     where("(#{field} COLLATE utf8_bin) REGEXP '^[\w[:upper:]] {5,}').not_locked.reorder('LENGTH(title), title ASC')" 
    end 
    end 

    def self.included(base) 
    base.extend(ClassMethods) 
    end 
end 

を、あなたはDvd.detect_uppercaseを呼び出すことができる必要があります:あなたは、このようなミックスインでこれを行うことができます。

+0

はい、mix-insはActiveRecordのイデオロギーに適合していて、ある種の機能を共有しています。スーパークラスからの継承は、Singeテーブル継承パターンの使用 – Anatoly

+0

にとっては意味があります。これは有望です。 mixinを使って、それを呼び出すモデルに基づいて特定のパラメータを変更するメソッドを作成できましたか?私はそれを試してみましょう。ありがとう。 – kakubei

+0

これは有望ですが、編集時に 'Dvd.detect_uppercase( 'dvd')'を呼び出すと、最新のエラーは次のようになります: 'NameError:初期化されていない定数Common :: ClassMethods' – kakubei

関連する問題