[wip]ユーザの管理

# 見て頂きたいものについて(私信)
自分の注意不足などで、このPRはかなり量が膨らんでしまいました。
そのため、以下のものだけ見て頂ければ十分かと思っています。
* [app/controllers/admin/items_controller.rb](https://github.com/onionSoup/tea/blob/admin_user/app/controllers/admin/items_controller.rb)
* [app/controllers/admin/order_details_controller.rb](https://github.com/onionSoup/tea/blob/admin_user/app/controllers/admin/order_details_controller.rb)
* [app/controllers/admin/users_controller.rb](https://github.com/onionSoup/tea/blob/admin_user/app/controllers/admin/users_controller.rb)
* [app/controllers/order_details_controller.rb](https://github.com/onionSoup/tea/blob/admin_user/app/controllers/admin/order_details_controller.rb)
* [config/locales/ja.yml](https://github.com/onionSoup/tea/blob/admin_user/config/locales/ja.yml)
* [app/models/user.rb](https://github.com/onionSoup/tea/blob/admin_user/app/models/user.rb)

この他は、以下のような作業でした。これらは見て頂かなくても大丈夫かと思います。
* CSSを整理する。（SCSSのネストを使っていなかったのを使う）
* ビューを整理する。（文言の統一、長すぎる行の改行、`dom_id`の使用など）
* テスト
* 空白や、式と戻り値の`()`の区別などミスの修正

## UI について
[heroku](http://calm-lowlands-7932.herokuapp.com/) に上げました。
今回は[ユーザー管理ページ](http://calm-lowlands-7932.herokuapp.com/admin/users)を作りました。（ログインが必要です。）

# このPRで特に何をするか
* 管理者がユーザーの管理をできるようにします。
  * ユーザーの削除
  * ユーザーの名前変更
  * ユーザーの注文状況の確認
  * ユーザーの注文明細追加、消去 

 以上を管理者ができるようにします。

ユーザーの注文状況確認は、「ネスレ入力用ページ」「発送待ち商品の確認」の２つのページのUIを変更することで対応します。

# 前回PRではできなかったこと
前回までは、上記の機能がありませんでした。
特にユーザーの注文状況の確認ができないのは大きな欠陥でした。

つまり、どのユーザーが何を注文したかを確認する方法が（お茶が届いたとシステムに知らせるまで）ありませんでした。例えば、
* 「急な出張でお茶を注文したくなくなったであろう人がお茶を注文しているかどうか、管理者として知りたい」
* 「ユーザーとして、お茶の注文を取り消したくなったが、忙しいので管理者にやっていてほしい」

というような事態に対応できませんでした。

# 終了条件（どうしたらWIPが取れるか）
  * [x] 管理者として、ユーザーの削除ができる
  * [x] 管理者として、ユーザーの名前の変更ができる
  * [x] 管理者として、ユーザーごとの注文状況を見ることができる
  * [x] 管理者として、ユーザーの注文明細追加、削除 ができる
  * [x] 以上の機能がテストされてる
  * [ ] 読みやすいコードになっている （特にパーシャルを使ったテンプレートの整理とCSSの整理）
   * レビューで教えて頂いたことを直す

# やらないこと
以下は次回のPRでやります。
* すべてのテンプレートを`Haml`に書き直す。
* 商品管理ページのバリデーション表示を修正する。

# 質問
すみません、こちらの「カウンターキャッシュ」について詳しく教えてください。
自分でやったのは

1. Rails組み込みの`counter_chache`を使う
2. 1対多関係の、子モデルの作成/削除にあわせてカウントアップされる親モデルのカラムを自作する

以上２つです。
１つめの、組み込み`counter_chache` は少し用途が違う気がしました。（間違っていたらすみません。）  
２つめの、自作したものは意図どおり動きましたが、長く、無駄が多く、正規化にも反しています。  
いずれも、moroさんが意図していたものとは違う気がします。  

「カウンターキャッシュ」とはどのようなものでしょうか？（漠然とした質問ですみません。）


# やったこと
（長いので、読み飛ばしてください）
## その1 counter_cacheを学習する

### これは何？
* 親が子を何個持っているかを、親テーブルのカラムに持たせる。
* `Parent.Children.size`が、SQLなしで取得できる。

### 例
|counter_chacheの有無 |  親モデル     |   子モデル    |
|------------------   |-------- |-------  |
| する                | Project | Task    |
| しない              | Blog    | Comment | 

```Ruby
#chacheを使ったのでSQL走らない。
project.tasks.size
=> 1

#chacheを使ってないのでSQL走る。
blog.comments.size
   (0.2ms)  SELECT COUNT(*) FROM "comments"  WHERE "comments"."blog_id" = ?  [["blog_id", 1]]
=> 1
```

組み込みの`counter_cache`は、子を`COUNT(*)`します。  
今回は子（`order_details`）のレコード数ではなく、子（のようなモデル）のカラム(`quantity`)の合計値を欲しいので  使えない気がします。  
#### 子（のようなモデル）が必要な理由
今欲しいのは、`Item`別の`OrderDetail#quantity`の合計値です。  
今あるモデルは

1. `Order`
2. `OrderDetail`
3. `Item`

の３つです。  
`OrderDetail`は、同じ`Order`の子でも別々の`Item`を持ちます。  
そのため、新たなモデルが必要な気がしました。  

## その２ 自作のカウントするカラムをつくる
子のsaveやdestroyに合わせて親のカラムをカウントアップ/ダウンすれば良い

### 親DetailsPerItemモデル
商品ごと（PerItem）の、注文明細の集合（Details）を扱うクラス。  
正確には、「商品`item_id`」と 「購入時価格`then_price`」でGroupByした時の  
各`Details`がもつ`quantity`の和を扱うためのクラス。  

こんな感じのテーブルを持つモデル。

|item_id |  then_price     |   sum_of_quantity    |
|------------------   |-------- |-------  |
|1| 180 | 10    |
|1| 200 | 8     |  
|2| 180 | 12    |
|2| 200 | 6     |  

```Ruby
# == Schema Information
#  item_id         :integer
#  then_price      :integer
#  sum_of_quantity :integer          default(0)
#

class DetailsPerItem < ActiveRecord::Base
  belongs_to :item
  has_many   :order_details
  validates  :item_id, uniqueness: {scope: :then_price }
end
```

### 子OrderDetailモデル
自身の保存、破棄に合わせて親の`sum_of_quantity`をカウントアップ/ダウンする
```Ruby
# == Schema Information
#  details_per_item_id :integer
#  item_id             :integer
#  quantity            :integer
#  then_price          :integer
#

class OrderDetail < ActiveRecord::Base
  belongs_to :order
  belongs_to :details_per_item
  belongs_to :item

  before_save    :add_quantity
  before_destroy :subtract_quantity

  def add_quantity
    details_per_item.sum_of_quantity += quantity
    details_per_item.save!
  end

  def subtract_quantity
    details_per_item.sum_of_quantity -= quantity
    details_per_item.save!
  end
end
```


### 実行例
```Ruby
details_per_item = DetailsPerItem.create(item_id: 1, then_price: 500)                           
=> #<DetailsPerItem id: 3, item_id: 1, then_price: 500, sum_of_quantity: 0>


details_per_item.order_details.create(
  quantity  : 99, 
  item_id   : details_per_item.item_id, 
  then_price: details_per_item.then_price
)
=> #<OrderDetail id: 2, details_per_item_id: 3, item_id: 1, quantity: 3, then_price: 500>

details_per_item.reload
=> #<DetailsPerItem id: 3, item_id: 1, then_price: 500, sum_of_quantity: 99>  #ちゃんと、sum_of_quantity が更新された。

```
とりあえず動きましたが、バグの温床になりそうです...