スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Sinatraで画像のCRUD

前回、画像と登録と表示を作りました。
次に一覧を作ろうと思ったらMongoidの制約でフィールドの一部を取ることができません。
そのまま実装すると一覧の画像すべてロードすることになってしまいます。
そこで、一覧に表示する名前や詳細を「picture」に保存して、画像データは「image」に保存することにしました。
一覧以外にも削除と更新を作りました。これでCRUDが完成です。

app.rb
#coding: utf-8
require 'sinatra/base'
require './models/image'
require './models/picture'

class MyApp < Sinatra::Base
configure do
set :haml, {format: :html5}
Mongoid.configure do |conf|
conf.master = Mongo::Connection.new('localhost', 27017).db('test')
end
end

def is_exist(src)
src && src != ''
end

get '/edit' do
if is_exist(params[:id])
@picture = Picture.first(conditions: {_id: params[:id]})
else
@picture = nil
end
haml :edit
end

post '/edit' do
image = nil
if params[:data]
file = params[:data][:tempfile]
image = Image.new(name: params[:name], data: file.read(file.length))
image.save
end
picture = nil
if is_exist(params[:id])
picture = Picture.first(conditions: {_id: params[:id]})
picture.name = params[:name]
picture.code = params[:code]
picture.description = params[:description]
else
picture = Picture.new(
name: params[:name],
code: params[:code],
description: params[:description],
)
end
if !picture
redirect '/list'
end
if image
picture.image_id = image._id
end
picture.save
redirect '/view?id=' + picture._id.to_s
end

get '/image' do
image = Image.first(conditions: {_id: params[:id]})
content_type image.content_type
params[:w] ? image.thumbnail(params[:w], params[:h]) : image.data
end

get '/list' do
@pictures = Picture.all
haml :list
end

get '/view' do
@picture = Picture.first(conditions: {_id: params[:id]})
haml :view
end

get '/delete' do
picture = Picture.first(conditions: {_id: params[:id]})
if !picture
redirect '/list'
end
image = Image.first(conditions: {_id: picture.image_id})
image.delete if image
picture.delete
redirect '/list'
end
end

models/image.rb
#coding: utf-8
require 'mongoid'
require 'RMagick'

class Image
include Mongoid::Document
field :data
field :format
field :width, type: Integer
field :height, type: Integer

before_save :to_data
after_initialize :from_data

# コンテントタイプ
def content_type
'image/' + format.downcase
end

# サムネイル作成
def thumbnail(w, h)
img = Magick::Image.from_blob(data).first
img.thumbnail!(calc_scale(w.to_i, h.to_i))
img.to_blob
end

# スケール計算
def calc_scale(w, h)
if width > height
scale = w / width.to_f
scaled_height = height * scale
if scaled_height > h
scale = h / height.to_f
end
else
scale = h / height.to_f
scaled_width = width * scale
if scaled_width > w
scale = w / width.to_f
end
end
scale
end

protected
def to_data
img = Magick::Image.from_blob(data).first
self.format = img.format
self.width = img.columns
self.height = img.rows
self.data = BSON::Binary.new(data, BSON::Binary::SUBTYPE_BYTES)
end

def from_data
self.data = data.to_s
end
end

models/picture.rb
#coding: utf-8
require 'mongoid'

class Picture
include Mongoid::Document
include Mongoid::Timestamps
field :name
field :code
field :description
field :image_id
end

views/list.haml
!!! 5
%head
%meta{'http-equiv' => 'content', content: 'text/html; charset=utf-8'}
%body
%h1 List
%a{href: '/edit'}
Edit
%div
- @pictures.each do |picture|
%a{href: "/view?id=#{picture._id}"}
#{picture.name}
%a{href: "/image?id=#{picture.image_id}"}
%img{src: "/image?id=#{picture.image_id}&w=100&h=100"}
%br

views/view.haml

!!! 5
%head
%meta{'http-equiv' => 'content', content: 'text/html; charset=utf-8'}
%body
%h1 View
%h2 #{@picture.name}
%h2 #{@picture.code}
%h2 #{@picture.description}
%div
%a{href: "/image?id=#{@picture.image_id}"}
%img{src: "/image?id=#{@picture.image_id}&w=100&h=100"}
%br
%a{href: '/list'}
List
%a{href: "/edit?id=#{@picture._id}"}
Edit
%a{href: "/delete?id=#{@picture._id}", onClick: 'return confirm("削除します。\nよろしいですか?");'}
Delete

views/edit.haml

!!! 5
%head
%meta{'http-equiv' => 'content', content: 'text/html; charset=utf-8'}
%body
%h1 Edit
%form{action: '/edit', method: 'post', enctype:'multipart/form-data'}
name:
%input{type: 'text', name: 'name', value: "#{@picture ? @picture.name : ''}"}
%br
code:
%input{type: 'text', name: 'code', value: "#{@picture ? @picture.code : ''}"}
%br
description:
%textarea{name: 'description'}= @picture ? @picture.description : ''
%br
- if @picture
%img{src: "/image?id=#{@picture.image_id}&w=100&h=100"}
%input{type: 'file', name: 'data'}
%br
%input{type: 'submit', value: 'edit'}
%input{type: 'hidden', name: 'id', value: "#{@picture ? @picture._id : ''}"}
スポンサーサイト

COMMENTS

COMMENT FORM

TRACKBACK


この記事にトラックバックする(FC2ブログユーザー)

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。