sinatra + html5_canvas + jquery 画像ドラッグドロップでファイル保存
こんにちは。麺処まつば副店長です。風が凄まじいですね(台風)
ここ暫く更新せずにいたら、ついに店長の大目玉をくらいました。
台風と店長の大目玉のダブルパンチ。恐ろしや……。
さて今日は、sinatra + HTML5 + jquery で canvas にドラッグドロップされた画像を
サーバに送信ファイル保存しつつ表示というのをやってみようと思います。
どれだけ需要があるか分かりませんが(笑)
手順はこんなカンジです。
1.views/index.haml
2.public/javascripts/dragdrop.js
3.app.rb
それでは作っていきましょう。
views/index.haml
副店長の悪いクセなんですが、まず見た目から入ります。
canvas をひとつだけおいたファイルを用意します。
1 !!! XML 2 !!! 3 4 %html{:lang => "ja"} 5 %head 6 %meta{ :content=>"text/html", :charset=>"utf-8" } 7 %title 画像 8 %link{ :rel => "stylesheet", :href =>"/style.css" } 9 %script{ :src => "javascript/jquery-1.6.2.min.js" } 10 %script{ :src => "javascript/dragdrop.js" } 11 %body 12 #main 13 %canvas{ :id=> "img_canvas", 14 :width => "500", :height => "500", 15 :ondragover => "onDragOver(event)", :ondrop => "onDrop(event)", 16 :style => "border: medium dotted #666;"}
9、10行目で、自作する js ファイルと、使用する jquery を指定しています。
13〜16行目で、canvas を設置しています。
ondragover / ondrop で、自作 js の関数を呼びます。
それから、canvas の width と height は、
スタイルシートで指定しないほうがいいみたいです。
こないだ参加したHTML5勉強会の講師の先生が
スタイルシートで書くと何故かうまくいかないって仰ってました。
(そして自分では試してないので、どううまくいかないのかは良く分かりません(笑))
public/javascript/dragdrop.js
上記で書いた canvas に画像がドラッグドロップされたときに動く
javascript をかいていきます。
1 function onDrop(event){ 2 // drop されたファイルの取得 3 var f = event.dataTransfer.files[0]; 4 5 // drop されたファイルが画像ファイルの場合の処理 6 if(/^image/.test(f.type)){ 7 // 画像ファイルを読み込むための準備 8 var img = document.createElement('img'); 9 var fr = new FileReader(); 10 11 fr.onload = function(){ 12 img.src = fr.result; 13 img.onload = function() { 14 // jquery ajax を使ってPOST 15 new $.ajax({ 16 url: "/post_img", 17 type: "POST", 18 data: {file: img.src}, 19 success: function(){ 20 // canvas に画像描画 21 canvas = document.getElementById("img_canvas"); 22 context = canvas.getContext("2d"); 23 canvas.width = img.width; 24 canvas.height = img.height; 25 context.drawImage(img, 0, 0); 26 }, 27 error: function(){ alert("ごめん失敗した。");}, 28 complete: function(){ alert("保存した!"); } 29 }); 30 } 31 } 32 fr.readAsDataURL(f); 33 } 34 35 // ブラウザがファイル自体を表示するのを防止 36 event.preventDefault(); 37 } // end funciton [openDrop] 38 39 function onDragOver(event){ 40 event.preventDefault(); 41 } // end function [onDragOver]
こんなカンジです。
15行目から、ajax を使って画像をPOSTしています。
成功すれば、canvas に読み込んだ画像を表示するようにしています。
app.rb
sinatra な ruby のファイルです。
画面表示と送信された画像を受けてファイル保存なぞします。
1 #coding:utf-8 2 3 require 'rubygems' 4 require 'sinatra' 5 require 'haml' 6 7 configure :production do 8 end 9 10 get '/' do 11 set :haml, :format => :html5 12 haml :index 13 end # end [get /] 14 15 post '/post_img' do 16 # 画像ファイルの取得 17 img_array = params[:file].split(/\s*,\s*/) 18 19 # 拡張子 20 ext = ".dat" 21 case img_array[0] 22 when "data:image/jpeg;base64" 23 ext = ".jpg" 24 when "data:image/gif;base64" 25 ext = ".gif" 26 when "data:image/png;base64" 27 ext = ".png" 28 end 29 30 # 画像ファイル保存 31 f = File.open("tmp/image#{ext}",'w') 32 f.puts img_array[1].unpack('m')[0] 33 f.close 34 return "" 35 end 36 37 get '/style.css' do 38 content_type 'text/css', :charset => 'utf-8' 39 sass :style 40 end
10〜13行目で、/ へのGETの定義
15〜35行目で、post された画像を保存する処理を書いています。
ajaxからどんなデータが渡ってくるかなって思ったら、
base64でエンコードされた文字列でした。
こんな感じの→「画像情報, エンコードされた文字列」
"data:image/jpeg;base64", "/9j/4AAQSkZJRgAB…
カンマ区切りだったんで配列化して、0番目の情報から画像情報を取得、
ファイル保存時の拡張子を指定しています(19〜28行目)
30〜33行目の間でファイルを保存しています。
終わりです。
※あ。「tmp」ディレクトリ作っといてくださいね。
では、さっそくできた画面内の canvas 領域に画像をドラッグドロップしてみましょう。
canvas に画像が表示されますか?→OK
サーバに画像は保存されますか?→OK
できました。
次回はコレをストレージに保存してみるところをやってみようと思います。
sinatra + haml + scss で stylesheet
おはようございます。麺処まつば副店長です。
珍しく朝っぱらからの更新です。
さて、先日まで sinatra + haml でゴニョゴニョやってたんですが、
ふとスタイルシートを使いたくなったので調べてみたら
sinatra は scss のテンプレートに対応しているようです。
ということで、今回は sinatra + haml + scss の使い方について簡単にまとめてみます。
本家→http://www.sinatrarb.com/intro-jp.html
手順はこんなカンジ
- app.rb
- views/style.scss
- views/index.haml
では作っていきましょうー。
app.rb
1 #coding:utf-8 2 3 require 'rubygems' 4 require 'sinatra' 5 require 'haml' 6 7 configure :production do 8 end 9 10 get '/' do 11 set :haml, :format => :html5 12 haml :index 13 end # end [get /] 14 15 get '/style.css' do 16 content_type 'text/css', :charset => 'utf-8' 17 sass :style 18 end
10〜13行目にかけて「/」へのGETの定義。
15〜18行目にかけて、「/styhle.css」の定義をしています。
views/style.scss
1 body 2 padding: 20px 3 background: #d3d3d3 4 5 img 6 margin: 10px 7 border: 5px 8 solid: #000000
scssを使うと、すっきりかけますね。
sinatra + haml で html5
こんにちは。麺処まつば副店長です。
先日からずっと目が痒かったのですが、放置していたら大変なことになりました。
慌てて病院に行って目薬をもらってきましたが
…年々抵抗力が落ちてきている気がしております…。
さて、副店長、最近やっとこさ HTML5 の勉強をはじめました。
で、折角なんで、こないだ中やってた sinatra + haml 上でやってみようと思いまして、
どうやるのか調べてたらすごい簡単にできたので、書いておきます。
#本当は書くまでもないくらい簡単なんですが、
#店長に「ちゃんと書いてます」アピールの記事稼ぎとかいうのは内緒です。
やり方は本当に簡単でした。
sinatra のファイルの下記一行追加するだけ。
set :haml, :format => :html5
終わりです(笑)
さすがにこれだけだと、「ちゃんと書いてます」アピールとして弱い気がするので
例も書いてみます
app.rb
1 #coding:utf-8 2 3 require 'rubygems' 4 require 'sinatra' 5 require 'haml' 6 7 configure :production do 8 end 9 10 11 get '/' do 12 set :haml, :format => :html5 13 haml :index 14 end # end [get /]
12行目で、html5の指定をしています。これだけです。
\わぁかんたん/
DataMapper Model
こんにちは。麺処まつば副店長です。
今日は DataMapper でレコードを扱う方法について少し調べてみました。
本家から、(副店長が)よく使いそうなものを拾ってきました。
本家はこちらです。
→http://datamapper.org/docs/create_and_destroy
→http://rubydoc.info/gems/dm-core/1.1.0/frames
検索
Zoo.all # 全部取得 Zoo.all(:open => true) # open が true のものだけ Zoo.all(:opened_on => start..end) # opend_on が start 〜 end の期間のもの Zoo.all(:order => [ :tiger_count.desc ]) # 虎の数で並び替え Zoo.get(1) # プライマリーキーが 1 Zoo.get!(1) # プライマリーキーが 1 失敗すると ObjectNotFoundError Zoo.get('DFW') # 自然(プライマリー)キーもサポート Zoo.get('Metro', 'DFW') # 複合キーでもいけます
更新(作成・更新・削除)
Zoo.create( :column1 => "column1 column1", :column2 => 15, :column3 => Time.now ) # インスタンス生成して保存 zoo = Zoo.new( :column1 => "column1 column1", :column2 => 15, :column3 => Time.now ) zoo.save # 更新 Person.update(:allow_beer => true) # 保存失敗で例外発生 User.raise_on_save_failure # 削除 zoo = Zoo.get(5) zoo.destroy # 全部消す Zoo.all.destroy # 合わせ技1:検索してなかったらcreate zoo = Zoo.first_or_create(:name => 'The Glue Factory')
なんとなく分かったツモリになりました(気分だけ)
DataMapper property
こんばんは。麺処まつば副店長です。
なんか知らんですが、目がかゆいです。
…と店長に訴えたら「ギガもあるのか」と言われました。エクサ目指して頑張ります。
さて、前回、DataMapper に挑戦したので、
それについてもう少し調べてみようと思います。
今回のターゲットは「property」です。
本家 API ページの Property から(副店長が)使いそうな情報だけ引っこ抜いてきました。
抜粋したものを簡単に並べてみます。
本家APIはコチラ→http://rubydoc.info/gems/dm-core/1.1.0/frames
property 定義の方法
property :[プロパティ名], [型], :[オプション]
デフォルトで使える型
Boolean
Class (datastore primitive is the same as String. Used for Inheritance)
Date
DateTime
Decimal
Float
Integer
Object (marshalled out during serialization)
String (default length is 50)
Text (limit of 65k characters by default)
Time
オプション
プロパティに指定できるオプション
オプション | 意味 |
---|---|
:accessor | accessor の設定。falseでreader + writer が作られない |
:reader | reader の設定。false で、reader が作られない |
:writer | writer の設定。false で writer が作られない |
:lazy | 遅延読み込み。false で設定解除。group指定もできる。 |
:default | デフォルト値の設定 |
:allow_nil | nil を許可するかどうか。true で許可。 |
:key | キーの設定 |
:field | フィールド(カラム名) |
:length | 文字列の長さ設定。 |
:format | autovalidationのフォーマット設定。dm-validations使う時 |
:index | index の設定。trueにするとindex が作られる。 |
:unique_index | ユニークな index 設定かな。true で指定 |
:auto_validation | 自動 validation の設定。true で実行される。 |
:validates | validation context 。dm-validations使う時に |
:unique | true でユニーク指定。Serial指定するとデフォルトでユニーク |
あとは、IDとかにしたいカラムには「Serial」つけるとか。
その他
あとはメソッドが allow_blank? とか色々あるけどあんまり使わなそうなので、
使うときに見に行く形ですかね。
次回、find とか update とかそのへんの操作についてもう少し調べてみようと思います。
sinatra + heroku + DataMapper + postgreSQL
こんばんは。麺処まつば副店長です。
いやー空が禍々しいですね(雷)
さて、今日は heroku + sinatra で、DB を扱う部分をやってみようと思います。
あとから詳しくかきますけど、今回は postgreSQL と DataMapper 使います。
そんなわけで、今回のメニューはコチラです。
フォームから入力された文字列の最後に 勝手に「。。。多分。」と付加することにより そこはかとなく胡散臭い文字列に仕立て上げた上でDBに保存する。 かつ保存された、そこはかとなく胡散臭い文字列を表示する。
今回の作り方はこのような流れです。
- postgreSQL の用意
- DataMapper の用意
- bundler
- migrate
- モデルの用意
- app.rb の用意
- view の用意
- ローカル動作確認
- heroku に反映
それでは作っていきましょう。
postgreSQL の用意
heroku で使える DB は、標準で PostgreSQL や、あと MySQL 、
それから巷で話題の NoSQL なんかも扱えるみたいですが、
今回は、とりあえず、ということで標準の postgreSQL を使ってみようと思います。
(NoSQL は個人的に非常に気になる材料なので、後日やります。(宣言))
まずは、ローカルに PostgreSQL をいれちゃいましょう。
これは、環境によってインストール方法が違うと思うので特に書きません。…が、
副店長の Mac に postgreSQL 入れた時の記録でしたらこちらです
→http://d.hatena.ne.jp/noodles_mtb/20110805/1312509838
DataMapper の用意
sinatra はモデルの機能持ってないので、どっかから調達してきます。
ActiveRecord とか、DataMapper とか、Sequelとか色々あるみたいですけど
今回は DataMapper 使ってみようと思います。
まず、DataMapper と、その postgreSQL のアダプター、
それから migrate もお願いしようと思うのでそれも。
$ gem install dm-core $ gem install dm-postgres-adapter $ gem install dm-migrations
DataMapper本家→http://datamapper.org/getting-started.html
bundler
DataMapper とか新しく入れたので、bundle する必要があります。
Gemfile
1 source :rubygems 2 gem 'sinatra' 3 gem 'haml' 4 gem 'dm-core' 5 gem 'dm-postgres-adapter' 6 gem 'dm-migrations'
4〜6行目が DataMapper 系の記述です。
これができたら、bundle しましょう
$ bundle update
これで DataMapper を使う準備は整いました。
モデルの用意
それでは、model を書いていきます。
今回は、フォームから入力されたテキストを胡散臭くして
DBに保存するだけなので、大したことは書きません。
word.rb
1 require 'rubygems' 2 require 'dm-core' 3 4 class Word 5 6 include DataMapper::Resource 7 property :id, Serial 8 property :msg, String 9 10 end
これだけです。
migrate
モデルを作りましたが、肝心の DB がないとダメですね。
まず、postgreSQL に DB つくっといてください。
そしたら、dm-migrations を使って migrate をしましょう。
DataMapper で migrate する場合には、自動と手動の2種類があるようです。
(→http://route477.net/ramaze/?DataMapper)
今回は自動の migrate を使ってみます。
(自動の場合、model 内に定義した propery をもとにmigrate するようです)
Rakefile
1 require 'dm-core' 2 require 'dm-migrations' 3 require './word.rb' 4 5 task 'db:migrate' do 6 DataMapper.setup(:default, ENV['DATABASE_URL'] || 'postgres://user_name:user_password@localhost/db_name') 7 DataMapper.auto_upgrade! 8 self 9 end
1〜2行目で、dm-core と dm-migrateions を使う宣言
3行目は、自作のモデルを呼んでいます(migrate の対象)
5〜9行目で、「db:migrate」の定義をしています。
6行目は、DataMapperを使ってDBに接続にいきます。6行目のコレ↓ですが、
ENV['DATABASE_URL'] || 'postgres://user_name:user_password@localhost/db_name')
これは、前者があれば前者、なければ後者につなぎにいきます。
ここでは、前者は heroku 上で使う DB 、これがなけば後者につなぎにいきます。
ここでは前者がないので後者、つまりローカルの postgreSQL に接続します。
それから、7行目の「auto_upgrade!」
これは、既存テーブルのデータを保持したまま自動 migration を行うものです。
「auto_migrate!」というのもありますが、既存テーブルのデータはなくなってしまいます。
場合に合わせてご利用ください。
※他の方が Rakefile をどういう風に書いてるのか拝見したところ
Rakefile の中で、別の Ruby のプログラムを呼んで
そこから migrate している方が多いようだったのですが
副店長はめんどks……げほげほ…
えー…、今回はお手軽版ということで、このように書いています。
それでは、migrate してみましょう。
$ rake db:migrate
きっと、db_name で指定した DB に新しくテーブルが追加されていると思います。
app.rbの用意
上記までの手順で、モデルを使う準備が整いました。
では、それを使っていきましょう。
app.rb
1 #coding:utf-8 2 3 require 'rubygems' 4 require 'sinatra' 5 require 'haml' 6 require 'dm-core' 7 require './word.rb' 8 9 configure :production do 10 end 11 12 DataMapper.setup(:default, ENV['DATABASE_URL'] || 'postgres://user_name:user_password@localhost/db_name') 13 14 get '/' do 15 haml :index 16 end # end [post /] 17 18 post '/' do 19 str = params[:str] + "。。。多分。" 20 Word.create(:msg => str) 21 22 @messages = Word.all(:order => [:id.desc]) 23 haml :index 24 end # end [post /]
大したことはやってません。
6行目で dm-core を require
7行目で 自作の model ( word.rb ) を require
12行目で DB 接続設定。です。
18〜24行目で、post の定義をしています
19行目で 入力された文字列を胡散臭く加工。
20行目で DB に INSERT
22行目で DB に保存された word の一覧を取得しています。
はい、本当に大したことはしていません。
view の用意。
おっと。これでできたと思っていましたが
view のことをすっかり忘れておりました。
views/index.haml
1 !!! XML 2 !!! 3 %html 4 %head 5 %meta{ :content=>"text/html", :charset=>"utf-8" } 6 %title 胡散臭いよー 7 %body 8 #main 9 %h1 胡散臭いよー 10 %div 胡散臭い文字列なら任せてください。 11 %form{:action=>"/", :method=>"post"} 12 %input{:type=>"texfield",:name=>"str"} 13 %input{:type=>"submit", :value=>"send"} 14 - if @messages && !@messages.blank? 15 - for msg in @messages 16 %div= msg['msg']
本気で大したことしてないので、説明は省略します。
ローカルで動作確認
さて、できたかどうかためしてみましょう
$ rackup
http://localhost:9292/
で入力した任意の文字列が胡散臭くなってかえってきたら成功です。
→あぁぁ…胡散臭い。成功です。
heroku に反映
ローカルで確認できたので、heroku 上にあげてしまいましょう。
まずは、ファイルを上げてしまいます。
$ git commit -a -c "usan kusai" $ git push heroku master
次に DB です。
rails 以外のプロジェクトの場合、デフォルトでDBが用意されてないそうなので
使う場合はこんなコマンドをたたいた上で migrate します
$ heroku addons:add shared-databasee $ heroku rake db:migrate
そして、動作確認
$ heroku open
うさんくさくなりましたか?
→すっごい胡散臭いです。成功です。
これで、heroku をなんとなく使える気がしてきました。
どんどん胡散臭いものを作っていきましょう>自分
MacOS X Lion にpostgreSQLを入れる
こんにちは。麺処まつば副店長です。
今日はお休みをいただいてるんですが、今日もゴニョゴニョやってます。
さてさて、heroku + sinatra で DB を扱ってみようと思うんですが
まず自分のローカルにDB入ってないとダメでしょう。
ということで、本日のメニューは
「新しい相棒 MacBook Air (「にぼし号」と命名)に、
postgreSQLを入れてみよう!」 です。
( なぜかというと、heroku のデフォルトが postgreSQL だから)
手順はこんなカンジです
- postgreSQL のインストール
- pgAdmin のインストール
あ、予めMacPorts入れといてくださいね。
では作っていきましょう。
postgreSQL のインストール
コレがないとどうにもなりません。
まずは、このコマンドでpostgreSQLのバージョンを確認しましょう。
$ port search postgresql
見てみたところ、現時点では9.0が最新のようですので
コレをいれちゃいます。
$ sudo port install postgresql90
$ sudo port install postgresql90-server
入ったら、次は自動起動の設定をします。
(なんかログに出るやつそのままたたけば大丈夫です)
$ sudo launchctl load -w /Library/LaunchDaemons/org.macports.postgresql90-server.plist
DBの領域を確保して、初期化します
$ sudo mkdir -p /opt/local/var/db/postgresql90/defaultdb
$ sudo chown postgres:postgres /opt/local/var/db/postgresql90/defaultdb
$ sudo su postgres -c '/opt/local/lib/postgresql90/bin/initdb -D /opt/local/var/db/postgresql90/defaultdb'
あとそれと、起動と停止はこうです。
$ sudo su postgres -c '/opt/local/lib/postgresql90/bin/pg_ctl -D /opt/local/var/db/postgresql90/defaultdb -l /opt/local/var/db/postgresql90/logfile start'
$ sudo su postgres -c '/opt/local/lib/postgresql90/bin/pg_ctl -D /opt/local/var/db/postgresql90/defaultdb -m immediate stop'
では、入ったかやってみましょう。
$ /opt/local/lib/postgresql90/bin/psql -U postgres -l
DB一覧が出たら成功です。
おめでとうございます>自分
pgAdmin のインストール
pgAdminなんて便利なのがあるので、折角ですし入れましょう。
↓これMac用。さっくり落として、さっくさっく入れちゃってください。
http://www.pgadmin.org/download/macosx.php
入ったらさっくり起動して、さっくさっく繋いじゃいましょう。
データベース作ったりとか色々使い倒しましょう。>自分