2009年12月19日土曜日

PostGISで使う SRID

自分に必要なのはこれだけかな。

select * from spatial_ref_sys where srid in (4301, 4326)

結果を要約すると、
4301 → Tokyo (いわゆる日本測地系。日本の地図でけっこう使われている)
4326 → WGS 84 (いわゆる世界測地系。Google Maps等で使われている)


参考:Bubble://ちずろぐ/別巻/ SRIDList

PostGIS調査メモ

参考になったリンクや、後で見るかもしれないリンクの集。それに加えて気づいたことのメモ。



インストール


Shapeファイル関連


マニュアル和訳

2009年12月15日火曜日

PHPで GDを使って画像ファイルに文字列を書き込む例

とりあえずよく使いそうな機能はこんなとこか。
楕円書いたりいろいろできるみたいだけど、使うかな?
四隅を角丸にしたいかも...

<?php
$string = 'こんにちはこんにちは!';
$fontSize = 12;
$padSize = 10;
$angle = 0; //角度を指定できる
$fontPath = 'C:/WINDOWS/Fonts/MSGOTHIC.TTC'; //Windowsの場合

try {
//文字列の大きさを取得 http://jp2.php.net/imageTtfBBox
$box = imageTtfBBox($fontSize, $angle, $fontPath, $string);
if ($box === false) {
throw new Exception('imageTtfBBox()失敗');
}
$boxWidth = abs($box[2] - $box[0]);
$boxHeight = abs($box[7] - $box[1]);

//キャンバス生成 http://jp2.php.net/imageCreateTrueColor
$width = $boxWidth + $padSize * 2;
$height = $boxHeight + $padSize * 2;
$img = imageCreateTrueColor($width, $height);
if ($img === false) {
throw new Exception('imageCreateTrueColor()失敗');
}

//背景色と文字色をそれぞれ造る
// http://jp2.php.net/imageColorAllocate
// http://jp2.php.net/imageColorAllocateAlpha (透過の場合)
$red = 0xFF;
$green = 0x00;
$blue = 0x00;
$bgColor = imageColorAllocate($img, $red, $green, $blue);
if ($bgColor === false) {
throw new Exception('imageColorAllocate()失敗');
}
$red = 0xFF;
$green = 0xFF;
$blue = 0xFF;
$alpha = 20; //0~127。127は完全に透明
$textColor = imageColorAllocateAlpha($img, $red, $green, $blue, $alpha);
if ($textColor === false) {
throw new Exception('imageColorAllocate()失敗');
}

//キャンバスに色を塗る http://jp2.php.net/imageFill
$startX = 0;
$startY = 0;
if (!imageFill($img, $startX, $startY, $bgColor)) {
throw new Exception('imageFill()失敗');
}

//文字を書く http://jp2.php.net/imageTtfText
$startX = $padSize;
$startY = $boxHeight + $padSize; //左下の座標を指定する
if (!imageTtfText($img, $fontSize, $angle, $startX, $startY, $textColor, $fontPath, $string)) {
throw new Exception('imageChar()失敗');
}

//出力(第2引数にファイルパスを渡すとファイルに保存する)
$type = 'gif';
header('Content-type: image/' . $type);
switch ($type) {
case 'gif': // http://jp2.php.net/imageGif
$result = imageGif($img);
break;
case 'jpeg': // http://jp2.php.net/imageJpeg
$quality = 100; //0~100。大きいほど高品質。デフォルトは75
$result = imageJpeg($img, null, $quality);
break;
case 'png': // http://jp2.php.net/imagePng
$quality = 0; //0~9。小さいほど高品質
$result = imagePng($img, null, $quality);
break;
}
if (!$result) {
throw new Exception('出力失敗');
}
} catch (Exception $e) {
header('Content-type: text/html');
echo $e->getMessage();
}

//後始末 http://jp2.php.net/imageDestroy
if ($img && !imageDestroy($img)) {
throw new Exception('imageDestroy()失敗');
}

Google Maps API V3と V2の機能比較

列挙しようかと思ったがけっこうありそうなので、とりあえず思いついたものだけメモ。


V2になくてV3にあるもの

  • 複数の吹き出し(InfoWindow)を同時に表示できる


V2にあってV3にないもの
  • ストリートビュー
  • Overview(右下の縮小地図)
  • Polygonの面積の取得
  • Polylineの長さの取得
  • GoogleBar(検索ボックス)
  • AdsManager

Google Maps API 有償版(プレミア)調査メモ

現時点での調査メモ。
実際に使うなら、最新情報の確認および問い合わせをした方がよい。


公式紹介ページ
1. Googleの紹介ページ
Google Maps API Premier - データを視覚化
2. ゼンリンによる紹介ページ(概要)
法人向けサービス:Google Maps API Premier | ゼンリンデータコム
3. ゼンリンによる紹介サイト(詳細)
プレミアについて/Googleマップの商用サービス GoogleMapsAPIプレミア

参考になるのは3番。


プレミアを使うことの主なメリット



料金について



Google Maps API利用規約についての参考ページ
Google Maps APIの利用規約について - Google-Maps-API-Japan | Google グループ

Windowsに Git (TortoiseGit)をインストール

手順をメモしたがメモする程でもなかった。

  1. tortoisegit - Project Hosting on Google Codeの右側の「Blogs:」にあるリンク「Latest Version(32bit)」からMSIをダウンロードして実行(インストール)
  2. msysgit - Project Hosting on Google Codeの右側の「Featured downloads:」にあるリンク「Git-[バージョン番号等].exe」からexeをダウンロードして実行(インストール)
    • TortoiseGitを使うなら、「Git GUI Here」「Git Bash Here」やデスクトップ等へのショートカットは作らない方が煩わしくなくて良いと思う

2009年12月4日金曜日

PHPでの配列の並び替え(ソート)の比較

PHP5.3で実験。
何気なくsort()を使うと、意外と意外な結果になるので注意。

$before = array('Google', 'apple', '+11112', 1112, '112', 12, '0', -1);

$array = $before;
sort($array);
foreach ($array as $val) echo $val . ', ';
//sort()の第2引数のデフォルトはSORT_REGULAR
//文字列は大文字優先
//今回のように数値と文字列が混在するとおかしくなる?
// => -1, 0, 112, Google, apple, 12, 1112, +11112,
echo '<hr />';

$array = $before;
sort($array, SORT_NUMERIC);
foreach ($array as $val) echo $val . ', ';
//数値としてソート
//文字列は大文字・小文字を無視したソートで、ゼロの前になるようだ
// => -1, apple, Google, 0, 12, 112, 1112, +11112,
echo '<hr />';

$array = $before;
sort($array, SORT_STRING);
foreach ($array as $val) echo $val . ', ';
//文字列としてソート
//記号、数字、文字列(大文字優先)の順
//数は数ではなく文字列としてソートされる
// => +11112, -1, 0, 1112, 112, 12, Google, apple,
echo '<hr />';

$array = $before;
sort($array, SORT_LOCALE_STRING);
foreach ($array as $val) echo $val . ', ';
//localeごとのソート(今回の環境ではSORT_STRINGと同じだった)
// => +11112, -1, 0, 1112, 112, 12, Google, apple,
echo '<hr />';

$array = $before;
natsort($array);
foreach ($array as $val) echo $val . ', ';
//「自然順アルゴリズム」
//人間がやったらまあこうするだろうという感じか
//記号、数、文字列の順
//数値は文字列ではなく数値としてソートされるのがSORT_STRINGとの違い
// => +11112, -1, 0, 12, 112, 1112, Google, apple,
echo '<hr />';

$array = $before;
natcasesort($array);
foreach ($array as $val) echo $val . ', ';
//「自然順アルゴリズム」、かつ大文字小文字を区別しない
// => +11112, -1, 0, 12, 112, 1112, apple, Google,

natcasesort()が一番しっくりくる。
大文字・小文字の違いは無視して欲しいし。

2009年12月2日水曜日

もう一歩踏み込んでGoogle Maps APIを使いこなすための12の参考サイト

(2010/09/02:情報が古くなっていたので全面的に改定)


Google Codeにあるもの(全て英語)

Google Maps JavaScript API V2 Reference - Google Maps JavaScript API V2 - Google Code

  • Google Maps API V2(Version 2)のリファレンス
  • V2は既にDeprecatedだが、V3にはまだ無い機能もあるので場合によってはV2が必要になる
  • 日本語のリファレンスはどこにいった?(以前からUpdateが追いついていなかったが...)

Google Maps Javascript API V3 Reference - Google Maps JavaScript API V3 - Google Code
  • Google Maps API V3 (Version 3)のリファレンス
  • V2には無かった円を描く機能がある

gmaps-utility-library-dev - Project Hosting on Google Code

google-maps-utility-library-v3 - Project Hosting on Google Code
  • Google Maps API V3のための準公式プラグイン集
  • だいぶ増えてきた
  • Google Maps API V3にはまだ無いOverview Controlを追加するプラグインもある

gmaps-api-v3-googlebar - Project Hosting on Google Code
  • Google Maps API V3にはまだ無いGoogleBar(Local Search Control、検索窓)を追加するプラグイン

google-maps-icons - Project Hosting on Google Code

Dynamic Icons - Google Chart Tools / Image Charts (aka Chart API) - Google Code
  • Google Chart APIの、動的にアイコンを生成する機能
  • 生成したアイコンはGoogle Mapsのマーカー画像として使える

gmaps-api-issues - Project Hosting on Google Code
  • Google Maps APIへの要望やバグ報告など

(おまけ)
Google Mapsの中心人物だったPameraさんのGoogle Code上のプロジェクト一覧
pamela.fox - Project Hosting on Google Code



その他


Google Maps 活用講座 - GoogleマップAPIの使い方を分かりやすく解説!
  • 初心者から上級者まで参考になりそう

Google Mapsをほどよくカスタマイズしてお手軽に表示 - Google Mapper [ゼロと無限の間に]
  • Google Maps API V2をサクッと使うためのプラグイン

Google Maps API V3を使って地図をお手軽に表示 - Google Mapper V3 [ゼロと無限の間に]
  • Google Maps API V3をサクッと使うためのプラグイン

2009年11月28日土曜日

Googleサイト内検索結果でページの下端が切れる問題

検索向けAdSenseによるサイト内検索で、IE以外だと検索結果の下端が切れてしまう問題について。


【発生条件】
検索結果を自分のサイト内に表示する場合に起きる。
広告を右のみにした場合に起きた。広告を他の位置にしたら起きないかも。
Firefox(3.5)、Google Chrome(4)、Safari(4 Windows版)で発生を確認した。


【現象】
検索結果の内容に関わらず、検索結果を表示するiframe(JavaScript http://www.google.com/afsonline/show_afs_search.js により生成される)の高さが常に1200pxになる。
その結果、検索結果が少ない場合は検索結果とフッターの間に大きな空白ができる。反対に検索結果が多い場合、検索結果の下端に表示されるページ番号の表示が途中で切れてしまったり表示されなくなってしまう。(実際にはframeの外側にあり、かつframeのスクロールバーが非表示になっているので隠れているだけだが。)


IEの場合、iframe内の検索結果のHTMLのbody要素に、onloadで下記のようなJavaScriptを実行している。

onload="window.top.location='http://(親windowの検索結果のURL)#'+document.body.scrollHeight;"
これにより、親windowのURLの末尾にiframe内のコンテンツの高さを表すhashが付く。

そして検索結果のshow_afs_search.jsの方でlocation.hashを取得し、それをiframeの高さとして設定している。(0.01秒ごとに実行するという監視をしている。高さが取得できた後も。)
その結果、検索結果のコンテンツの内容に応じて検索結果をリサイズするというユーザーフレンドリーなユーザーインターフェイスを実現している。

試しに検索結果を表示した後、URLの最後に「#500」などと付けると検索結果の高さが変わる。これはFirefoxでも有効。


なぜIE以外ではiframe内のbodyのonloadのJavaScriptを付けないのだろう?Firefoxのセキュリティ等により無意味なんだろうか?


【回避策】
検索結果を表示するページのgoogleSearchXxxを設定しているJavaScriptに、下記のように高さを明示的に指定してあげる。
var var googleSearchFrameWidth = 800; //これは既存のコード
var googleSearchFrameHeight = 1210; //これを追加する
これにより、デフォルトの高さが1210pxになり、検索結果の下端が切れなくなる。

IEの場合、これでもリサイズが有効なので、この値は無視してリサイズしてくれると思う。

CakePHPの GetText (i18n)で複数形の翻訳をする

はまったのでメモ。最初からリファレンスや参考サイトを見ながらやれば書いてあったんだろうけど。


CakePHPで単数と複数で異なる翻訳を付けようとした。

__n(' person', ' people', $count);
poファイルも書いた。
msgid " person"
msgid_plural " people"
msgstr[0] "人"
msgstr[1] "人"

するとエラー(Warning)が表示された。
Warning (2): strlen() expects parameter 1 to be string, array given ...


該当箇所はCORE/cake/libs/i18n.phpのtranslate()。
if (is_array($trans)) {
if (isset($trans[$plurals])) {
$trans = $trans[$plurals];
}
}
if (strlen($trans)) {
$singular = $trans;
return $singular;
}
strlen()に配列を渡しているようだ。
でもその上で$transが配列の場合は文字列に入れ替えてるはず。(変数の使いまわしは良くないと思う。)それが効いてないのは「isset($trans[$plurals])」がfalseになっているということか。

この$pluralsをセットしているところを追うと、今回の場合は同じファイル内の__pluralGuess()によりセットしているようだ。
__pluralGuess()の中を追うと、$headerの中身で判断してるようだ。
if (strpos($header, "plurals=3")) {
if (strpos($header, "100!=11")) {
if (strpos($header, "10<=4")) {
return $n % 10 === 1 && $n % 100 !== 11 ? 0 : (略)

$headerを出力してみる。
nplurals=INTEGER;plural=EXPRESSION;

ん?さっきのif文の条件と似ても似つかない。
これは...poファイルで何か設定不足?

poファイルの最初の方を見てみる。
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
まさにこれだ。

こうしてみる。(キャッシュの削除も忘れずに。)
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

動いた!

以上。

2009年11月6日金曜日

PHPで Fatal Error時の状況を調べる方法

PHPでFatal Errorが発生すると以降の処理が実行されない。
かつ、try/catchやset_error_handler()ではFatal Errorを捕まえられない。
なので通常は、Fatal Errorが起きたときの詳しい状況はログに残らない。
(例えばエラーが起きたPHPのファイル名はログに残るが、それを呼び出した側のPHP名や、データの状況は分からない。)

しかし、register_shutdown_function()を使えばエラーが起きたときの状況をログに残せる。

register_shutdown_function('shutdownHandler');

function shutdownHandler(){
$error = error_get_last();
if ($error['type']) { //エラーの場合のみ
error_log(...); //必要な情報を書き出す。
}
}

ただしこれだとE_NOTICEとかでもひっかかってしまうので、Fatal Errorだけを拾いたい場合はtypeを指定する。
register_shutdown_function('shutdownHandler');

function shutdownHandler(){
$error = error_get_last();
if ($error['type'] == E_ERROR) {
error_log(...); //必要な情報を書き出す。
}
}
これだとExceptionが拾えない?


参考:
PHP の「エラー処理ハンドラ」「シャットダウンハンドラ」「例外処理ハンドラ」の挙動 - Web/DB プログラミング徹底解説
PHP: register_shutdown_function - Manual

JavaScriptで画像の大きさを縮小する方法

半分にするならこんな感じ。

<img src="test.jpg" alt="test" onload="this.width /= 2" />


最大値を決めてそれ以下になるようにするならこんな感じ。
<img src="test.jpg" alt="test" onload="this.width = Math.min(this.width, 100)" />


widthを変えれば勝手にheightも同じ比率で変わってくれるようだ。
Firefox3.5とIE7のみで確認。

CakePHPで用意されている layout

CakePHPでは、コントローラでlayoutを指定すれば任意のlayoutを使うことができる。
通常layoutは自分で用意するが(たいていはdefalut.ctp)、いくつか組み込みのlayoutが用意されている。
それぞれどんな出力になるか試してみた。

なお、以下のサンプルで使っているviewの中身は下記の通り。

test


1. $this->layout = 'ajax' の場合の出力結果
test
<!-- 1.7983s -->


2. $this->layout = 'flash' の場合の出力結果
(コントローラ内で$this->flash('foo', 'bar');をセット済み)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>foo</title>

<style><!--
P { text-align:center; font:bold 1.1em sans-serif }
A { color:#444; text-decoration:none }
A:HOVER { text-decoration: underline; color:#44E }
--></style>
</head>
<body>
<p><a href="/test/bar">foo</a></p>
</body>
</html><!-- 1.6536s -->
詳細はよく分からないが、何かFlashのために便利なものなのだろう、きっと。


その他にjs、xml、rssというディレクトリが用意されているがそのままでは使えない。マニュアルを参考に自分でlayoutを作るようだ。(RSSの場合はこちら(Layout :: Controller Code :: Creating an RSS feed with the RssHelper :: RSS :: Core Helpers :: The Manual :: 1.2 Collection :: The Cookbook)をコピーすればすむかも。


参考:Layouts :: Views :: Developing with CakePHP :: The Manual :: 1.2 Collection :: The Cookbook

Safariだけ img要素の onloadの動きが違う

動的にsrc属性の値を変えた時、かつ変更前と変更後のsrc属性の値が同じ場合にonloadが実行されるかどうかが違う。
IE(7)、Firefox(3.5)ではonloadが実行されたが、Safari(4)では実行されなかった。


テスト用コード

<img src="test.jpg" alt="test"
 onload="alert('Loaded!')"
 onclick="this.src = 'test.jpg'" />


load時に"Loaded!"が表示されるのは同じだが、クリックした時にsrc属性に同じ値をセットしたタイミングで、Safariだけはonloadが走らない。
src属性にセットする値が元の値と別ならば、Safariでもonloadが走る。

こんな感じならSafariでもonloadが走る。
<img src="test.jpg" alt="test"

 onload="alert('Loaded!')"

 onclick="this.src = 'test2.jpg'" />




Safari曰く、「変わってないからloadしてない、だからonloadではない」そうだ。(推測)

YUI AutoCompleteを使うコードの例

【CSS】
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.8.0r4/build/autocomplete/assets/skins/sam/autocomplete.css" />


【JavaScript】
<script type="text/javascript" src="http://yui.yahooapis.com/combo?2.8.0r4/build/yahoo-dom-event/yahoo-dom-event.js&2.8.0r4/build/animation/animation-min.js&2.8.0r4/build/datasource/datasource-min.js&2.8.0r4/build/autocomplete/autocomplete-min.js"></script>

<script type="text/javascript">
new YAHOO.widget.AutoComplete(
    "myInput",
    "myContainer",
    new YAHOO.util.LocalDataSource(["とうきょう", "とちぎ", "とやま"]),
    {useShadow: true} //AutoCompleteに影を表示
);
</script>


【HTML】
<div style="width:15em">
    <input id="myInput" type="text">
    <div id="myContainer"></div>
</div>


参考:YUI 2: AutoComplete

Rails 2.xで XMLサイトマップを生成する方法

Rails2.3で試した。
必要最低限の要素のみ。


config/routes.rb

map.connect "sitemap.xml", :controller => :test, :action => :sitemap


controllers/test_controller.rb
class TestController < ApplicationController
def sitemap
# サイトマップとして送信したいページのURL生成に必要な情報を取得する
@members = Member.find(:all)
@entries = Entry.find(:all)

  headers["Content-Type"] = "text/xml; charset=utf-8"

  respond_to do |format|
format.xml {render :layout => false}
end

end
end


views/test/sitemap.xml.builder
xml.instruct!
xml.urlset(:xmlns => "http://www.sitemaps.org/schemas/sitemap/0.9") do
# トップページ
xml.url do
xml.loc(url_for(:controller => :top, :only_path => false))
end
      
# 個別のページ
@members.each do |member|
xml.url do
xml.loc(url_for(:controller => :members, :action => :show, :id => member.id, :only_path => false))
end
end



end
「http://」から始まるフルなURLにするために「:only_path => false」を付けている。

状況によってはキャッシュさせた方が良いだろう。

検索エンジンへの通知はrobots.txt等で。(Google Webマスターツールとか使った方が安心感があるけど。)

robots.txt
# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
#
# To ban all spiders from the entire site uncomment the next two lines:
# User-Agent: *
# Disallow: /

Sitemap: http://www.example.com/sitemap.xml


参考:
「はじめてのRuby on Rails2」著者サポートページ
Rails2.0でGoogleサイトマップとかのsitemap.xml作る - ひげろぐ
sitemaps.org - プロトコル

CSSフレームワーク YAMLと Highslide JSは相性が悪い

CSSフレームワークのYAMLとページ内ポップアップライブラリのHighslide JSを併用したら、IEで見た場合のみHighslideの表示がおかしくなった。

参考情報を探したが、ドイツ語しか見つからない...


結局解決していない?


具体的には、2カラムの右側(div#col3)にあるリンクをクリックしたらHighslideがポップアップするようにしたら、IEの場合だけ"Loading"の表示が画面の右の方にずれてしまう
場合によっては画面の外にまでずれてしまい、その時だけ横スクロールバーが出るような状況に。

Firebug Liteなどを使って調べていたら、どうやらLoadingのCSSプロパティleftの値がおかしいらしい。
Highslideは、Loadingの位置を計算で求めている。
その際に、offsetLeftを積み上げてleftを計算する。積み上げるというのはリンクからoffsetParentをたどっていき、そのoffsetLeftの合計を求める。(scrollLeftの考慮もしている。)
で、このoffset系のプロパティは、ブラウザによって挙動が違うらしい。

実際にlinkのleftの計算に使われるoffsetParentとoffsetLeftを表示させてみると、Firefox(3.5)とIE(7)ではかなり内容が違う。
まずFirefoxの方はたどるoffsetParentが少ない。すぐにBodyにたどりつく。offsetに関連しない要素は無視するようだ。
対してIEはoffsetに関連しない要素も全部拾う。何が関連するかの判断もFirefoxとはかなり違う。
さらに、IEではdiv#col3の子要素のoffsetLeftの値がおかしい
具体的には、div#col3の子要素は、正しいoffsetLeftの値に加えて、なぜかdiv#col3のoffsetLeftの値が加算されている。
これにより、LoadingのLeftがdiv#col3のoffsetLeft分だけ右にずれてしまうようだ。

ここで、上記の参考サイトを見て、div#col3のpositionプロパティを変えたらなんとなかるかなあと思い実験。
FirefoxのFirebugで調べたところ、div#col3はpositionを指定していないので、デフォルトのstaticのはず。
が、IEでFirebug Liteで調べたところ、なぜかrelativeになっている。IE用のパッチのCSSの影響?
そこで、div#col3のpositionにstaticを指定したら、Loadingがリンクと同じ位置に表示されるようになった。
(たぶん)position:staticの場合、offsetParentの対象でなくなるようだ。これにより、div#col3のoffsetLeftが重複して加算されることを回避できた。

2009年11月3日火曜日

Google Analyticsの携帯からのアクセス解析で出来ることと出来ないこと

下記はGoogle Analyticsの携帯向け(公式Beta版)による統計を元にしているが、説明については推測で補完している部分もあるので注意。


主な解析出来ること

  • アクセス元(携帯の基地局?)の地図上へのマッピング表示
  • サイト滞在時間
  • 携帯キャリア
    • 「ユーザー→PC環境→ブラウザ」で。ただしauは「UP.Browser」、SoftBankは主に「NetFront」になる
    • あるいは、「ユーザー→PC環境→OS」で。この場合、SoftBankは「(not set)」になるようだ
    • あるいは、「ユーザー→ネットワーク環境→利用ネットワーク」から見る?
  • 参照サイト(ただし、ほとんどのdocomoはリファラを吐かないので対象外)
  • 検索エンジン(同上)
  • 検索キーワード(同上)
  • アクセス数順のURL

主な解析出来ないこと
  • ユーザーの言語
  • 画面の色
  • 画面の解像度
  • Flash Playerのバージョン
  • ページのタイトル(Google Botを使って取得してくれればいいのに)


ほとんどのdocomoがリファラを吐かないので参照サイトや検索キーワードが取れないのは他の解析サービスと同じ。

画面の解像度やFlash Playerのバージョン等が取れないのが、日本の携帯事情を隅々まで飲み込んでいる「うごくひと2」などと違うところか。

2009年10月28日水曜日

Google Analyticsで携帯からのアクセスを解析する方法 (公式Beta版)

以下はサーバ側でPHPを使っている場合。それ以外(ASP.NET、Java/JSP、Perl)は試してないが、おそらく同様だと思う。

  1. 下記サイトの、「download snippet instructions」のリンクからZIPをダウンロードする
    Google Analytics Blog: Google Analytics Now More Powerful, Flexible And Intelligent
  2. ZIPを解凍する。(ASP.NET、JSP、PHP、Perl用のファイルとサンプルが入っている)
  3. phpディレクトリにある「ga.php」を、Webサーバの公開ディレクトリに置く。ファイル名をを変えてもOK。(例:/var/www/html/test/mobile.ga.php)
  4. 同じくphpディレクトリにある「sample.php」から、$GA_ACCOUNT、$GA_PIXEL、関数「googleAnalyticsGetImageUrl()」とimg要素の部分をコピーして自分のPHPに埋め込む。
    (サンプルではPHPのショートタグ(「<?=」)を使っているので注意。)
  5. 自分のサイトに合わせて下記のように変数$GA_ACCOUNTとGA_PIXELの値をセットする。
    (ZIP内のサンプルではこれらの変数をfunctionの外で定義してglobalで読み込んでるけど、素直にfunctionの中に移した方が無難だと思う。)
    • $GA_ACCOUNT:自分のGoogle Analyticsのプロファイルの値を入れる。その際に、先頭のアルファベットをUAでなくMOのままにするので注意。
    • $GA_PIXEL:上記の手順3でga.phpファイルを置いたURLを指定する。(例:/test/mobile_ga.php)



しばらくデータを集めてみよう。うごくひと2やmyRTとも比べてみたい。


参考:公式Blogでコード配布、Google Analytics 携帯対応 | カグア!Google Analytics 活用塾:事例や使い方(実際のアクセス解析結果が掲載されている)

2009年9月24日木曜日

PHPの mbstringの設定の意味についてのメモ

こんな感じ?
PHP5.3の場合だが、5.2でもそんなに違いはないと思う。(mbstring.http_output_conv_mimetypeくらい?)
実際に使う場合は必要に応じて要調査。

[mbstring]
; language for internal character representation.
; http://php.net/mbstring.language
mbstring.language = [(2010/04/26訂正)Japaneseだとmb_send_mail()でメールの文字コードがjisになる。また、文字コード検出順で"auto"を使う場合にもこの設定が必要]

; internal/script encoding.
; Some encoding cannot work as internal encoding.
; (e.g. SJIS, BIG5, ISO-2022-*)
; http://php.net/mbstring.internal-encoding
mbstring.internal_encoding = [mbstring系関数で使われるデフォルトの文字コード]

; http input encoding.
; http://php.net/mbstring.http-input
mbstring.http_input = [入力データを自動で文字コード変換する場合の変換元の文字コード]

; http output encoding. mb_output_handler must be
; registered as output buffer to function
; http://php.net/mbstring.http-output
mbstring.http_output = [ob_start('mb_output_handler')した場合の変換先の文字コード]

; enable automatic encoding translation according to
; mbstring.internal_encoding setting. Input chars are
; converted to internal encoding by setting this to On.
; Note: Do _not_ use automatic encoding translation for
;       portable libs/applications.
; http://php.net/mbstring.encoding-translation
mbstring.encoding_translation = [入力データを自動で文字コード変換するかどうか]

; automatic encoding detection order.
; auto means
; http://php.net/mbstring.detect-order
mbstring.detect_order = [(2010/04/26訂正)変換元文字コードをautoにした場合 一部の関数での文字コード検出の優先順位]

; substitute_character used when character cannot be converted
; one from another
; http://php.net/mbstring.substitute-character
mbstring.substitute_character = [文字コード変換できなかった文字の代替文字]

; overload(replace) single byte functions by mbstring functions.
; mail(), ereg(), etc are overloaded by mb_send_mail(), mb_ereg(),
; etc. Possible values are 0,1,2,4 or combination of them.
; For example, 7 for overload everything.
; 0: No overload
; 1: Overload mail() function
; 2: Overload str*() functions
; 4: Overload ereg*() functions
; http://php.net/mbstring.func-overload
mbstring.func_overload = [非mbstring系の関数のうちどれをmbstring系の関数で上書きするか]

; enable strict encoding detection.
mbstring.strict_detection = [文字コード変換時に厳密なチェックを行うかどうか]

; This directive specifies the regex pattern of content types for which mb_output_handler()
; is activated.
; Default: mbstring.http_output_conv_mimetype=^(text/|application/xhtml\+xml)
mbstring.http_output_conv_mimetype = [mb_output_handler()関数が呼び出された場合に使うContent-Typeの正規表現パターンらしい]

; Allows to set script encoding. Only affects if PHP is compiled with --enable-zend-multibyte
; Default: ""
;mbstring.script_encoding = [普通は使わない]

参考:
 PHPの文字化けを本気で解決する - ぎじゅっやさん
 セキュリティ専門家でも間違える!文字エンコーディング問題は難しいのか?
 PHP: 実行時設定 - Manual
 PHP: INIファイル の扱いに関する変更 - Manual

PNGの画像を IE6で透過にするライブラリ調査メモ

IE6では透過PNGが透過しない。それを無理やり透過させてしまうJavaScriptライブラリを調べたメモ。





DD_belatedPNGが一番良さそうかな?


参考:
ITキヲスク | IE6で透過pngを表示させるオススメscript、「DD_belatedPNG.js」

Rails ActiveRecord::Validationsのエラーメッセージを多国語対応するメモ

RailsでActiveRecordのValidationによって生成されるエラーメッセージを翻訳するためのメモ。


方法その1:I18nを使う

所定のYAMLに翻訳部分を記述しておく方法。現在はこれが一番スマートなようだ。
(フィールド名とその後のメッセージの間に半角スペースが入ってしまう?)

参考:
 Rails 2.2.2でエラーメッセージを日本語化する。|WEBデザイン Tips
 Rails 2.2 の ActiveRecord::Validations#add のソースコードを読む - Ruby on Rails 研究 - Ruby on Rails with OIAX



方法その2:GetTextを使う

ActiveRecord::Errorsのdefault_error_messagesをゴリゴリ書き換える方法。
例えば、基本となるModelを作ってその中でメッセージをセットし、他のモデルはそれを継承する方法でもよいと思う。

class BaseModel < ActiveRecord::Base
 ActiveRecord::Errors.default_error_messages[:invalid] = _("がおかしいよ!")
 ActiveRecord::Errors.default_error_messages[:empty] = _("を入力してね!")
 ・
 ・
end
ただし最新のRailsではDeprecation::warnの対象

個々のエラー内容の前に出てくる文(デフォルトでは「<n> errors prohibited this object from being saved」と「There were problems with the following fields:」)は、Module: ActionView::Helpers::ActiveRecordHelperにあるとおり、:header_messageと:messageを指定することにより変えられる。
(2009/10/14追記:Ruby on RailsでRuby-GetText-Packageを使う (Rails-2.3.2以降) - よたらぼ 保管庫に書いてある、「エラーメッセージのタイトル部分をカスタマイズ」のやり方なら、個々のformごとに:header_messageと:messageを指定しなくてすむようだ。)


参考:
 エラーメッセージからフィールド名を取り除く
 ActiveRecord::Errorsあたりのローカライズ - ハードコアシステム開発
 validationのエラーメッセージ(error_messages_for)の日本語化 - Slow Dance
(2009/10/14追加:最新のRails/GetTextについての説明になっていた)
 Ruby on RailsでRuby-GetText-Packageを使う (Rails-2.3.2以降) - よたらぼ 保管庫

Railsで Viewの partialにデータを渡す方法

RailsのViewで部分テンプレートであるpartialを呼び出す場合、呼び出し時に :object または :collection と :locals を渡すことができる。

<%= render :partial => "msg", :object => "データ", :locals => {:name => "他のデータ"} %>

:collection の場合は複数のデータのそれぞれに対して1回ずつpartialが実行される。
<%= render :partial => "msg", :collection => ["データ1", "データ2"] %>

partial側では :object と :collection で渡されたデータは、partialの名前と同じ名前の変数に入っている。
#_msg.html.erb
<%= msg %> <= ここにデータが入っている
<%= name %> <= :localsで渡したデータは指定した名前の変数に入っている。


参考:
UK STUDIO - Railsのpartialの使い方
Ruby On Rails ピチカート街道 - partial パーシャルな関係【partial と object】 -
render :partialカウンター、オブジェクト - ザリガニが見ていた...。

Highslide JSでimage mapのリンクを扱う場合の注意点

Highslide JSは普通のリンクだけでなく、Image Mapのリンクでもページ内ポップアップができる。

しかし、IEで表示した場合、Image Mapのリンクをクリックすると下記の現象が起きる場合がある。

  • リンク(Image Map)の場所に関わらず、「Loading」の表示がページの左上に表示される
  • ポップアップ表示も、ページの左上を基点として拡大・縮小する

Image Mapがページを下にスクロールした位置にある場合、Loadingの表示が無いように見える。


解決策はここに書いてあった。
Highslide JS • View topic - Headline HTML problems with IE while fine in Firefox
Try using highslide-full.js instead of highslide-with-html.js.

highslide-full.jsを使えとのこと。
やってみたら、見事に解決した。


下手にHighslide Configuratorを使わずに、FULLを使った方が無難かも。

2009年8月28日金曜日

Firefoxの起動や終了が遅い問題を解決するアドオンいろいろ

Firefoxの起動や終了にやたらと時間がかかる原因の1つは、Firefoxの内部データを保存しているDBの1つであるplaces.sqliteが肥大化することらしい。
Firefoxの終了が遅くなると、終了してから起動しようとすると「Firefoxは起動しています」とか言われて起動できないこともよくある。

で、そのplaces.sqliteをVACUUMするアドオンが相次いでリリースされている。


Vacuum Places :: Firefox Add-ons

  • ステータスバーのアイコンをクリックするとVACUUM
  • 設定画面(ロシア語!)はあるが、実際には使えない(設定しても意味無い) バージョン0.2からは使えるようになったらしい


Vacuum Places Improved :: Firefox Add-ons
  • 上記のVacuum Palcesの改良版
  • 設定画面が英語になり、かつ、実際に使えるようになっている
  • 設定すれば、一定のFirefox起動回数ごとに自動でVACUUMしたりできる


ふと今日は・・・・・・  Vacuum Places 日本語化
  • 上記2つの日本語化版


PlacesCleaner :: Firefox Add-ons
  • アクセス回数が少ないページを履歴から削除することにより、さらにplaces.sqliteをダイエットできるそうだ


SQLite Optimizer :: Firefox Add-ons



個人的には以前から使っているSQLite Optimizerが気に入っている。
VACUUM&Reindexしたら、確かに再起動が早くなった。
ていうか、これはFirefox本体でやるべきことだと思う。


ちなみに、上記のアドオンをいくつか試していたら、DeliciousアドオンのSQLiteのデータがおかしくなった。(ReSyncですぐに直ったけど。)どれが悪さしたんだろう?



参考:
 Places を VACUUM する拡張機能3個 - えむもじら
 Firefoxを起動したままplaces.sqliteをVACUUMできる: べつになんでもないこと
 Mozilla Re-Mix: Firefoxの[places.sqlite]をワンクリックで最適化できるアドオン「Vacuum Places」

Railsでタグクラウド

いくつかプラグインがあるが、acts_as_taggable_on_steroidsが一番人気のようだ。

acts_as_taggable_on_steroidsの使い方は、acts_as_taggable_on_steroidsの使い方まとめ - ひげろぐが参考になる。

acts_as_taggable_on_steroidsのインストール元については、Railsのtagプラグイン「acts_as_taggable_on_steroids」がgithubに行ってた - 常識という迷信にあるとおり、現在はgithubにあるのが最新のようだ。



上記の参考サイトではacts_as_taggable_on_steroidsの機能をフルに使っているが、タグクラウドを表示したいだけなら下記だけでOK。

  1. acts_as_taggable_on_steroidsをインストール
  2. タグのモデルを用意する(既存のモデルでもcountと表示用の文字列(下記の例ではlabel)さえあればOK)
    # tag_sample.rb
    class TagSample
     attr_accessor :count, :label
    end
  3. 上記のモデルにデータをセットした配列を用意
    # FooController.rb
    # 実際にはDBから取得したデータとかをループで処理するだろうけど
    tag1 = TagSample.new

    tag1.count = 10

    tag1.label = "ラベル1"
    tag2 = TagSample.new

    tag2.count = 20

    tag2.label = "ラベル2"
    @tags = [tag1, tag2]

  4. ヘルパーでTagsHelperをインクルードする
    # foo_helper.rb
    module FooHelper
    include TagsHelper
    end
  5. ビューでタグクラウドを表示(第2引数のCSSクラスの数は増減OK)
    <!-- foo/bar.html.erb -->
    <% tag_cloud(@tags, ["tag-s", "tag-m", "tag-l"]) do |tag, css| %>
     <%= link_to(h(tag.label), {:action=> :tags, :id => tag.label}, :class => css) %>
    <% end %>
  6. CSSで見た目を調整
    a.tag-s { font-size: 80%; }
    a.tag-l { font-size: 150%; }

Railsで View内で head要素にCSS等を追加する方法

Railsで特定のページだけにCSSファイルを追加する方法を見て知った。これは便利。


application.html.erb等で、 yieldにパラメータを指定すればOK。

<html>
<head>
<title>テスト</title>

<%= yield :head %>

</head>
<body>

<%= yield %>

<%= yield :foot %>

</body>
</html>

Viewの方ではcontent_forに同じパラメータを指定してブロック内に書く。
<h1>head and foot</h1>

<% content_for :head do %>
 <%= stylesheet_link_tag "foo" %>
<% end %>

<% content_for :foot do %>
 <%= javascript_include_tag "bar" %>
<% end %>

こんな感じのHTMLになる。
<html>
<head>
<title>テスト</title>

<link href="/stylesheets/foo.css?1345990170" media="screen" rel="stylesheet" type="text/css" />

</head>
<body>

<h1>head and foot</h1>

<script src="/javascripts/bar.js?1350833305" type="text/javascript"></script>

</body>
</html>


これを使えばCSSはhead内に、JavaScriptはbody要素の最後に入れられる。

Railsの日付選択ヘルパー (select_date)

Rails2.3で日付選択ヘルパー(select_date)を使うためのメモ。

オプションとして指定できるものはこんな感じのようだ。

<%
options = {
 :prefix => 'payday', # field名のprefix
 :order => [:month, :year, :day], # 表示順
 :date_separator => '/', # 項目間の区切り
 :prompt => true, # 選択リストの一番上の表示について。個別の指定も可
 :include_blank => true, # 選択リストの一番上のブランクにする
 :use_month_numbers => true, # 月を数字で表す

 # 選択可能な年の範囲を指定
 :start_year => Date.today.year,
 :end_year => Date.today.year + 1,

 # 非表示にする
 :discard_year => true,
 :discard_month => true,

 :discard_day => true
}
html_options = {} # ?
%>
<%= select_date(Date.today + 2.days, options, html_options) %>


また、Rails2.2にはバグがあるらしい → エラー回避 date_select -- can't convert Symbol into String - 税理士業界でSaaS開発をしながら綴る日記


select_dateとdate_selectは似てるけど別モノらしい。
年月日を個々に作る場合、「select_year, select_month, select_day」が使えるが、「year_select, month_select, day_select」は無い。



参考:
 Module: ActionView::Helpers::DateHelper (本家リファレンス)
 変なヤバいもんログ » Railsで忘れそうなHelperメソッドメモ

 いきなりはまった。select_date - 印刷屋のdeveloper日記

Railsプラグイン ActiveForm調査メモ

AtcitveFormはテーブルに紐付かないモデルを使って入力フォームを作るためのプラグイン。
データの入れ物とvalidationを担う。

「ActiveForm」という名前のプラグインは複数あるので注意。
Gemでインストールすると、module版のActiveFormがインストールされるが、よく分からなかったのでパス。

どうやら「RealityForge」で公開されたActiveFormが主流のようだ。


最新版?:
 maciej's active_form at master - GitHub


使い方:
 RailsのActiveFormの使い方 - 京の路
 Ruby on Rails プラグイン まとめ wiki - active_formプラグイン
 るびすけの開発日記 ~Ruby on Rails~ - IT業界のための転職サイト -



Rails2.2以降ではエラーが発生する。

undefined method `self_and_descendants_from_active_record' for Xxx:Class

rails2.2でactive_formを導入するときにはまった - オレワカ。を参考に、「self_and_descendants_from_active_record」を追加すると解消した。
svnから持ってくるバージョンでは 「self_and_descendents_from_active_record」 すらも無いので注意。


使用例
#コントローラ
class SearchController < ApplicationController
 def index
  @search = Search.new(params[:search])
  if params[:search]
   @search.valid?
  end
 end
end
#モデル
require 'active_form'

class Search < ActiveForm
 attr_accessor :tag
 validates_presence_of :tag
 validates_length_of :tag, :maximum => 3
 def validate
  # カスタム入力チェックはここで
 end
end
<!-- ビュー -->
<% form_for(:search, @search) do |f| %>
<%= error_messages_for :search, "tag" %>
<%= f.text_field "tag" %>
<% end %>

HTMLの lang属性は大文字?小文字?

日本の場合はlocaleは"ja"とシンプルなので分かりやすいが、例えばイギリスだと"en-GB"か"en_GB"か"en-gb"か"en_gb"か?

Yahooイギリス版を見てみると、"en-GB"になっていた。(Yahoo! UK & Ireland
でも台湾版だと"zh-tw"と小文字になっている。(Yahoo!奇摩

とりあえずアンダーバー(アンダースコア)でなくハイフンというのは分かったが、大文字小文字の使い分け方は分からない。
文字コード指定の場合と同様にどっちでも良さそうな気がするけど、結局はブラウザ等の挙動に依存する。
各国・各地域のYahoo等のメジャーなサイトに合わせておくのが無難だと思う。

prototype.jsと script.aculo.usを使って一定時間で画像を入れ替えるサンプル

JavaScriptで画像を定期的に入れ替え。かつエフェクト効果を付けたい。
コマンド一発で済みそうなのを軽く探してみたけど、要件を満たすライブラリが見つからなかった。で、自分で書いたらこうなった。
諸事情によりprototype.js系にした。

需要はありそうだと思ったけど、そうでもないのかな?

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.0.3/prototype.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/scriptaculous/1.8.2/scriptaculous.js"></script>

<script type="text/javascript">
var urls = ["foo.jpg", "bar.gif"]
var i = 0;

Event.observe(window, "load", function() {
 var img = $("img");

 setInterval(function() {
  img.visualEffect("Fade", {duration: 1});
  setTimeout(function() {
   img.src = urls[i];
   i++;
   if (i == urls.length) {
    i = 0;
   }
   img.visualEffect("Appear", {duration: 1});
  }, 1500);
 }, 4000);
}, true);
</script>

参考:
 script.aculo.us リファレンス
 prototype.js リファレンス
 Developer's Guide - Google AJAX Libraries API - Google Code

2009年8月12日水曜日

Railsの GetText 2.0でサーバが起動しないエラーの対応メモ

レアなケースだろうけど一応メモ。


(参考:RailsでGetText)
Rails のためのものぐさな Web アプリケーションの国際化手法 - 川o・-・)<2nd lifeが参考になる。
ただしGetText 2.0からはenvironment.rbで読み込むgemが変わったので注意。

config.gem "locale_rails"
config.gem "gettext_activerecord"
config.gem "gettext_rails"



ActiveRecordもActionMailerも使わないので、config/environment.rbで不使用にしていた。
config.frameworks -= [ :active_record, :action_mailer ]

gettext(2.0)を使うために、下記をgemでインストール。
locale
locale_rails
gettext
gettext_rails
ActiveRecordは使わないのでgettext_activerecordは入れなかった。

アプリケーションにgettextを使う設定を入れて、mongrelを起動しようとしたがエラーになって起動できない。
ruby server/script

.../lib/active_support/core_ext/module/aliasing.rb:33:in `alias_method': undefined method `create!' for class `ActionMailer::Base' (NameError)

ActionMailer?使ってないけど?
しょうがないから不使用指定を外す。
config.frameworks -= [ :active_record, :action_mailer ]

config.frameworks -= [ :active_record ]

これでも駄目。
試しにgettext_activerecordをインストール。
これで起動したら起動できた。

もう1つ試しにgettext_activerecordのrequireをコメントアウトしたら起動しなかった。


結論:RailsでGetTextを使う場合、不要でもActionMailerを外しては駄目。かつ、不使用でもgettext_activerecordが必要。

ActiveResourceを使っている Controllerを RSpecでテストする例

参照系しか試してない。


下記の例では、MemberというActiveResourceをリスト表示したり詳細表示したりするControllerについて、RSpecでテストする。
(参考:ActiveResource の使い方(前編) : Rails 同士で通信する - WebOS Goodies ※「ユニットテスト」の項。RSpecではないけど。)

require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
require 'active_resource/http_mock'

describe MembersController do

 before do
  @member = {:id => 1, :name => 'foo'}

  @members = [@member]

  @header = Member.connection.__send__(:build_request_headers, {}, :get)

  ActiveResource::HttpMock.respond_to do |mock|
   mock.get '/members.xml', @header, @members.to_xml(:root => 'members')
   mock.get '/members/1.xml', @header, @member.to_xml(:root => 'member')
  end
 end

#後は普通にケースを書く
 #(略)

end

要するに、http_mockをrequireしておき、before()でモックが返すXMLを定義している。


ActiveResourceで取得する際にパラメータ付きのURLを使う場合、「mock.get」のところにもパラメータを付けなければいけないので注意。
例:
mock.get '/members.xml?q=keyword', @header, @members.to_xml(:root => 'members')



...と、ここまで書いてから、mockを使ってテストできることを知った。
 before do
  @member = mock_model(Member)
  Member.should_receive(:find).with(:all).and_return(@member)
  get 'index'
 end
ActiveResourceでもActiveRecordでもModelであることには違いがないから、ただMockを使えば良いだけだった。

HttpMockはむしろ、ActiveResource::Baseを継承したModelのテストのために使うのか。

RSpecの規約を覚えるためのリンク集とメモ

RSpecはDSLなので、決め事を覚えないと使いこなせない。
よく使うことになるであろう、参考リンクを列挙しておく。


前処理、後処理



aeertion(expectation)


change matcher


Controllerのテスト


Viewのテスト


Mock(mock_model)



参考:
 RSpec をもっと理解したかったので、まとめを作りました - takihiroの日記
 RSpec.info: Writing
 Index of /rspec (公式?仕様書)

RSpec on Railsのセットアップ

やったことのメモ。


インストール

gemでRSpecをインストール(もしかして不要?)

gem install rspec

RSpec-Railsもインストール(「ruby script/plugin install http://...」でインストールした方がいい?)
gem install rspec-rails
(rspec_railsだと見つからない)


generateする(とりあえずMemberモデルを対象に。)
ruby script/generate rspec
ruby script/generate rspec_model Member


なにはともあれ実行してみる
ruby script/spec spec/models/member_spec.rb
または
rake spec:models
などなど。(参考:RSpec on Rails でインストールされる rake タスク



ActiveRecordを使わない場合

そのままでは下記のようなエラーになる。
.../spec/spec_helper.rb:16: undefined method `use_transactional_fixtures=' for #<Spec::Runner::Configuration:0x1234567> (NoMethodError)
上記のソース(spec/spec_helper.rb)にはこう書いてある。
# If you're not using ActiveRecord you should remove these
# lines, delete config/database.yml and disable :active_record
# in your config/boot.rb
config.use_transactional_fixtures = true
config.use_instantiated_fixtures = false
config.fixture_path = RAILS_ROOT + '/spec/fixtures/'
書いてあるとおり、この3行を削除したら無事動いた。



参考:
 Rubyist Magazine - スはスペックのス 【第 1 回】 RSpec の概要と、RSpec on Rails (モデル編)
 Rubyist Magazine - スはスペックのス 【第 2 回】 RSpec on Rails (コントローラとビュー編) (続きは...?)
 RSpec on Railsを試してみた。 - ひげろぐ

Rubyの ActiveResource調査メモ





基本:

 ActiveResourceでいろんなAPIを叩いてみる。標的はHotpepper API - 富士山は世界遺産


発行されるURLと拡張子について:
 天使やカイザーと呼ばれて: ActiveResourceで拡張子なしのURIを発行する方法


応用編:
 ActiveResource の使い方(前編) : Rails 同士で通信する - WebOS Goodies
 ActiveResource の使い方(中編) : メソッドの詳細 - WebOS Goodies
 (後編は? 2009/09/17追記:公開された↓)
 ActiveResource の使い方(後編) : 一般の Web API にアクセスする - WebOS Goodies


ActiveResourceのバグ?
 [PATCH] ActiveResource find(:all) method returns "NoMethodError: undefined method `collect!'... - lambda {|diary| lambda { diary.succ! } }.call(hatena)
取得するXMLがn件のデータを包含する要素を持つ形の場合、包含する要素に属性type="array"が無いと「collect!メソッドが無いよ!」というエラーが発生する問題。

たとえばこれだとエラーになる。(n件のmemberを、membersという要素で包含している。)

<?xml version="1.0" encoding="UTF-8"?>
<menbers>
 <member>
  <id>1</id>
  <id>name</id>
 </member>

</menbers>

type="array"を付ければエラーにならない。
<?xml version="1.0" encoding="UTF-8"?>
<menbers type="array">
 <member>

  <id>1</id>
  <id>name</id>
 </member>

</menbers>


Rubyの ActiveRecordについてのメモ

しばらく離れていたらすっかり忘れてる。
調査したことのメモ。
微妙に仕様変わってる。


基礎:ActiveRecordを使ってみる « UK STUDIO


検索して見つからない場合の戻り値:ActiveRecord find時の戻り - 忘れやすいのでメモ - Yahoo!ブログ
(検索方法によってnilだったり空の配列だったり、例外が投げられたり)


find_first()とfind_all()は無くなった:同じくActiveRecord find時の戻り - 忘れやすいのでメモ - Yahoo!ブログ


最大値等のSQLでいう集約関数:RDBMSの集約関数の結果をActiveRecordで取得する方法 - 森薫の日記


ランダムに1件取り出す:
 そんな悲しい目をしないで » Blog Archive » Rails ActiveRecord でランダムにレコードを取得する方法
 Mysql で、ランダムにレコードを取り出す方法 - kaeruspoon
(RAND()を使う方法は行数と同じだけRNAD()を実行するわけだから、行数が多い場合はしんどそう)


find_by_xxx()とfind_all_by_xxxについて:ActiveRecordで検索-find_by_* - うなの日記

Railsの migration

メモ。


概要:Ruby on Rails : migration 機能でデータベーススキーマを変更する - WebOS Goodies

詳細:Ruby on Rails : migration 機能リファレンス - WebOS Goodies

データ型について等:FFTT : RailsのMigration

MySQLの数値型の:limitについて、上記参考サイトでは桁数を指定するように書いてあるが、手元のRails2.3.3ではバイト数を指定するようだ。
なのでbigintの場合は :limit => 8 にする。


参考:MySQL :: MySQL 5.1 リファレンスマニュアル :: 10.2 数値タイプ

Windows + Ruby 1.8.7 + Rails 2.3.3 + MySQL 5.4.1 環境構築メモ

備忘録として。


前提として、以前Railsを試したことがあるので、下記は事前にインストール済みだった。

  • Ruby 1.8.6(One-Click Installer版)
  • Ruby Gems
  • MySQL 5.4.1(Beta)


やったことの手順
  1. Gemsでインストール済みのgemを全てupdate。Railsが2.3.3になった
  2. Release - Ruby-mswin32 (ja)からWindows用の1.8.7のZIPをダウンロードし解凍、既存のRuby(1.8.6)のフォルダに上書きコピー
    (1.8.6のままではエラーが起きる)
  3. このままではdb:migrateする時に下記のエラーが出る。(MySQLの5.1以降に対応していないらしい)
    rake aborted!
    Mysql::Error: Commands out of sync; you can't run this command now: SHOW TABLES
    そこで、PHP5.2のフォルダからlibmysql.dllをコピーしてきてRubyのbinフォルダに入れると解消した
    (参考:Aptana Forums • View topic - Fixed: Commands out of sync

On2の動画コーデックいろいろ

On2 VP3

  • オープンソース化され、それを元にTheora(oggに採用されている。oggは今のところHTML5の動画フォーマットの最有力候補)が作られた。
  • 参考:On2VP3 - WikipediaTheora - Wikipedia

On2 VP6
  • Flash 8のFlash Video(通称FLV4)の動画コーデックとして採用されたことにより、Web上で多く使われている。(FLVの最新はH.264を採用したFLV5)
  • 参考:On2 VP6 - Wikipedia

On2 VP7

On2 VP8


VP1、2、4、5は花開かなかったようだ。VP8はどうなる?

rating(星5つとか)に実効性を与えるにはどうするかを考えてみる

星の数1~5個(または0~5個)で評価すること(以下レーティングと言う)は、たいていの場合うまく機能していない。

うまく機能しない原因

  • レートを付ける人の数が少ないので、レートが偏る
  • 極端なレート(1 or 5)を付けられる傾向が強くなることが多いので、平均点自体にあまり意味が無い
  • 未評価の場合、星1つよりも下という扱いのことがある


以上を踏まえて、こういうのがいいんじゃないだろうか
  • レートを付ける人ごとに、レートの絶対値の平均点を計算し、それを使って付けられるレートに重みを付ける
  • 最大5までとか制限せずに、10まで、100まで、あるいは無制限といった大きい数にする
  • レートはプラスだけでなく、マイナス評価もできるようにする
  • 未評価は「未評価」という別枠として扱う

例えば、A・B・Cというものにマイナス100からプラス100の間でレートを付けるとして、FooさんとBarさんが下記のようにレートを付けたとする。
 Foo → A:+100、B:+100、C:-100
 Bar → A:+70、B:+50、C:+30

するとFooさんの絶対値の平均は約100、Barさんの平均は50になる。
この平均でそれぞれのレートを割るって100をかけると
 Foo → A:+100、B:+100、C:-100
 Bar → A:+140、B:+100、C:+60

それなりに絶妙な評価を与えてるような気がしなくもない。
極端に走りがちなFooさんより、渋い点を付けるBarさんの方が高い点を与える力を持っている、ように見えるけど。どうなんだろう?
偏差とか使った方がいいのかな?

ログインしなくてもレーティングできるなら、非ログイン者は全て「ゲスト」扱いにして、「ゲスト」の平均で重み付けすれば落ち着くところに落ち着くだろう。


参考:
 学術論文における"rating"ってなんだ? - かたつむりは電子図書館の夢をみるか
 五つ星の評価は無意味だ « maclalala2

PHPで Google Maps APIのジオコーディングを使う例

Google Maps APIは基本的にJavaScriptから呼び出すが、ジオコーディング(住所等から緯度経度を求めること)についてはJavaScript以外からでもRESTに取得できる。

PHPで呼び出す場合の例。
APIキーはJavaScriptの場合と違ってドメインごとに取得する必要は無いようだ。(どこかのドメイン用に取得したキーを使える。)

<?php
$apiKey = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

$place = '京都';

$url = 'http://maps.google.com/maps/geo?';
$params = array(
 'q' => $place,
 'key' => $apiKey,
 'sensor' => 'false',
 'output' => 'json',
);
$results = json_decode(file_get_contents($url . http_build_query($params)));

echo '<pre>';
var_dump($results);
var_dump($http_response_header);
echo '</pre>';


参考:サービス - Google Maps API - Google Code

2009年7月28日火曜日

OAuth調査メモ

OAuthの仕様を理解するための調査のメモなど。


Twitterでの RTの書き方いろいろ

Twitterで他人のつぶやき(Tweet)を再POST(ReTweet)する「RT」。人によって書き方がいろいろ。


基本形


一番多数派のかたち(何かのツールによるもの?)
 RT @xxx: XXXXXX

@リプライの後ににコロンを付けない
 RT @xxx XXXXXX

RTにコロンを付ける
 RT: @xxx XXXXXX

両方コロンを付ける
 RT: @xxx: XXXXXX

コロンの後にスペースを入れない
 RT @xxx:XXXXXX

コロンの前にもスペースを入れる(以前@geekpageさんがやってた)
 RT : @xxx: XXXXXX

小文字で書く
 rt @xxx XXXXXX

@リプライを入れない
 RT XXXXXX


応用編

RTにコメントを付ける
 YYYYYY RT @xxx XXXXXX

コメントを後ろに付ける(海外のユーザーに多い気がする)
 RT @xxx XXXXXX << YYYYYY

RTをさらにRTする際に、RTした人にも@リプライする
 RT @yyy RT @xxx XXXXXX

RTをさらにRTする際に、RTした人は後ろに書く
 RT @xxx XXXXXX (via @yyy)


コメントはRTの後とか@リプライの後とかに入れる人もいる。


参考:RT - Twitter Search

PHPで Twitterの Search APIを使って検索する例

例えばこんな感じ。

<?php
$url = 'http://search.twitter.com/search.json';
$params = http_build_query(array('q' => 'なう', 'lang' => 'ja', 'rpp' => 3));
$results = json_decode(file_get_contents("$url?$params"));

echo '<pre>';
var_dump($results);
var_dump($http_response_header);
echo '</pre>';


PythonやRubyと比べると、PHPは標準関数でいろいろなことができるなーと実感する。


参考:Twitter API Wiki / Twitter Search API Method: search

PHPの URLエンコード (urlencode, rawurlencode, http_build_query)

(2013/5/19 変更:rawurlencode()はRFC3986なのにRFC1738と書いてたので訂正。)


まずはurlencode()rawurlencode()を比較。

  • urlencode()
    • 半角チルダ(~)を%7Eに変換する
    • 半角スペースをプラス(+)に変換する
  • rawurlencode()
    • 半角チルダ(~)の変換についてはPHPのバージョンによって違う
      • PHP 5.2.xまでは、%7Eに変換する
      • PHP 5.3.0からは、%7Eに変換しない(チルダのまま)
    • 半角スペースを%20に変換する

rawurlencode()はRFC1738 RFC3986に沿った変換とされているので、基本的にはurlencode()よりrawurlencode()の方が無難。
ただし、RFC1738 3986ではチルダを%7Eに変換しない。


ちなみに、RFC1738はその後、RFC3986によって更新されているが、RFC3986はパッと見た感じではURLエンコードについては(JavaScriptのencodeURIComponent()で使われるRFC2396の方ではなく、)RFC1738を踏襲しているようだ。(2013/5/19 追記:一部変更されてる。)

Amazonの新しいAPIでも、RFC3986によるURLエンコードを使っている。(参考:Amazon Product Advertising API への対応(PHP版) - もやし日記



次に、http_build_query()の話。
http_build_query()は便利だが、URLエンコードの内容はurlencode()と同じなのが残念。
RFC1738/3986に沿った形にするには、もう1つ変換を咬ませなければならない。
//例
function encodeAlongRFC1738($str) {
return strtr($str, array('%7E' => '~', '+' => '%20'));
}

echo encodeAlongRFC1738(http_build_query($arr));
上記の変換は、PHP5.2までのrawurlencode()にも使える。



あとは実験結果。上記のencodeAlongRFC1738()も交えて。
元の文字
 "~_ _+"

urlencode()の場合
変換結果
 "%7E_+_%2B"
urldecode()すると
 "~_ _+"
rawurldecode()すると(正しくデコードできない)
 "~_+_+"

rawurlencode()の場合(PHP 5.2)
変換結果
 "%7E_%20_%2B"
urldecode()すると
 "~_ _+"
rawurldecode()すると
 "~_ _+"

rawurlencode()の場合(PHP 5.3)
変換結果
 "~_%20_%2B"
urldecode()すると
 "~_ _+"
rawurldecode()すると
 "~_ _+"


urlencode() + encodeAlongRFC1738()の場合
変換結果
 "~_%20_%2B"
urldecode()すると
 "~_ _+"
rawurldecode()すると
 "~_ _+"


元の配列
 array("test[0]" => "~_ _+")

http_build_query()の場合
変換結果
 "test%5B0%5D=%7E_+_%2B"
urldecode()すると
 "test[0]=~_ _+"
rawurldecode()すると(正しくデコードできない)
 "test[0]=~_+_+"

http_build_query() + encodeAlongRFC1738()の場合
変換結果

 "test%5B0%5D=~_%20_%2B"
urldecode()すると
 "test[0]=~_ _+"
rawurldecode()すると
 "test[0]=~_ _+"

urldecode()はurlencode()に対してもrawurlencode()に対しても使える。



参考:URIに使ってよい文字の話 - RFC2396 と RFC3986 - Text::Easyhacking

PHPでは 0 == 'A' がtrueになる

手元のPHP5.3.0で発現。もしかしたら5.2では起こらないかも。

下記は「0 == 'A'」を評価する際にPHP内部で行われていることの推測

  1. 式を評価する時に両辺のデータの型が違う場合、暗黙の型変換が行われる。
  2. その際に、どちらかが数値だと、もう一方も数値に変換して比較しようとする。
  3. さらに、PHPでは先頭が数字の文字列を数値に変換(キャスト)すると、先頭部分の数値になる(例:"123ABC" → 123)
  4. さらにさらに、先頭が数字でない文字列を数値型に変換する場合、ゼロになる

これにより、「0 == 'A'」は右辺が数値に変換され、先頭に数字が無いのでゼロになり、「0 == 0」になり、trueになる。


同じように「'A' == 0」も「1 == '1A'」もtrueになる。

「'0' == 'A'」や「0 === 'A'」はfalseになる。

PHPを5.3にバージョンアップしたら動かなくなった場合の対処法

Windows上のPHPを5.2から5.3にバージョンアップしたら動かなくなった時にやったこと。
(自分の環境での解決策のメモ)


トラブル1:Apacheを起動する時に下記のようなエラーが出て起動できない

ローカル コンピュータ の Apache2 サービスを開始できません。
エラー 1067: プロセスを途中で強制終了しました。
原因は存在しないextensionをロードする設定になっていることだった。
自分の場合、php_pdo.dllとphp_zip.dllをコメントアウトしたらApacheを起動できるようになった。
(以前、PHP 5.3 RC2に無いエクステンションを書いたことを思い出してやったら動いた。)


トラブル2:PHPのページを呼んでも帰ってこない OR 真っ白のページが表示される
Apacheのアクセスログにもエラーログにも何も記録されていない。PHPのエラーログにも何も書かれない。
ということはPHPのエラーログにエラーを書き出す前にこけてる?そしてApacheはPHPからの処理の戻りを待ち続けてる?

原因は、タイムゾーンの設定をしていないことだった。
date.timezone = Asia/Tokyo
上記設定をしてあげたら無事動くようになった。

これは仕様か?

2009年7月21日火曜日

新たな天才の出現に立ち会えた気がする(動画)

とにかくこの動画を見てみてください。



崖の上のポニョとCoccoのMy Dear Pigを足したような。絵もまた素晴らしい。

2009年7月12日日曜日

Pythonのメソッドのパラメータの不思議

Windows上のPython2.5のPytyon Shellで確認した。

こんなclassがあったとする。

class Test(object):
 def foo(self):
  return [self.bar(), self.bar({'buz': 10})]
 def bar(self, p={'buz': 1}):
  p['buz'] += 1
  return p

下記のように、dict型の引数pに初期値が設定されているメソッドbar()を引数無しで呼ぶと、前回呼んだ時のメソッド内の変数pの値が使われるようだ。
>>> Test().foo()
[{'buz': 2}, {'buz': 11}]
>>> Test().foo()
[{'buz': 3}, {'buz': 11}]

ちょっとびっくり。引数の型がdictの場合だけでなく、配列でも同じことが起きた。


また、classじゃなくても同じ現象になった。
def test(foo={'bar': 1}):
 foo['bar'] += 1
 return foo

>>> test()
{'bar': 2}
>>> test()
{'bar': 3}
>>> test({'bar': 10})
{'bar': 11}
>>> test()
{'bar': 4}
引数を付けた時だけ別になっている。

CakePHPでユニットテスト

CakePHPでユニットテストする場合、標準ではPHPUnitではなくSimpleTestを使う。


1. ダウンロード
SimpleTestはDownloading SimpleTestからtar.gzをダウンロードできる。
(なぜかSoureceForgeの方からはtar.gzがダウンロードできなかった。どうでもいいが上記のページには"... from SourceForget.net ..."と書いてある。ソースのことなど忘れたい...とか?)


2. セットアップ
基本的にCakePHP1.2の本家のリファレンスに沿って進めればセットアップできる。


3. setUp, tearDown
SimpleTestではxUnitと同様にsetUp() tearDown()が使えて、さらにそれに加えていろいろなタイミングで呼ばれるfunctionがあるらしい。
参考:CakePHPでSimpleTest その2 TestSuiteの動きをモデルのテストケースのスケルトンで確認 | ねねとまつの小部屋

<?php
//app/tests/cases/models/member.test.phpの例
App::import('Model', 'Member');

class MemberTestCase extends CakeTestCase {

 function setUp() {
  $this->Member =& ClassRegistry::init('Member');
 }

 function testHoge() {
  $result = $this->Member->hoge('foo');
  $expected = array('baz' => 'bar');
  $this->assertIdentical($result, $expected);
 }
}


4. assert
assertEqual()は"=="で比較するので危険らしい。常にassertIdentical()を使った方が良さそうだ。


5. Caverrage
"Analyze Code Coverage"を見るにはxdebugが必要らしい。


6. Controllerのテスト
$this->testAction()が使える
<?php
class MembersControllerTest extends CakeTestCase {
 function startCase() {
  echo '<h1>テストケースを開始します</h1>';
 }
 function endCase() {
  echo '<h1>テストケースを終了します</h1>';
 }
 function startTest($method) {
  echo '<h3>メソッド「' . $method . '」を開始します</h3>';
 }
 function endTest($method) {
  echo '<hr />';
 }
 //普通に呼び出す
 function testIndex() {
  $result = $this->testAction('/');

}
 //レンダリングしたHTMLを取得する
 function testIndexGetRenderedHtml() {
  $result = $this->testAction('/', array('return' => 'render'));
  //表示して確認
  debug(htmlentities($result));
 }
 //コントローラ内でセットしたデータを取得する
 function testIndexGetViewVars() {
  $result = $this->testAction('/', array('return' => 'vars'));
  $this->assertIdentical($result['fuga'], 'honyarara');
  //表示して確認
  debug($result);
 }
}

参考:コントローラのテスト :: テスト(Testing) :: CakePHPによる作業の定石 :: マニュアル :: 1.2 Collection :: The Cookbook

Linuxで svnにパスワードを保存させない設定

Linuxでsvnを使うと、デフォルトではSubversionサーバへの接続設定がパスワードも含めて全て平文で記録される。
rootに丸見えで気持ち悪い場合もある。

これをやめさせるには、ファイル ~/.subversion/config を編集し、パスワードを保存しないようにする。

store-passwords = no
パスワードだけでなく、なるべく保存される情報を無くしたいなら、auth-credsをnoにする。
store-auth-creds = no

上記設定をしても既に保存された情報は消えないので、 ~/.subversion/auth/svn.simple/ にあるハッシュっぽい名前のファイルを消しておく。


参考:Subversion - Linux Wiki

Google Chromeに Extension(拡張)をインストールするメモ

(2010/01/17追記)
面倒な事をしなくても、現在は下記のように簡単にExtensionが使えるようになるみたいですね。

  1. Google Chrome Extensionsのサイトを表示すると、もし使用中のChromeがExtension非対応の場合はBeta版のインストールを勧められる(英語)
  2. そこからChromeのBeta版をインストールして、Chromeを再起動する

(追記終わり)


Google ChromeでExtension(拡張)を使えるようにするメモ。

  1. Chromeをdev版に切り替える。
    Chrome dev版のダウンロードページ
    からdev版をダウンロードしてインストール。
  2. Extensionを有効にする。
    Chromeのショートカットのプロパティを開き、「リンク先」の最後に「 --enable-extensions」を付ける
    参考:Google Chrome 拡張(Chrome Extension) はてなブックマークのエントリー数を表示する Chrome拡張を作った - 忘れないようにメモ

以上。

ショートカットからChromeを立ち上げ、試しにAdSweepのページでAdSweepをインストールしてみればExtensionが有効になっているか分かる。
はてなブックマークのエントリー数を表示するChrome拡張なぜかインストールできなかった。(2009/08/12変更)インストールできるようになった。コメント欄参照。)

インストールしたExtensionは、chrome://extensions/ を見れば確認できる。


ExtensionはGoogle Chrome Addons, Themes, and Pluginsあたりから入手できるが、まだまだ欲しいものはない状況。
せめてRefControlが欲しいなあ。


参考:Early Access Release Channels ‎(Chromium Developer Documentation)‎

2009年7月5日日曜日

CMANのネットワーク監視が強化されるらしい

CMANのサイトリニューアルのご案内によると、無料でサイトを監視してくれるサービスをリニューアルするらしい。
微妙なバージョンアップだが、無料で続けるそうだ。頑張って欲しい。

2009年7月4日土曜日

RSSフィードを Twitterに POSTしてくれるサービスいろいろ

RSS/ATOMフィードを取得して、それをTwitterにPOSTしてくれるサービスの比較。


twitterfeed

  • この手のサービスでは一番有名。最近リニューアルした
  • OpenIDでログインすればユーザー登録不要
  • OAuthでTwitterとやり取りするのでTwitterのパスワードを預けなくてもよい(OAuthでなくてパスワードを預けてもできるみたい)
  • フィードはRSS2.0かATOMがお勧めらしい
  • フィードのエントリーの日付(pubDate)かGUIDかのどちらで新規投稿を特定するかを選べる
  • エントリーのタイトルをPOSTするか、本文か、その両方かを選べる
  • POSTの先頭と最後にそれぞれ任意の文字列を付けられる。最大20字と書いてあるが、日本語だと6文字程度しか入れられないようだ
  • URL短縮は多くのサービスから選べる。デフォルトはBit.lyで、Bit.lyのAPI KEYを入力すればBit.lyの方でクリック数等を追跡できる
  • 「30分ごと」「1時間ごと」と設定しても、2~3時間ごとにしか処理してくれない。(利用ユーザーが多くて処理が重いから?それともTwitter側による制限?)


RSS2twitter
  • OAuthでTwitterとやり取りするのでTwitterのパスワードを預けなくてもよい
  • 機能はtwitterfeedに近い。フィルタはこっちの方が少し上。いくつかtwitterfeedにはあるがこちらには無い機能がある
  • Prefixに日本語を入れたら文字化けした
  • URL短縮は独自のもの(http://url4.eu/xxx)。なのでクリック追跡もRSS2twitter内で見られる
  • フィードを登録するとすぐにPOSTしてくれるのが良い
  • 参考:RSS2twitterはOAuthで認証してTwitterにフィードを流す - F.Ko-Jiの「一秒後は未来」


HootSuite
  • Twitterをラップしてさらに機能を付加するWebのUI。フィードからPOSTする機能も付いている
  • フィードは5つまでしか登録できない
  • POSTするのはエントリーのタイトルのみ。本文はPOSTできない
  • 1時間ごとに設定してもその通りには処理してくれないのはTwitterfeedと同じ。Twitterfeedより早くPOSTしてくれることもあれば、その逆の場合もある
  • URL短縮はow.ly。これはHootSuiteの関連サービスのようだ。リダイレクトではなく、フレーム内に短縮先ページを表示するのが嫌だ


Pingvine
  • 最短5分間隔
  • シンプルで最低限の機能。ユーザー登録も無し
  • 1つのサービスにつき1つのフィードしか登録できない
  • 登録したがPOSTされない。と思ったら何日か経って忘れた頃にPOSTされ始めた。


Twitterボットを簡単につくれちゃう! Bot Maker(ボットメイカー)
  • 国産
  • シンプルで最低限の機能
  • (試してない)

PHP5.3だと CakePHPで Deprecatedエラーが出まくる問題の対処方法

PHP5.3ではE_ALLにE_DEPREATEDが含まれるので、こんなエラーが出まくる。

PHP Deprecated: Assigning the return value of new by reference is deprecated in ...

そこで、cake/libs/configure.phpの290行目あたりに下記の処理を入れればDeprecatedエラーが出なくなる。
if (isset($config['debug'])) {
 if ($_this->debug) {
  error_reporting(E_ALL);
  //この下のIF文を追加する
  if (error_reporting() > 6143) {
   error_reporting(E_ALL & ~E_DEPRECATED);
  }

ついでに、php.iniでのerror_reportingは「E_ALL | E_STRICT」にしてるけど、CakePHPではE_STRICTが出て嫌だという場合には、httpd.confまたは.htaccessにてCakeのディレクトリのみ下記のようにerror_reportingを設定すればOK。(この値はPHP5.3の場合)
php_value error_reporting 22527


この問題については#6026 (php 5.3 needs error_reporting(E_ALL & ~E_DEPRECATED);) - CakePHPでCakephp1.3に回されて、php 5.3 compatibility? - CakePHP | Google グループでは黙殺されている?


(2009/07/13 追記)
SimpleTestを使う場合、app/webroot/test.phpの28行目あたりにも下記を追加するとテスト時にDeprecatedが出なくなる。
error_reporting(E_ALL);
//この下のIF文を追加する
if (error_reporting() > 6143) {
error_reporting(E_ALL & ~E_DEPRECATED);
}
set_time_limit(0);
(追記終わり)


参考:
 PHP: 定義済み定数 - Manual (エラー定数のバージョンごとの値)

Firefox3.5で最後のタブを閉じてもWindowを閉じないようにする方法

Firefox3.0から3.5にUpdateしたら、全てのタブを閉じたときにFirefoxのWindow自体も閉じるようになってしまった。
(タブバーは常に表示するようにしている。)

これでは使いにくいので調べた。

Closing the only tab closes the windowにあるとおり、about:configで browser.tabs.closeWindowWithLastTab をfalseにすると、3.0までと同じように空のタブを残してくれるようになった。

どうも3.5がBeta版の時から論議が交わされてきた設定らしく、同じように不満を持つ人も少なくないようだ。

2009年6月24日水曜日

本に関連するTwitterアカウント(Botを含む)のリスト

本に関連するPOSTをしているTwitterアカウント(Botまたはユーザー)のリスト。


tnd (tnd)

積んでる本などを紹介するためのサービス @tnd 本の名前 #感想 で紹介できます 中の人@ina_ani
 参考:つんどいったー - 積んでるモノを **かるーく** 紹介


売れ筋Books(書籍総合) (uresuji_books)

今売れている本をつぶやきます。売れ筋Books隊の隊長です。




売れ筋 単行本 (uresuji_tankobn)

今売れている単行本をつぶやきます。



売れ筋 文庫 (uresuji_bunko)

今売れている文庫をつぶやきます。



売れ筋 新書 (uresuji_shinsho)

今売れている新書をつぶやきます。



売れ筋 マンガ (uresuji_manga)

今売れているマンガをつぶやきます。



ジュンク堂書店池袋本店/PC書 (junkudo_ike_pc)
ジュンク堂書店池袋本店6Fコンピュータ書の最新情報をお届けします


Amazon.co.jp ベストセラー (amz_ranking)
amazon.co.jp 本のベストセラーの順位変動をお知らせします。ある本の最高位が更新されたときと、一定期間ランキングを維持している場合にお知らせしています。
 参考:Amazonベストセラーを教えてくれるTwitterBotをGAE/Jで作りましたぞ - やればできる子の日記


(2009/07/13 追記)
読んだ 4 (yonda4) on Twitter
@yonda4 書名、で読んだ本やマンガを教えてください。読書の記録を取るサービスです。
 参考:twitterで読書記録。読んだ4!


(2009/07/20 追記)
bk1でも売れてるらしい (uresen) on Twitter
非公認わんこ(bot)。オンライン書店ビーケーワンの売れ線(ディリーランキング)をつぶやいてます。
 ※botだけどたくさんフォローしてる...

SEO 8か条+2

経験上、学んだSEOのコツ。

  1. タイトル要素には、検索で入力されるであろうキーワードを数個を、入力されるであろう順番に並べる。タイトルは20~30字程度で、かつ、検索結果に並んだときに検索者が見たくなる文にする
  2. h1~h3要素には、検索で入力されるであろうキーワードを数個を、入力されるであろう順番に並べる
  3. ページ内のテキストは多いほうが良い。(Text, Text, Text!)かつ、何らかの分野に特化する
  4. 内部リンクを網の目のように多くする
  5. リンク(内部リンクも外部からのリンクも)に使う文字列は、検索で入力されるであろうキーワードを数個を、入力されるであろう順番に並べる。画像をリンクにする場合には、画像のalt属性にその文を入れる
  6. リンク(内部リンクも外部からのリンクも)は、リンク元のページの本文の中に埋め込まれている方がより良い
  7. トップページから末端ページまでたどり着くステップを少なくする
  8. コンテンツを1つのドメインに集める。サブドメインに分けない


あと、外部からのリンクは多いほうが良いが、現実問題としてはなかなか難しい。
はてなダイアリーがSEO上強いのは、上記のうち 3、4、6、8 に該当するから。(もちろんはてなブックマークからの多大な恩恵もあるが。)


おまけ:携帯サイトの場合
  1. 携帯サイトは、モバイルサイトマップをGoogleとYahooに登録する
  2. 携帯サイトは、携帯サイトからのリンクを貼る

ブログ アーカイブ

tags