インターン 4日目(2月1日)

# TODO 
- 管理画面から申し込み一覧、申し込み詳細にいける。
- そこから写真の納品ができる
- 写真の納品はただuploadできるだけでなく、一気に複数枚アップロードできる
- そして、納品一覧ページではアップロードした写真の一枚だけサムネイルとして表示され、クリックするとアップロードした全てのファイルが見れる。
- 納品してアップロードした写真は,`homes/top.html.erb`で表示される。


# １から行こう
## 管理画面から申し込み一覧、申し込み詳細にいける。

復習

```ruby:app/config/routes.rb
...
namespace :admin do
  resources :order
end
```

`/admin/order`から管理画面にアクセスできるようにする。

この場合のコントローラーとビューには気をつけなければならないことがある。
Controllerは`adminディレクトリ`を作成し、その中に`order_controller.rb`を作る。
その時に作るClassにも注意、以下のようにする。

```ruby:app/controllers/admin/order_controller.rb
class Admin::OrderController < ApplicationController
  def index
    @order = Inquiry.all
  end
  def show
    @order = Inquiry.find(params[:id])
  end
end
```

のようにただ、`OrderController < ApplicationController`にするのではない。
=> `Admin::OrderController < ApplicationConroller`のようにする。

Viewも`adminディレクトリ`の中に`orderディレクトリ`を作り、その中に`index.html.erb`と`show.html.erb`を作成する。
こちらは申し込み一覧画面。名前を押すと詳細管理画面へ飛べる。

```ruby:app/views/admin/order/index.html.erb
<h1>管理画面です</h1>
<% @order.each do |order| %>
  <p>名前</p>
  <span>
    <%= link_to order.name, admin_order_path(order.id) %>
  </span>
  <p>電話番号</p>
  <span><%= order.phone_number %></span>
  <p>メールアドレス</p>
  <span><%= order.mail %></span>
<% end %>
```
詳細画面から納品画面へを押せば、アップロード画面へ飛べる。

```ruby:app/views/admin/order/show.html.erb
<h1>詳細管理画面です。</h1>
<h1>名前</h1>
<%= @order.name %>
<h1>電話番号</h1>
<%= @order.phone_number %>
<h1>メールアドレス</h1>
<%= @order.mail %>

<%= link_to '納品画面へ' ,uploader_form_path %>

```

# 2. そこから写真の納品ができる。

[gemとして、CarrierWaveを利用する](https://qiita.com/ryo-ichikawa/items/9ea8a03d78dbaa3106f4)
### 1.Gemfileをインストール

```ruby:Gemfile
gem 'carrierwave'
```

`$ bundle install`

### 2.uploaderクラスを作成

CarreirWaveでは uploader というジェネレータが提供されるので、任意の名前でクラスを作成。
以下では、uploadfileという名前でuploadクラスを生成。

`$ rails g uploader UploadFile`
これによって生成されるのは

```ruby:app/uploaders/upload_file_uploader.rb
class ImageUploader < CarrierWave::Uploader::Base

  storage :file

  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end
end
```


###画像の保存のために、Storeモデルを作成し、このモデルクラスにuploaderを設定
storeというモデルクラスに、imageというstring型のカラムを追加する。
`rails g model store image:string`
`rails db:migrate`

### 3.storeモデルへuploaderを設定。
`mount_uploader :carrierwave用に作ったカラム名, carrierwaveの設定ファイルのクラス名`
これによりモデルとの紐付けができるようになる。

```ruby:app/model/store.rb

mount_uploader :image, ImageUploader
```

### 4.ビューの修正
formへファイル選択ボックスを追加
また、バリデーションでエラーが発生し、フォームが再表示された場合もアップロードされたファイルが保持されるようにカラム名_cacheというhiddenフィールドを用意しておく。

=>ここら辺でContollerをいじらなければいけないのだけど、何をやっているのかよくわからなくなった。。。。。。。そもそも参照していたページが、昨日実装したものと違うし、昨日実装したものをどこをどう消したらいいのかさえもわからない。。。。。。。。。
=>次からは、参照したやつを残しておくのと、クソページだと思ったら、今後アクセスするのは時間の無駄でしかないのでブロックしよう。
[ゴミサイトにアクセスするのは時間の無駄なのでガンガンブロック](http://albatrus.com/main/everyday/1638)


[ストロングパラメータをもう一度確認する](https://diveintocode.jp/tips/strong_parameter)
requireでモデル持ってきて、permitでカラムを制限するという理解でOK?????

色々あって解決した。
これからはどれを参照したのかきちんとメモって、くそサイトはブロックしておく
＋
どのような仕組みで動いているのかをきちんと理解してから、色々やる必要があると思った。

それでは、以下のことを順番にやっていく。

- 写真の納品はただuploadできるだけでなく、一気に複数枚アップロードできる
- そして、納品一覧ページではアップロードした写真の一枚だけサムネイルとして表示され、クリックするとアップロードした全てのファイルが見れる。
- 納品してアップロードした写真は,`homes/top.html.erb`で表示される。

[CarrierWave 複数の画像をコード三行で一つのカラムに保存する](https://qiita.com/ggtmtmgg/items/ba5f275c122c83013ea1)

Storeテーブルにimagesカラムを追加

```
$ rails g migration add_images_to_store images:json
$ rake db:migrate
```

ImageUploaderを`images`カラムにマウント

```ruby:app/model/store.rb
  class Store < ActiveRecord::Base
    mount_uploaders :images, ImageUploader
  end
```

画像アップロード用のフォームを作成

```ruby:app/views/upload/index.html.erb
<%= f.label :images, "ユーザー画像" %>
<%= f.file_field :images ,multiple: true%>
```

strong parametersに`images`に追加

```ruby:app/controllers/upload_controller.rb
params.require(:store).permit(:{images: []})
```

=> 実行!!!!
エラー! どうも、Railsに生の状態で登録されているDBであるSQliteには、Json形式が登録されていないらしい。

rails consoleでStoreモデルの中身を調べてみても、imagesのカラム型が登録されていない。
これの解決策として、

```ruby:app/models/store.rb
class Store < ApplicationRecord
  serialize :images, JSON
  mount_uploaders :images, ImageUploader
end
```
上のように、`serialize :image, JSON`を追加すればimagesのカラム型は何型で登録してあったとしても、必ずJSONに変換される。

これで、imagesの型をJSONのままにして色々やっても結局うまくいかず、string型に一応設定しておいたらうまくいった。
この時にDBを弄ったので、暗記事項として復習をしておく。
[db:migrateを最初からやり直したい！](http://xengineer.hatenablog.com/entry/2015/05/30/db%3Amigrate%E3%82%92%E6%9C%80%E5%88%9D%E3%81%8B%E3%82%89%E3%82%84%E3%82%8A%E7%9B%B4%E3%81%97%E3%81%9F%E3%81%84%EF%BC%81)
最初からやり直すには、

```
$ rake db:migrate:reset
$ rake db:reset
```
の二つがある。

- rake db:migrate:reset
  - db/migrate/*.rb を古い順にあててくれるらしい
- rake db:reset
  - db/schema.rb でdbを再構築してくれるらしい

`rake db:reset`の方はよくわからないが、`rake db:migrate:reset`は全てのマイグレーションの処理を最初から全てやり直してくれる。
こっちの方が良さそう。

ちなみに、`rails g migration add_images_to_store images:json`といったカラムを追加する操作は、`migrationファイル`を作成してくれるだけで、特に変更が起こる訳ではなく、`rails db:migrate`を行った際に初めて反映される。

あと、マイグレーションファイル作ろうとしたら`identical`っていうのが出てきたんだけど、これはすでに同じファイルがあるよってことで、実行順番を変えるために作り直すことはできない。

[rails db:rollback](http://railsdoc.com/references/rake%20db:rollback)っていう機能があって、これはマイグレーションを前の順番に戻せる。またオプションを指定すれば、いくつ前のマイグレーションまで戻すかの変更ができる。

他にDBのconflictとかあったけど、まあそれは無視しよう。

#### そして、納品一覧ページではアップロードした写真の一枚だけサムネイルとして表示され、クリックするとアップロードした全てのファイルが見れる。

```ruby:Gemfile
gem 'mini_magick' #を追加する。
```

```ruby:app/uploaders/image_uploader.rb
class ImageUploader < CarrierWave::Uploader::Base
  #以下は初めからある
  storage :file

  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end
　　　#以下を追加
　　 #サムネイルのために以下を追加
  include CarrierWave::MiniMagick

  #画像のサイズを変更
  #アップロードすると最大1280×720にリサイズされる。
  process :resize_to_limit => [1280, 720]

  # サムネイルの生成
  #100×100のサムネイルの生成
  version :thumb do
    process reseze_to_fill => [100, 100]
  end
```

このアップロードされたものをトップ画面に表示したい。

```ruby:app/views/top.html.erb
<%= render "header" %>
<%= @store.each do |store| %>
  <%= image_tag store.images[0].url %>
<% end %>
<%= render "footer" %>
```

この前にもちろん、`インスタンス変数の@store`にアップロードされた画像を渡す必要がある。

```ruby:app/controllers.html.erb/homes_controller.erb
class HomesController < ApplicationController
  def top
    @store = Store.all
  end
  #中略
end
```

なぜかサムネイル表示できない。。。。。。
⬇︎
サムネイルの動作が働くのは新たにアップロードをした時なので、この機能を追加する前に動作が働かないのは当然。
よって、この機能を追加して再度一からやり直してみようと思った。
しかし、色々できない。。。。。。。。。。。

`binding.pry`とかで色々どこでエラーが出てるかもわかるらしいし、rubyの勉強がきちんとできていないと思うからパーフェクトrubyを一から読んでみる。

さらには、結局聞いて見たところ、
`serialize :images, JSON`でJSONに変更したところでSQLiteではJSONは受け付けていないから無理！！！

ということで色々直すの面倒なので、一から作り直す
+
複数アップロードの際にJSONを使うのではなく、モデルでは`belongs_toとhas_many`の構造を使用する