新年のご挨拶まわり
新年そうそうユルさんが風邪をひいてしまったので初詣は延期。雑煮を初めて作ったのだけど、もちを煮すぎて失敗してしまった。でもまあまあうまかった。
ぼくひとりで近所のネコたちに新年のご挨拶まわりにいきました。
新年そうそうユルさんが風邪をひいてしまったので初詣は延期。雑煮を初めて作ったのだけど、もちを煮すぎて失敗してしまった。でもまあまあうまかった。
ぼくひとりで近所のネコたちに新年のご挨拶まわりにいきました。
すべての関数はモジュールに属している。
-module(restaurant).
関数は以下のように定義する。
menu(coffee) -> 190; menu(burger) -> 290; menu(coke) -> 100.
これをシェル(つまり外部)から使うにはexport定義をしてやる必要がある。
-export([menu/1]).
関数名のあとのスラッシュの後ろは引数の数を表している(これをアリティと呼ぶ)。
実際にシェルから使ってみる。
1> c(restaurant).
{ok,restaurant}
2> restaurant:menu(coffee).
190
3> restaurant:menu(coke).
100
無名関数はfunという名前で定義する。
1> SubTotal = fun(Item, Count) -> restaurant:menu(Item) * Count end. #Fun<erl_eval.12.115169474> 2> SubTotal(coffee,3). 570 3> SubTotal(burger,2). 580
listsモジュールには、RubyでいうEnumerableモジュールのような便利な関数がそろっている。
4> lists:map(fun({Item, Count}) -> restaurant:menu(Item) * Count end, [{coffee, 3}, {burger, 2}]).
[570,580]
map関数の第一引数に、リストの各要素に適用される関数を指定してあげる。第二引数はそのリストだ。
funを返す関数も定義できる。
5> Member = fun(Count) -> (fun(Item) -> restaurant:menu(Item) * Count end) end. #Fun<erl_eval.6.56006484> 6> ItemValue = Member(3). #Fun<erl_eval.6.56006484> 7> ItemValue(coffee). 570 8> ItemValue(burger). 870
リスト内包表記を使うと、もっと簡潔にリスト処理が行える。
9> [{restaurant:menu(Item), Count} || {Item, Count} <- [{coffee, 3}, {burger, 2}]].
[{190,3},{290,2}]
10> lists:sum([restaurant:menu(Item) * Count || {Item, Count} <- [{coffee, 3}, {burger, 2}]]).
1150
最近、将棋がおもしろくてよくやるのだけど、下手くそなへぼ将棋なので、コンピュータ相手になかなか勝てない。頭の悪さを認識する今日この頃である。Erlangの勉強をしていてもよく思うのだけど、二十歳の頃は本を一度読めばだいたい理解できたのに、今は何度か同じところを読み返してさらに動かしてみたりしないとなかなか理解できない。大人になるほど阿呆になるんだな。
MXTVでガッチャッマンをやっているのだけど、意外とおもいろくてみてしまう。コンドルのジョーがシブい。
NSR感がよく出ているいい動画。やっぱり2stはいいなあ。
ガードは、パターン照合に条件を付与することができる。カンマ区切りで論理積になり、セミコロン区切りで論理和となる。
cource(X) when is_integer(X), X > 0 -> "cource No." ++ integer_to_list(X); cource(X) when is_integer(X), X =:= 0 -> "cource is ALL"; cource(X) -> "cource is bad!".
こうしておけば、
1> restaurant:cource(1). "cource No.1" 2> restaurant:cource(0). "cource is ALL" 3> restaurant:cource(aa). "cource is bad!"
となる。
論理和で上記の関数を定義していると結果は当然、
1> restaurant:cource(1).
"cource No.1"
2> restaurant:cource(0).
"cource No.0"
3> restaurant:cource(aa).
=ERROR REPORT==== 4-Jan-2009::23:03:07 ===
Error in process <0.30.0> with exit value: {badarg,[{erlang,integer_to_list,[aa]},{restaurant,cource,1},{erl_eval,do_apply,5},{shell,exprs,6},{shell,eval_loop,3}]}
** exited: {badarg,[{erlang,integer_to_list,[aa]},
{restaurant,cource,1},
{erl_eval,do_apply,5},
{shell,exprs,6},
{shell,eval_loop,3}]} **
こうなる。最後の、引数がアトムのときの例外は、integer_to_list()の部分で発生している。
しろさん(近所の野良猫さん)が野鳥を捕まえてばりばり食べていた。普段は甘えてくるかわいらしいネコだけど、ちゃんと野生なのだ。カッコよかったし、エサがなくても生きていけそうなので安心した。
以前、「RMagickのメモリばか喰いを解決する方法」という記事を書いたけど、同じくらい馬鹿馬鹿しい方法がある。
それはRMagickを使わないという方法だ。
def create_thumbnail(in_file)
out_file = generate_thumbnail_name(in_file)
`/usr/local/bin/convert #{in_file} -thumbnail 50x50 #{out_file}`
end
これでメモリリークとはおさらばである。
まあ、サムネイル画像を作る程度の機能でいいのなら、ImageScienceとかを使うのがおすすめです。実際のところ、RMagickほどの機能が必要なことってwebアプリではあまりないと思う。
「ちはやふる (1) (Be・Loveコミックス)」を読みました。会社の同僚の人におすすめしてもらったもの。おもしろかったです。
Railsのバージョンを2.1.2にあげたらvalidates_uniquness_ofでActiveRecord::StatementInvalid例外が出るようになった。
TypeError: wrong argument type Hash (expected String): ....... vendor/rails/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb:147:in `log' vendor/rails/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb:302:in `execute' vendor/rails/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb:537:in `select' vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:7:in `select_all_without_query_cache' vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:59:in `select_all' vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:80:in `cache_sql' vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:59:in `select_all' vendor/rails/activerecord/lib/active_record/validations.rb:651:in `validates_uniqueness_of'
vendor/rails/activerecord/lib/active_record/validations.rbの651行目を見てみる。
results = finder_class.with_exclusive_scope do
connection.select_all(
construct_finder_sql(
:select => "#{connection.quote_column_name(attr_name)}",
:from => "#{finder_class.quoted_table_name}",
:conditions => [condition_sql, *condition_params]
)
)
end
どうも、select_allに文字列のSQLを渡さなきゃいけないのに、Hashが渡っていることでエラーになっている。
なので、construct_finder_sqlメソッドを見てみる。
def construct_finder_sql(options)
scope = scope(:find)
sql = "SELECT #{options[:select] || (scope && scope[:select]) || ((options[:joins] || (scope && scope[:joins])) && quoted_table_name + '.*') || '*'} "
sql << "FROM #{(scope && scope[:from]) || options[:from] || quoted_table_name} "
add_joins!(sql, options, scope)
add_conditions!(sql, options[:conditions], scope)
add_group!(sql, options[:group], scope)
add_order!(sql, options[:order], scope)
add_limit!(sql, options, scope)
add_lock!(sql, options, scope)
sql
end
それぞれのメソッドもたどって見たけど、このメソッドはちゃんと文字列のSQLを返していた。どこかで悪さをしているやつがいるらしい。
と思ってプラグインを調べたらActsAsReadonlyableが犯人だった。
def construct_finder_sql(options)
options.merge(:sql => super)
end
こんなことしている。なので、select_allをオーバライドして仮対処してみた。
module ActiveRecord
module ConnectionAdapters
class AbstractAdapter
def select_all(sql, name = nil)
sql = sql[:sql] if sql.is_a?(Hash)
select(sql, name)
end
end
end
end
会社のキーボードを特に気にせず使っているけど、マウスをさわるためにキーボードから手を離すのがメンドくさいので「Lenovo ThinkPlus USBトラベルキーボード ウルトラナビ付 31P9514」なんかでも来月のおこづかいで買おうかと思っている。Thinkpadのキーボードとトラックポイントは最高だから。ただ高いんだよね、これ。なんでこのキーボードこんなに高くなってるんだろう。
日曜日は東名高速で沼津までドライブしました。田子の浦にうち出でてみて富士の高嶺に雪が積もっているのを眺めてから、富士宮市でラーメンを食べます。このラーメン、油がすごくて、ユルさんはダブルクオーターパウンダーを食べたぼくみたいにやられていました。
朝霧高原で一面の雪化粧を堪能してから都内に戻って夜景を楽しみました。レインポーブリッジから見える夜景は、自分が世界三大都市のひとつに住んでいることを実感させてくれておすすめです。おもしろかった。
今朝早く、リビングに置いてあるサーバから異音が響いてきて目がさめます。ガラガラという音はどうもハードディスクっぽい感じだったけど、とりあえず電源を落として会社に行きました。
ところが、帰ってきてからひとつづつハードディスクを確かめてみたけどなんの異常もなく起動してしまった。またすぐに異音が出るようになりそうだけど、どのハードディスクが原因なのか見極めができてないので外すこともできません。ログにも何も吐かれてないのでお手上げ状態。もうちょっと様子見しましょう。
http://www.nichinan-uji.jp/modules/myalbum32/photo.php?lid=70&cid=71#top1
この前、ユルさんと九州へのUターンの話をしていていろいろ調べていたら、宮崎県のサイトにUターンしたい人のためのページが用意されていて、そこで飫肥の街の空き家が紹介されていました。
飫肥の街は古い町並みが残る静かな観光地で、ぼくとユルさんは何度も訪れているのですが、とても住みやすそうないいところです。そこでこんな家があったのでふたりで盛り上がってしまいました。
土地が293.51坪で、建物の面積が43.94坪なので相当に庭は広いです。バイクや工作のためのガレージを建てたり庭園鉄道を走らせたりできそう。さらに外装のリフォームには自治体から補助が8割も出るようです。内装が幽霊が出そうな感じなので古民家風なカッコいいものにしたりとかいろいろと想像を楽しみました。
merbをちゃんとやろうと、環境を整えてmerbアプリを作ってmerbコマンドで起動しようとしたら、
[tsukasa@ubuntu] $ merb Loading init file from /home/tsukasa/test/config/init.rb Loading /home/tsukasa/test/config/environments/development.rb ~ ~ FATAL: The gem dm-core (= 0.9.8, runtime), [] was not found
のようなエラーが出た。dm-coreのバージョンが0.9.9だったので、config/dependencies.rbを以下のように修正する。
dm_gems_version = "0.9.9"
でもやっぱりダメだ。詳しくみるために--verboseオプションをつけてみた。
[tsukasa@ubuntu] $ merb --verbose [~/test] ~ Running bootloaders... Loading init file from /home/tsukasa/test/config/init.rb Loading /home/tsukasa/test/config/environments/development.rb ~ Loaded DEVELOPMENT Environment... ~ Expanding RUBY_PATH... ~ loading gem 'merb-action-args' ... ~ loading gem 'merb-assets' ... ~ loading gem 'merb-cache' ... ~ loading gem 'merb-helpers' ... ~ loading gem 'merb-mailer' ... ~ loading gem 'merb-slices' ... ~ loading gem 'merb-auth-core' ... ~ loading gem 'merb-auth-more' ... ~ Registered slice 'MerbAuthSlicePassword' located at /usr/lib/ruby/gems/1.8/gems/merb-auth-slice-password-1.0.7.1 ~ loading gem 'merb-auth-slice-password' ... ~ loading gem 'merb-param-protection' ... ~ loading gem 'merb-exceptions' ... ~ ~ FATAL: The gem dm-core (= 0.9.9, runtime), [] was not found ~ ~ FRAMEWORK_ROOT = /usr/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib ~ ~ Gem::LoadError: Could not find RubyGem launchy (>= 0.3.2) ~ ./config/dependencies.rb:18 ~ /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require' ~ /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:31:in `require' ~ /home/tsukasa/test/config/init.rb:3 ~ FRAMEWORK_ROOT/merb-core/bootloader.rb:520:in `load' ~ FRAMEWORK_ROOT/merb-core/bootloader.rb:520:in `load_initfile' ~ FRAMEWORK_ROOT/merb-core/bootloader.rb:388:in `run' ~ FRAMEWORK_ROOT/merb-core/bootloader.rb:99:in `run' ~ FRAMEWORK_ROOT/merb-core/server.rb:172:in `bootup' ~ FRAMEWORK_ROOT/merb-core/server.rb:42:in `start' ~ FRAMEWORK_ROOT/merb-core.rb:170:in `start' ~ /usr/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/bin/merb:11 ~ /usr/bin/merb:19:in `load' ~ /usr/bin/merb:19
お? launchy といえものがないらしい。なので入れてみた。
sudo gem install launchy
そしてmerb起動。
Loading init file from /home/tsukasa/test/config/init.rb Loading /home/tsukasa/test/config/environments/development.rb ~ Connecting to database... ~ Loaded slice 'MerbAuthSlicePassword' ... ~ Parent pid: 6331 ~ Compiling routes... ~ Activating slice 'MerbAuthSlicePassword' ... merb : worker (port 4000) ~ Starting Mongrel at port 4000 merb : worker (port 4000) ~ Successfully bound to port 4000 merb : worker (port 4000) ~ Started request handling: Fri Jan 16 08:29:35 -0500 2009
動いた! やった~。
merbでは
thor merb:gems:install
というコマンドでMERB_ROOT/gems以下に依存するgemsライブラリを入れてくれます。これって公開サーバにいちいちgemをインストールしなくていいってことですね。Railsだとそこでしくじって間抜けなinternal errorになったりするのでうれしい機能。
・merbの勉強
・TRPG(第7回)
・Rails勉強会@東京(第37回)
・ユルさんとのんびり
土曜の夜は午前3時までTRPGやっていたので、日曜の朝は眠かったです。
今日の飲み会で、ガンダム00のマリナ・イスマイールが何歳なのか、という話で盛り上がった。ユルさんの情報によると27歳だそうだ。
土曜日はユルさんにつきあって北千住まで。彼女が律さんとコミケの打ち合わせがあったのでした。行く途中の千代田線で、北千住を通り過ぎたと思ってあわてて降りたら次の駅が北千住だったりしました。千代田線は狐に化かされたりするので注意が必要です。北千住ではケーキを食べました。あと、ネコが三匹雪まみれになっているカレンダーがあったのでちょっと欲しかったけど我慢しました。
merbの勉強をちょっとしました。けどなんだか飽きてきていて放置気味です。Railsもちょっと飽きてきているので困りものであります(ホントは困っていない)。Erlangの勉強もしました。こっちはおもしろいですね。全然違うものをすると脳が活性化する感覚が顕著で、とても気持ちがいいのです。
景虎という日本酒をユルさんに買ってもらいました。おかげで土日の晩はのんびり楽しみます。焼き魚が欲しいな。
近所を散歩しました。しろさん(近所のネコです)を最近見ないので探しにいったのでした。しかし見つからず。あんなにいっぱいネコがいるのに、まったく見かけないときもあるのが不思議です。どこかで暖をとっているのでしょうか。
ひさしぶりにエースコンバット4をしています。今さらです。サラ・コナーです。ターミネーター3はなかったことにされそうですね。なんの話でしょうか。
tokyobikeのブルホーンハンドル化計画の構想を練っていました。去年はストイックに自転車に乗っていたのですが今年は方向転換しておしゃれに気軽に自転車とつきあっていこうと思います。自転車通勤したいなあ。
同じようなことを考える人はどこにでもいるものです。
ここだけの話なのでご内密にお願いしたいのですが、デザインを変えたといっても、実は黒いのが白くなっただけで全然変わっていないのです(どきどき)。
今日はユルさんのお祝いだったので黄色いバラを買って帰りました。よろこんでもらえたのでよかった。
AR の古いバージョンだけなのかもしれないけど、今日、after_createが連続して2回コールされる現象に出会いました。レコードはひとつしか作られていないのです。でもafter_createが2回コールされ、両方とも同一のインスタンスのもので、コールされる時間もほぼ連続的といっていいのです。
after_createのブロック群はStringやProcの形で配列に保存されていて、コールされるタイミングでその配列のそれぞれのブロックが順繰りに呼ばれます。そこに同じProcがふたつ存在しているのではないかと疑ったのだけど、そうではありませんでした。いろいろ調べたのだけど結局原因はわからず。
仕方なくafter_createを使うのをあきらめたのだけど、ヒマを見ては原因追跡をやっていこうと思います。