Railsでプラグインを使わずに画像を表示させる

More than 1 year has passed since last update.

Railsの勉強で作ったサンプルサイトにギャラリーをつけるために、
画像のアップロードと表示の方法を勉強しました。
勉強中なのでプラグインは使わない方法です。
超初心者なので一つ一つ忘れないように勉強したことを残しておきます。

プロジェクト立ち上げ

アプリケーション、モデル作成

$rails new Gallery
$rails g model Image

テーブル作成

db/migrate/20161028_create_image.rb
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を作成

app/controllers/images_controller.rb
class ImagesController < ApplicationController
  def index
    @image = Image
  end

  def new
    @image = Image.new
  end
end

とりあえずここまで。
@image = Image.newは、新しく作成したImageテーブルのレコードを
@image変数に格納して扱えるようにしています。

createを作成

images_controller.rb
~
  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を定義。

images_controller.rb
~
private
def image_params
  params.require(:image).permit(:filename, :file)
end

require:外部のファイルやデータを呼び出す。キーにimageテーブルを指定。
permit:保存を許可するカラムを指定。
ストロングパラメータ用にどのデータを保存するかを指定しているということだと思います。

表示用のアクションを作ります。

images_controller.rb
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のオプション。ファイルをインラインで表示するか、ダウンロードして保存するか指定する。

ルーティング

config/routes.rb
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_tagshow_image_image_path(id)を指定することができるようになります。

ビュー作成

index

app/views/images/index.html.erb
<% @images.each do |img| %>
  <%= image_tag show_image_image_path(img) %>
<% end %>

ルーティングで設定したshow_imageを使って画像にアクセスしています。

new

app/views/images/new.html.erb
<%= 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

app/views/images/show.html.erb
<%= 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
大変お世話になりました。

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.