TODO
- 管理画面から申し込み一覧、申し込み詳細にいける。
- そこから写真の納品ができる
- 写真の納品はただuploadできるだけでなく、一気に複数枚アップロードできる
- そして、納品一覧ページではアップロードした写真の一枚だけサムネイルとして表示され、クリックするとアップロードした全てのファイルが見れる。
- 納品してアップロードした写真は,
homes/top.html.erb
で表示される。
1から行こう
管理画面から申し込み一覧、申し込み詳細にいける。
復習
...
namespace :admin do
resources :order
end
/admin/order
から管理画面にアクセスできるようにする。
この場合のコントローラーとビューには気をつけなければならないことがある。
Controllerはadminディレクトリ
を作成し、その中にorder_controller.rb
を作る。
その時に作るClassにも注意、以下のようにする。
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
を作成する。
こちらは申し込み一覧画面。名前を押すと詳細管理画面へ飛べる。
<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 %>
詳細画面から納品画面へを押せば、アップロード画面へ飛べる。
<h1>詳細管理画面です。</h1>
<h1>名前</h1>
<%= @order.name %>
<h1>電話番号</h1>
<%= @order.phone_number %>
<h1>メールアドレス</h1>
<%= @order.mail %>
<%= link_to '納品画面へ' ,uploader_form_path %>
2. そこから写真の納品ができる。
1.Gemfileをインストール
gem 'carrierwave'
$ bundle install
2.uploaderクラスを作成
CarreirWaveでは uploader というジェネレータが提供されるので、任意の名前でクラスを作成。
以下では、uploadfileという名前でuploadクラスを生成。
$ rails g uploader UploadFile
これによって生成されるのは
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の設定ファイルのクラス名
これによりモデルとの紐付けができるようになる。
mount_uploader :image, ImageUploader
4.ビューの修正
formへファイル選択ボックスを追加
また、バリデーションでエラーが発生し、フォームが再表示された場合もアップロードされたファイルが保持されるようにカラム名_cacheというhiddenフィールドを用意しておく。
=>ここら辺でContollerをいじらなければいけないのだけど、何をやっているのかよくわからなくなった。。。。。。。そもそも参照していたページが、昨日実装したものと違うし、昨日実装したものをどこをどう消したらいいのかさえもわからない。。。。。。。。。
=>次からは、参照したやつを残しておくのと、クソページだと思ったら、今後アクセスするのは時間の無駄でしかないのでブロックしよう。
ゴミサイトにアクセスするのは時間の無駄なのでガンガンブロック
ストロングパラメータをもう一度確認する
requireでモデル持ってきて、permitでカラムを制限するという理解でOK?????
色々あって解決した。
これからはどれを参照したのかきちんとメモって、くそサイトはブロックしておく
+
どのような仕組みで動いているのかをきちんと理解してから、色々やる必要があると思った。
それでは、以下のことを順番にやっていく。
- 写真の納品はただuploadできるだけでなく、一気に複数枚アップロードできる
- そして、納品一覧ページではアップロードした写真の一枚だけサムネイルとして表示され、クリックするとアップロードした全てのファイルが見れる。
- 納品してアップロードした写真は,
homes/top.html.erb
で表示される。
CarrierWave 複数の画像をコード三行で一つのカラムに保存する
Storeテーブルにimagesカラムを追加
$ rails g migration add_images_to_store images:json
$ rake db:migrate
ImageUploaderをimages
カラムにマウント
class Store < ActiveRecord::Base
mount_uploaders :images, ImageUploader
end
画像アップロード用のフォームを作成
<%= f.label :images, "ユーザー画像" %>
<%= f.file_field :images ,multiple: true%>
strong parametersにimages
に追加
params.require(:store).permit(:{images: []})
=> 実行!!!!
エラー! どうも、Railsに生の状態で登録されているDBであるSQliteには、Json形式が登録されていないらしい。
rails consoleでStoreモデルの中身を調べてみても、imagesのカラム型が登録されていない。
これの解決策として、
class Store < ApplicationRecord
serialize :images, JSON
mount_uploaders :images, ImageUploader
end
上のように、serialize :image, JSON
を追加すればimagesのカラム型は何型で登録してあったとしても、必ずJSONに変換される。
これで、imagesの型をJSONのままにして色々やっても結局うまくいかず、string型に一応設定しておいたらうまくいった。
この時にDBを弄ったので、暗記事項として復習をしておく。
db:migrateを最初からやり直したい!
最初からやり直すには、
$ 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っていう機能があって、これはマイグレーションを前の順番に戻せる。またオプションを指定すれば、いくつ前のマイグレーションまで戻すかの変更ができる。
他にDBのconflictとかあったけど、まあそれは無視しよう。
そして、納品一覧ページではアップロードした写真の一枚だけサムネイルとして表示され、クリックするとアップロードした全てのファイルが見れる。
gem 'mini_magick' #を追加する。
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
このアップロードされたものをトップ画面に表示したい。
<%= render "header" %>
<%= @store.each do |store| %>
<%= image_tag store.images[0].url %>
<% end %>
<%= render "footer" %>
この前にもちろん、インスタンス変数の@store
にアップロードされた画像を渡す必要がある。
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
の構造を使用する