ボクココ

個人開発に関するテックブログ

普通のクラスをRailsのモデル化する

ども、@kimihomです。

Railsのコアを学習中。新しく知ったことをメモメモ。

Rails Pluginの作成

rails plugin new my_awesome_plugin
      create
      create  README.rdoc
      create  Rakefile
      create  my_awesome_plugin.gemspec
      create  MIT-LICENSE
      create  .gitignore
      create  Gemfile
      create  lib/my_awesome_plugin.rb
      create  lib/tasks/my_awesome_plugin_tasks.rake
      create  lib/my_awesome_plugin/version.rb


      create  test/test_helper.rb
      create  test/my_awesome_plugin_test.rb
      append  Rakefile
  vendor_app  test/dummy
         run  bundle install
...

ここで、 test/dummyに注目。このディレクトリ以下にサンプルのRailsプロジェクトが作成され、testでこのプロジェクトに対してのテストコードが書ける。他は割と gemから作った方法と同じ感じに見受けられる。

Active Model

Active Record と Active Resource の共有するところを保持。

単体のクラスをActive Model化する

module MailForm
  class Base
    include ActiveModel::Conversion
    extend ActiveModel::Naming
    extend ActiveModel::Translation
    include ActiveModel::AttributeMethods
    include ActiveModel::Validations

    def persisted?
      false
    end
  end
end

ActiveModel::AttributeMethods

ActiveModel::AttributeMethods は method_missing を利用して動的に属性を定義できる仕組み。 attribute_method_prefixattribute_method_suffix などをクラス内で定義すれば、 prefix_attribute(attribute) で動的にメソッドを定義できる。まぁ黒魔術なのであまり頻繁には使いたくない感じ。

to_model の定義

モデルであるには、to_modelを定義しなければならない。これはRails の ControllerやView helperにモデルが渡ったとき、直接そのモデルを呼ぶのではなっく、まず初めにto_modelを呼んでモデルを操作する。このメソッドは、 include ActiveModel::Conversion内にて含まれる。

include ActiveModel::Conversion では、そのほかに to_key, to_param, to_partial_pathという重要なメソッドが含まれる。

to_keyform_forなどのView Helperを呼んだときに変換される。dom_iddom_classメソッドによって変換されるHTMLのidとclassが決まる。デフォルトではidとモデルのクラス名がそれぞれ用いられる。

to_param はユニークなURLを作成する上で利用され、デフォルトではモデルのidが用いられる。 link_to post_path(@post) などとすれば、posts/1のようになるが、to_paramに返す値を変えるこどでこの挙動を変えることができる!!

to_partial_path はrender で渡すモデルによって、見に行く部分テンプレートのパスを返す。 デフォルトでPostクラスの場合はposts/postのようになる。モデルのコレクションをrenderする際に、to_partial_pathを定義して render @postのようにすれば、高速でオブジェクトごとに違う部分テンプレートを用意することが可能。

extend ActiveModel::Naming

モデルであるためには、 model_name メソッドが必要。そのメソッドが用意されている、ActiveModel::Namingをextendする。ちなみにモデルになるためのテストケースを書くには、以下のように書く。

require 'test_helper'
require "fixtures/my_model"

class ComplianceTest < ActiveSupport::TestCase
  include ActiveModel::Lint::Tests

  def setup
    @model = MyModel.new
  end

include ActiveModel::Validations

モデルであるためには、errorsメソッドが必要。バリデーションに関するメソッド。ActiveModel::Validationsを取り込むことで、erorrsを始め、valid?, validates などのメソッドをmixinできる。

persisted?

モデルであるためには、persisted?メソッドが必要。form_for @modelした時、persisted?がtrueなら更新するPUT、 falseなら作成するPOSTに変換してくれる。

参考図書(引き続き学習中)

pragprog.com