Assets.github.com%2fimages%2fgravatars%2fgravatar-user-420

長くなりがちなRailsのモデルをきれいに分割する Edit

  • yusabana
  • nekogeruge_987
  • kwappa
  • idkazuma
  • futoase@github
  • miio@github
  • uzuki05
  • zen3324
  • tak0303
  • drillbits
  • snaka@github
  • kou66-m@github
  • GenTamura84
  • m_doi
  • Narikazu3
  • HaaseDakker@github
  • ainame
  • Konboi@github
  • somewhatgood@github
  • Warp013
Edit

FrogApps 技術ブログ始めました!
RailsやiOS、HTML5の情報を発信中!! → http://qiita.com/teams/frogapps


Railsでアプリを作っていると、app/models/以下にあるモデルファイルの行数が非常に長くなることになります。

そこでincludeメソッドを使ってモデルファイルを機能毎に分割してみましょう。

ファインダー関係のメソッドだけを、user/finder.rbに切り出します。
このときクラスメソッド関係は通常の定義方法が異なります。

クラスメソッドの定義は、ClassMethodsモジュールの中で行う様にします。

has_many, belongs_toなどのクラスメソッドの実行は、self.includedの中でbase.has_manyの様にして呼び出します。

app/models/user.rb
class User < ActiveRecord::Base
   include User::Finder
end
app/models/user/finder.rb
module User::Finder
  def self.included(base)
    base.extend ClassMethods

    # クラスメソッドの呼び出し
    base.has_many :items
  end

  # クラスメソッドの定義
  module ClassMethods
    def hot
      ...
    end
  end

  # インスタンスメソッドの定義
  def search(str)
    ...
  end
end

このようにしてファイルを分けることで、モデルファイルが大きくなるのを避けられ機能毎に整理することができます。

Icon-ok
10 users said this post was useful/correct.


ActiveSupport::Concernというのを使っておくと色々便利で、書きやすくなる他、User::Finderの中でUser::Finder::Basicをincludeするというように、User::Finderを更に分割したくなった時も対応できるようになります。
http://api.rubyonrails.org/classes/ActiveSupport/Concern.html

コードは以下のようになると思います。

module User::Finder
  extend ActiveSupport::Concern

  included do
    # Userモデルに書きたい中身をここにそのまま書けばOK
    has_many :items
    def self.hot
      …
    end
    def search(str)
      ...
    end
  end

  # クラスメソッドの定義方法その2
  module ClassMethods
    def hot2
      ...
    end
  end

  # インスタンスメソッドの定義方法その2
  def search2(str)
    ...
  end
end

ちなみにConcernのコードは短いのでRails使ってない人もパクるといいと思います。
https://github.com/rails/rails/blob/master/activesupport/lib/active_support/concern.rb

こんなメソッドあったんですね!
ありがとうございます!

ActiveSupport::Concernの意味と歴史のTweetをまとめてみました。

http://togetter.com/li/443850

Sign up and follow masuidrive :)

Sign up with GitHub/Twitter

x close