Rails の Active Record

[Rails](http://rubyonrails.org/) は Webアプリケーションフレームワークです。MVC (Model, View, Controller) にレイヤを分離しています。
Rails の **MVC** にはそれぞれ代表するライブラリ（フレームワーク）があります。 [Active Record](http://railsguides.jp/active_record_basics.html) はその一つです。

* Rails のライブラリの `gemspec` の `summary` を抜粋
    * Models
        * Active Record
            * Object-relational mapper framework (part of Rails).
    * Views
        * Action View
            * Rendering framework putting the V in MVC (part of Rails).
    * Controllers
        * Action Controller (Action Pack)
            * Web-flow and rendering framework putting the VC in MVC (part of Rails).


**Active Record** の *Object-relational mapper* ってなんでしょう！

簡単に説明すると [Ruby on Rails](http://rubyonrails.org/) の [Ruby](https://www.ruby-lang.org) はオブジェクト指向スクリプト言語ですね。
オブジェクト指向(Object-oriented)は実世界をコンピュータの世界に写像するパラダイムです。
実世界のモノは状態を保有します。それを写像したオブジェクトは永続化の必要性が生じます。

永続化にはリレーショナルデータベース(RDB)が広く利用されていますね。
でも **RDB** の基礎となったリレーショナルモデルは数学的なパラダイムなのです。
このパラダイムの違いでインピーダンス・ミスマッチが存在します。

そこでオブジェクトをリレーショナルデータベースにマッピングすることで
親和性を改善する手法が **Object-relational mapping (ORM)**  です。


そのライブラリが [Active Record (Object-relational mapping in Rails)](https://github.com/rails/rails/tree/master/activerecord) です。


## Active Record Pattern

[README](https://github.com/rails/rails/blob/master/activerecord/README.rdoc#philosophy) に [Patterns of Enterprise Application Architecture :Martin Fowler (著)](http://martinfowler.com/books/eaa.html) の [Active Record](http://martinfowler.com/eaaCatalog/activeRecord.html) の実装と書いています。

> An object that wraps a row in a database table or view,
> encapsulates the database access, and adds domain logic on that data.

訳してみました。

```
データベースのテーブルまたはビューの行をオブジェクトにまとわせる,
データベースの読み書きをカプセル化し, そのデータにドメインロジックを追加する.
```

![activeRecordSketch](http://www.martinfowler.com/eaaCatalog/activeRecordSketch.gif)

データベースで `1件` のデータはレコードと呼ばれます。`1件` のレコードでオブジェクトが生成されて
そのオブジェクトにはデータ構造とデータ、さらに振る舞いを保有するデザインパターンです。

データ構造とデータに振る舞いを一体化した、能動的なレコードなので *Active Record* でしょうか。


## Object-oriented Modeling

Object-oriented Modeling and Design :James Rumbaugh (著), Michael Blaha (著), William Premerlani (著) にオブジェクト指向の定義が記されています。

> データ構造と振る舞いが一体となったオブジェクトの集まりとしてソフトウエアを組織化すること

**Active Record** を利用することでオブジェクト指向の定義に沿える **Convention over Configuration** でしょうか。


## Object-relational mapping

**ORM** は [ActiveRecord::Base](https://github.com/rails/rails/blob/master/activerecord/lib/active_record/base.rb) のクラスを継承することでマッピングが得られます。

* `1つ` のテーブルが `1つ` のクラスに対応します。
* `1つ` のレコードが `1つ` のインスタンスに対応します。

| Object    | Relational          |
|-----------|---------------------|
| Class     | Table               |
| Instance  | Record              |
| Attribute | Column              |
| Value     | Field               |
| Message   | Select, Update, ... |


## Layered architecture

* 永続化クラス(ActiveRecord::Base)から派生してドメインクラスを作ります。
* ドメインクラスには抽象化した関心事の責務を記述します。

```
ドメインクラス <-> 永続化クラス <-> データベース
```


## Example

2行でデータベースを操作するだけのドメインクラスを記述できます。
(**Rails 5** では `ActiveRecord::Base` が `ApplicationRecord` になります。)

```ruby
class Product < ActiveRecord::Base
end
```

クラスメソッドやインスタンスメソッドで **SQL** が実行されます。

```ruby
product = Product.find(1)  # SELECT * FROM products WHERE id = 1 LIMIT 1
product.name = "bouquet"   #
product.save               # UPDATE products SET name = "bouquet" WHERE id = 1
```

**DSL** でドメインクラスの関連やフィールドのバリデーションを定義します。

* has_many: 関連付け(アソシエーション)
* composed_of: 値オブジェクトを集約(アグリゲート)
* validates: フィールドを検証(バリデーション)

```ruby
class Customer < ActiveRecord::Base
  has_many :sales_orders
  has_many :products, through: :sales_orders
  composed_of :address, mapping: [%w(address_street street), %w(address_city city)]
  validates :name, presence: true
end

class Address
  attr_reader :street, :city
  def initialize(street, city)
    @street, @city= street, city
  end
end
```

Rails の Active Record でソフトウェアを楽しく、そして速く開発しましょう！

# Tips

**Active Record** は `1つ` のテーブルが `1つ` のクラスに対応する規約です。
単純な原理なのでクラス(テーブル)の責務を適切に分離することになるでしょう。

複雑なものには向かないかもしれませんが、簡単なものには向いています。
*（複雑なことを簡単にすることで対応の幅は広がりますが、難しいことです。）*

ただ簡単であることは大切で、開発者は複雑だったり理解できなかったりすると
継続的な開発を止めて作り直したくなります。でも単純で簡単だと理解してくれる可能性は高くなります。

**ドメインエキスパートもドメインクラスのコードが読めるくらいが理想ですね。**