スポンサーサイト

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

[nginx]アップロードサイズの上限を設定する

ファイルのアップロードが動作しないと思ったら
nginxのログに以下のメッセージが出てました。

client intented to send too large body



アップロードできる上限サイズを超えてしまっていたようです。
設定ファイルに「client_max_body_size」を追加して上限を大きくしました。

location / {
  ???
  client_max_body_size 20M;
}

スポンサーサイト

[Merb]アプリケーションのルートパスを取得する

Merbアプリケーションのルートパスなど、
触っている中で知ったものをいくつかメモしておきます。

# Merbアプリケーションのルートパス
Merb.root

# 実行されているモード(developmentやproductionなど)
Merb.env

# config/init.rbで設定されている値
Merb.config[:session_id_key]

# ユーザーエージェント
request.env["HTTP_USER_AGENT"]

[Merb]merb-authを使ってみる

Merbに最初から準備されているmerb-authという認証を
以下のページを参考にやってみました。

認証を用いたHelloWorld

Flash(Actionscript)のFileReference.uploadを使用してファイルを
アップロードしている箇所があるのですがなぜか認証がうまくいかないという
問題が出ました。

どうやらクッキーが渡されていないようです。

じゃあ手動でクッキーを格納したらどうかと以下のような感じでやってみました。

# Javascript
function getCookie(){
 return document.cookie;
}

# Actionscript
var request:URLRequest = new URLRequest(url);
var cookies = flash.external.ExternalInterface.call("getCookie").toString();
request.requestHeaders = new Array(new URLRequestHeader("Cookie", cookies));
fileRef.upload(request);



試してみましたが、サーバー側には値が送られてきませんでした。

もう少し調べてみると、リファレンス

URLRequest パラメータを受け取るメッソドすべてが requestHeaders プロパティをサポートしているわけではありません。呼び出すメソッドのマニュアルを参照してください。例えば、FileReference.upload() メソッドおよび FileReference.download() メソッドは、URLRequest.requestHeaders プロパティをサポートしていません。



という記述がありました。
ファイルアップロードの時にクッキーを設定したりするのは厳しそうです。

ということで、パラメータの一部に含めてサーバーに送ることにします。

# Actionscript
var request:URLRequest = new URLRequest(url);
var variables:URLVariables = new URLVariables();
variables["cookies"] = ExternalInterface.call("getCookie").toString();
request.data = variables;
fileRef.upload(request);



サーバー側でファイルアップロードを待ち受けているところだけ
認証を行う前に、POSTパラメータからクッキーを取り出して
本来クッキーが格納されるところに手動で入れてやります。

# vi app/helpers/global_helpers.rb
module Merb
 module GlobalHelpers
  # helpers defined here available to all views.
  def provide_cookies_from_params
   cookies = params[:cookies]
   cookies.split(";").each do |cookie|
    temp = cookie.split("=")
    request.cookies[temp[0]] = temp[1]
   end
  end
 end
end

# vi app/controllers/items.rb
class Items < Application
 before :provide_cookies_from_params, :only => :upload
 before :ensure_authenticated

 def index
 end

 def upload
 end
end



とりあえず動いたからOKにしました。

その後調べてみたところ、こんなライブラリもあるみたいです。
http://code.google.com/p/as3httpclientlib/
http://code.google.com/p/as3httpclientlib/wiki/Examples

これは便利そう。

[Merb]DataMapperのvalidation

前回に引き続きDataMapperについてです。
今回はvalidation関係を探ってみようと思います。

Modelを編集します。

vi app/models/entry.rb

class Entry
 include DataMapper::Resource

 validates_present :title, :content

 property :id, Serial

 property :title, String, :unique => true
 property :content, String

 has n, :comments
end



実行してみます。

rake db:automigrate
merb -i
entry = Entry.new
entry.title = "タイトル1"
entry.save



失敗しました。
validates_presentで指定されたフィールドは値を保存しないと怒られるようです。

entry.content = "内容1"
entry.save



次に別レコードで同じtitleを登録しようとします。

entry = Entry.new
entry.title = "タイトル1"
entry.content = "内容2"
entry.save



失敗しました。
unique指定しているため、ちゃんとチェックしてくれるようです。

事前に保存可能かどうかを調べるには・・

entry.valid?



でいけるみたいです。

後は独自のチェックをしたい場合は、Modelにチェックメソッドを定義したり
valid?をオーバーライドするとかでしょうか。

例えばcontentが10バイト未満をエラーにするとして・・

vi app/models/entry.rb

class Entry
 include DataMapper::Resource

 validates_present :title, :content

 property :id, Serial

 property :title, String, :unique => true
 property :content, String

 has n, :comments

 def vaiid?(context = :default)
  if !super(context)
   return false
  end
  if @content.length < 10
   return false
  end
  true
 end
end



試してみます。

merb -i
entry.title = "abcd"
entry.content = "123456789"
entry.valid?
=> false

entry.content = "1234567890"
entry.valid?
=> true



関連づけているModelまでチェックしてくれるのか試してみます。
commentのcontentを必須とします。

vi app/models/comment.rb

class Comment
 include DataMapper::Resource

 validates_present :content

 property :id, Serial

 property :entry_id, Integer
 property :content, String

 belongs_to :entry
end



実行します。

merb -i
entry = Entry.new
entry.title = "abcd"
entry.content = "1234567890"
entry.valid?
=> true

entry.comments.push(Comment.new)
entry.valid?
=> true



entry.valid?は通過しました。
どうやら関連づいたModelのチェックまではしないようです。

entry.comments[0].valid?
=> false



直接comment.valid?を呼ぶとfalseが返されます。
保存しようとするとどうなるのか。

entry.save

~ SELECT "id" FROM "entries" WHERE ("title" = 'abcd') ORDER BY "id" LIMIT 1
~ INSERT INTO "entries" ("content", "title") VALUES ('1234567890', 'abcd')
~ SELECT "id", "entry_id", "content" FROM "comments" WHERE ("entry_id" IN (3)) ORDER BY "id"
=> true



commentテーブルへの追加は行われませんでした。
ちゃんとcomment.contentにデータを入れます。

entry.comments[0].content = "comment"
entry.save

~ SELECT "id" FROM "entries" WHERE ("title" = 'abcd') ORDER BY "id" LIMIT 1
~ INSERT INTO "comments" ("entry_id", "content") VALUES (3, 'comment')
~ SELECT "id", "entry_id", "content" FROM "comments" WHERE ("entry_id" IN (3)) ORDER BY "id"
=> true



今度はcommentテーブルにデータを追加されました。

エラーメッセージは以下の方法で取得できるようです。

entry = Entry.new
entry.title = "abcd"
entry.valid?
=> false
entry.errors.full_messages
=> ["Title is already taken", "Content must not be blank"]



エラーコード的なものも取得できたら良いなと思ったのですが
よくわからなかったです。

[Merb]DataMapperを触ってみる

MerbのDataMapperを触ってみました。
RailsのActiveRecordすらまともに触ったことがないので手探りな感じです。

まずサンプルのModelを作ります。

merb-gen model entry title:string,content:string
merb-gen model comment content:string,entry_id:integer



記事とそれに関連づくコメントというイメージです。
次に2つのモデルを1対Nの関係にするため、Modelを修正します。

vi app/models/entry.rb

class Entry
 include DataMapper::Resource

 property :id, Serial

 property :title, String
 property :content, String

 has n, :comments
end

vi app/models/comment.rb

class Comment
 include DataMapper::Resource

 property :id, Serial

 property :entry_id, Integer
 property :content, String

 belongs_to :entry
end



DBを作成してサーバーを起動します。

rake db:automigrate
merb -i



entryテーブルにレコードを追加します。

entry = Entry.new(:title=>"タイトル1", :content=>"内容1")
entry.save



こんな書き方もできます。

entry = Entry.new
entry.title = "タイトル2"
entry.content = "内容2"



次はcommentテーブルにレコードを追加します。

comment = Comment.new(:content=>"タイトル1のコメント1", :entry_id=>1)
comment.save



entryとcommentを関連づけていますので、一発で保存することもできました。
(内部では2つのSQLが発行されています。)

entry = Entry.new(:title=>"タイトル3", :content=>"内容3")
comment = Comment.new(:content=>"タイトル3のコメント1")
entry.comments.push(comment)
entry.save



entry_idという名前を自動的に関連づけるIDと見なしてくれるようです。

次は検索ということで全件取得します。

entries = Entry.all



IDを指定して取得します。

entry = Entry.get(1)



取得フィールドを限定します。

entry = Entry.all(:fields => [:id, :title])
entry = Entry.get(1, :fields => [:id, :title])



ソートを指定してみます。

entries = Entry.all(:order => [:id.desc])



取得件数を絞ります。

entries = Entry.all(:order => [:id.desc], :offset => 1, :limit => 2)



commentを取得します。

entry = Entry.get(1)
entry.comments.each do |comment|
 puts comment.content
end



entryオブジェクトのメンバとしてアクセスできるわけですね。

今までガリガリSQL文を書いてきた経験しかないので
このオブジェクトを操作する感覚で、データを操作できるところがとても新鮮です。

結合して取得したり、複雑な検索条件をどうさばけばいいのかが気になるところです。
継続して調べていきたいと思います。

[Javascript+Flash]環境依存メモ

Flash(Actionscript)をJavascriptから操作するというようなことをやっていて
いくつか環境依存な問題が発生したので、メモしておきます。

1)AsからJsに提供する関数名は、Js側で定義済の関数名と重複するとNG(IE)

JavascriptからActionscriptを呼べるように
Actionscript側で以下のような方法で関数を公開することができます。

ExternalInterface.addCallback("hoge", fuga);

上記のhogeと同名の関数がJavascript側に定義されているとIEでエラーが発生しました。



2)Flashを子に持つdiv要素の幅と高さを小さくしたらFlashが消えた(IE6)

Flashをdiv要素の子として配置し、幅や高さを縮めるというようなことをしていたのですが、
ある大きさよりさらに縮めようとした場合、いきなりFlashが消えるという現象が発生しました。

結果的には、div要素のスタイルに、「overflow:hidden;」を設定することで回避できました。

例えば、IEで空のブロック要素を用意した場合、幅や高さを縮めても一定以下には縮まりません。

<div style="width:5px;height:5px"></div>

これは、IEは文字が入っていなくても文字の大きさ分だけサイズを確保しようとするのだとか。
これを狙い通り縮めるには、overflowを設定する必要があります。

空のブロック要素の場合は、単に縮まらないだけなのですが
Flashを子に持つ場合はFlashにまで悪影響を及ぼしてしまうようでした。



3)wmodeを設定する場合は、Flashを表示領域内に配置する(Win + Fx)

透明なFlashを用意して、「top:-100px;left:-100px」として表示領域外に
配置していたのですが、WindowsのFirefoxだけなぜかFlashが動いてくれないという
現象が起きました。

どうやらwmodeを設定する場合には、ブラウザの表示領域にFlashがこないと
レンダリングされないようです。

参考:http://d.hatena.ne.jp/Cherenkov/20090321/p1

透明である必要はなかったので、wmodeの設定をやめたら無事動きました。


プロフィール

jou4

Author:jou4
FC2ブログへようこそ!

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

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