Railsの勉強で作ったサンプルサイトにギャラリーをつけるために、
画像のアップロードと表示の方法を勉強しました。
勉強中なのでプラグインは使わない方法です。
超初心者なので一つ一つ忘れないように勉強したことを残しておきます。
#プロジェクト立ち上げ
##アプリケーション、モデル作成
$rails new Gallery
$rails g model Image
##テーブル作成
class CreateImages < ActioveRecord::Migrattion
def change
create_table :images do |t|
t.string :filename
t.binary :file
t.timestamps
end
end
end
画像はバイナリで扱います。
#コントローラ作成
rails g controller Images
##indexとnewを作成
class ImagesController < ApplicationController
def index
@image = Image
end
def new
@image = Image.new
end
end
とりあえずここまで。
@image = Image.new
は、新しく作成したImageテーブルのレコードを
@image
変数に格納して扱えるようにしています。
##createを作成
~
def create
upload_file = image_params[:file] #image_paramsは後に定義
image = {} #ローカル変数にからのハッシュを入れて定義
if upload_file != nil
image[:filename] = upload_file.original_filename #original_filenameは元々のファイル名を取り出す
image[:file] = upload.file.read #readでファイル本体を取り出す
end
@image = Imag.new(image) #imageを渡して新しくレコードを作る
if @image.save
fhash[:success] = "画像を保存しました。"
redirect_to @image
else
flash[:error] = "保存できませんでした"
redirect_to "new"
end
end
ここまでで実際のファイルデータの取り出しや格納を行います。
ちなみに、空のハッシュの意味がわからなくて色々調べました。
こちら参考にさせていただきました。
http://ref.xaio.jp/ruby/classes/hash
http://qiita.com/yukimura1227/items/8c972efb27667dfac5cd
私では明確に理解はできなかったのですが、「空で宣言しておいて後から値を入れよう」
ってことなのかな?と理解しています。
##image_paramsを作成
create
アクションで使ったimage_params
を定義。
~
private
def image_params
params.require(:image).permit(:filename, :file)
end
require:外部のファイルやデータを呼び出す。キーにimage
テーブルを指定。
permit:保存を許可するカラムを指定。
ストロングパラメータ用にどのデータを保存するかを指定しているということだと思います。
##表示用のアクションを作ります。
def show_image
@image = Image.find(params[:id])
send_data @image.file, :type => 'image/jpeg', disposition => 'inline'
end
private
~
send_data
:動的に生成されたデータを出力する。
:type
:send_data
のオプション。コンテントタイプを指定。
:disposition
:send_data
のオプション。ファイルをインラインで表示するか、ダウンロードして保存するか指定する。
#ルーティング
Rails.application.routes.draw do
resources :images
resources :images do
member do
get "show_image"
end
end
end
imageテーブルをリソースとしたルーティングを設定します。
member do
:リソースベースの7つのアクション以外で独自のアクションを呼び出すときに使用。
member
は特定のデータを対象をしたアクションを呼び出す。
*collection do
:全てのデータを対象としたアクションを呼び出す。
これにより<img src=“/images/:id/show_image”>
で画像にアクセスできるようになり、
image_tag
でshow_image_image_path(id)
を指定することができるようになります。
#ビュー作成
##index
<% @images.each do |img| %>
<%= image_tag show_image_image_path(img) %>
<% end %>
ルーティングで設定したshow_image
を使って画像にアクセスしています。
##new
<%= form_for(@image) do |f| %>
<%= f.file_field :file, accept: "image/jpeg" %>
<%= f.submit "送信する" %>
<% end %>
普通にform_for
を使ってフォームを作ります。
と言っても、form_for
の使い方についてめっちゃ調べました。
こちら参考にさせていただきました。
http://railsdoc.com/references/form_for
http://qiita.com/shunsuke227ono/items/7accec12eef6d89b0aa9
http://qiita.com/Momozono/items/319bc503e6a5f0963ab9
##show
<%= image_tag show_image_image_path(@image) %>
こちらもshow_image
を使ってアクセスしています。
ちなみにRubyのコード見ててよく思うのが、
「同じ単語で違う意味(仕様)のものが多くてわけわからない」なんです。
この場合"image"ですね。テーブル名とか変数名とか工夫すればいいのかな・・・
image_tag
:イメージタグを作成
show_image
:ルーティングで設定したアクション
_image
:アクセスするテーブル名
@image
:show_image
アクションで定義したインスタンス変数
#ハマったこと
##UrlGenerationError in Samples#show
今思えば何のことないのですが、これのお陰でroutes.rb
らへんを色々引っ掻き回してしまいました。
結局URLが間違っていただけでした。
newで送信するまでは良かったのですが、送信後にこのエラーがでます。
原因は送信後のURLが/images/:id
までしか入力されていなかったからです。
$rake routes
でルーティングを確認したところ、
/images/:id/show_image(:format)
となっていたので、
最後に「show_image」をつけなければいけなかったということです。
わざわざそんなことしなくても表示させる方法を今後考えてみます。
ちなみにルーティングの確認についてはこちらで学ばせていただきました。
http://www.rubylife.jp/rails/routing/index1.html
#まとめ
前に書いた通り、やはり私はrailsを勉強するにあたって、「同じ単語で違う意味」のものに
とても弱いことがわかりました。
今回はテーブル名をimage
にしましたが、最初に始めた時は名前を変えてsample
としていたので、
テーブル名として使われているimage
がどれかわからずとにかくNoMethodやらParameterMissing
やらをやたらくらいました・・・
でもお陰で文法の勉強ができてよかったです!
今回全般的に参考とさせていただいたのはこちらです
http://qiita.com/gaaamii/items/27d27fb7685b39744416
大変お世話になりました。