2008年12月13日土曜日

YouTubeのパートナープログラムで10万ドル以上稼ぐ人

ニューヨークタイムズの記事より。
YouTube Videos Pull In Real Money

2007年末に始まったYouTubeのPartner Program(YouTubeのパートナーになったユーザーがビデオに広告を組み込んで報酬を得る仕組み)を通じて、10万ドル単位で稼いでいる人や団体がいるそうです。
記事の中でMichael Buckleyという人が紹介されていますが、この人は現在では仕事をやめて、フルタイムでYouTube用のビデオを作っているとか。
ちなみにどんなビデオかというと...



このようなビデオを週に3回ずつ投稿しているそうです。
(各エピソードの閲覧数は平均で20万、最も人気のあるもので300万!)

2008年11月20日木曜日

[iGoogle] アマゾンで今売れている商品を表示するガジェット

アマゾンの各ストアごとに現在売れている商品を表示するガジェットです。

以前もアマゾンのベストセラーに関するガジェットをつくりましたが、そちらはアマゾンのRSSを利用して、こちらはアマゾンのWebサービス(Amazon Associates Web Service)を利用しています。
主な変更点は...
カテゴリーを細かく指定することができる。
より多くの商品を表示することができる。
(中古商品が出品されている場合は)中古の価格を表示。

iGoogleに追加する場合はこちらからどうぞ
Add to Google

自分のブログやWebページに埋め込む場合はこちらからどうぞ

2008年11月19日水曜日

[iGoogle] 新刊本の情報を表示するガジェット

今月発売の書籍を表示するガジェットです。
月別・カテゴリー別の表示指定が可能です。
アマゾンのマーケットプレイスに古本が出品されている場合は古本の価格(出品されているうちの最安価格)もチェックできます。

以前も新刊本に関するガジェットをつくりましたが、そちらはアマゾンのRSSを利用して、こちらはアマゾンのWebサービス(Amazon Associates Web Service)を利用しています。
本当は月別だけではなくて、日別/週別の表示も可能にしたかったのですが、Webサービスの仕様上、月単位での区切りが限界のようですので、ご了承下さい。

iGoogleに追加する場合はこちらからどうぞ
Add to Google

自分のブログやWebページに埋め込む場合はこちらからどうぞ

2008年11月16日日曜日

[iGoogle] Hot Pepperの飲食店を地図から検索できるガジェット

ホットペッパー(hotpepper.jp)に登録されている飲食店を地図(Googleマップ)から検索できるガジェットです。
ランチや飲み会でクーポン使いたいな、という時に便利(?)。


お店の検索の仕方

希望する「範囲」と「ジャンル」を指定して「周辺のお店を検索」ボタンをクリックすると、地図の中心(黒いアイコン)周辺のお店を検索できます。
周辺のお店を検索」ボタンの代わりに黒アイコンをクリックしても検索を実行できます。
また、「絞り込み」リンクからより詳細な条件指定を行うこともできます。


地図の場所について

デフォルトでは最初にページを読み込んだ時に、「新宿駅」を中心にした地図が開きます。
iGoogleにこのガジェットを追加する場合で、このデフォルト地点を変更するには、「設定を編集」を開いて「最初に表示する場所」に、希望する場所(駅名や市区町村名)を記入してください。


iGoogleに追加する場合はこちらからどうぞ
Add to Google

自分のブログやWepサイトに埋め込む場合はこちらからどうぞ

2008年11月7日金曜日

[iGoogle] 価格.comの製品検索&製品情報監視ガジェット

価格.comに登録されている製品を検索したり、特定の製品情報(最安価格など)を監視することができるガジェットです。


製品情報監視機能について
製品IDを登録すると、ページを読み込んだ時に指定された製品情報を自動的に表示することができます。
最安価格のチェックなどに活用してください。

※ 製品IDを登録することができるのはガジェットをiGoogleに追加した場合のみです。Webページ等に埋め込む場合には製品IDを指定できません。

製品IDとは?
製品IDは価格.comの製品ごとに付与されている個別の認識コードです。
このガジェットで製品を検索すると製品IDを確認することができます。
また、価格.comのURLからも確認することが可能です。
例えば、価格.comにおけるプレステ3(プレイステーション3 HDD 80GB クリアブラック CECHL00)のURL:

http://kakaku.com/item/20504010180

赤字の箇所が製品IDです。

製品IDを登録する方法
ガジェットの「設定を編集」から登録することができます。
登録することができる製品ID数の上限は5個です。


iGoogleに追加する場合はこちらからどうぞ
Add to Google

ブログやWebページに埋め込む場合はこちらからどうぞ

2008年11月6日木曜日

[iGoogle] 楽天で売れている商品をまとめてチェックできるガジェット

わりと細かくジャンルを指定することができるのが特徴です。
ただし、あまり深い階層のジャンルだとランキングを取得できないことがあります。

ページを開いた時に最初に読み込むジャンルを指定することができます。

(iGoogleに追加する場合)「設定を編集」を開いて「最初に表示するジャンルのID」に、希望するジャンルのIDを記述してください。
ジャンルIDは、ガジェット右上隅を確認してください。

ジャンルIDの例
総合ジャンル => 0
CD・DVD・楽器 => 101240
食品 => 100227

iGoogleに追加する場合はこちらからどうぞ Add to Google
自分のサイトやブログに埋め込む場合はこちらからどうぞ

2008年10月31日金曜日

[iGoogle] iTunesの新作・人気曲・人気アルバムを閲覧できるガジェット

appleのiTunesで配信されている各種フィード(iTunes Music Store RSS Generator)をまとめたガジェットです。
時間帯によっては読み込めない(エラーが出る)場合があるかもしれません。
しばらく時間をおくと復活すると思うのでご了承ください。

(iGoogleに追加する場合)「設定を編集」に「ジャンル」という項目があります。
ここで指定されたジャンルが、ページ読み込み時に最初に表示されます。


上のサンプルは日本のiTunes Storeだけに対応したタイプですが、インターナショナル版も同時に作成しました。
世界の音楽に興味のある方はそちらをおすすめします。

iGoogleに追加する場合はこちらからどうぞ(日本版) Add to Google
インターナショナル版はこちらから Add to Google

自分のブログやWebページに埋め込む場合はこちらからどうぞ 日本版 | インターナショナル版

関連ガジェット
[iGoogle] CD新発売情報取得ガジェット

2008年10月29日水曜日

[iGoogle] ソーシャルブックマークの人気ページをまとめてチェックできるガジェット

色々なソーシャルブックマークで「ホット」「人気」「話題」のページをまとめて閲覧できるガジェットです。
それぞれのフィードをRSSリーダーに登録して購読するより、話題になっているページを簡単に俯瞰できると思います。



対応しているソーシャルブックマークサービス

Yahooブックマーク
はてなブックマーク
livedoor クリップ
Buzzurl
@nifty クリップ

iGoogleに追加する場合はこちらからどうぞ Add to Google
自分のブログやWebページに埋め込む場合はこちらからどうぞ

関連ガジェット
[iGoogle] "ブログで話題のキーワード” をコンパクトにまとめたガジェット

2008年10月22日水曜日

[Ruby on Rails] will_paginateの便利なViewヘルパー

will_paginateのエントリー([Ruby on Rails] ActiveRecord以外でwill_paginateを使う方法)を書くためにwill_paginateのソースを読んでみたら、使えそうなViewヘルパーがあったのでメモ。

will_paginate(collection = nil, options = {})

よく使うやつですね。
詳細ははぶきます。

参考リンク:
will_paginateに移行 - ひげろぐ


paginated_section(*args, &block)

will_paginateメソッドの親戚。パラメーターは共通です。

<% paginated_section @posts do %>
<ol id="posts">
<% for post in @posts %>
<li> ... </li>
<% end %>
</ol>
<% end %>

このように書くと...
<div class="pagination"> ... </div>
<ol id="posts">
...
</ol>
<div class="pagination"> ... </div>




page_entries_info(collection)
ページの情報を人間が見やすい形で整形してくれる。(残念ながら英語にしか対応していませんが)
<%= page_entries_info @posts %>
# #-> Displaying entries 6 - 10 of 26 in total

日本語にするならこんな感じでヘルパーを書く
application_helper.rb
def my_page_entries_info(collection)
if collection.total_pages < 2
case collection.size
when 0; 'エントリーは見つかりません'
when 1; '<b>1</b> 件のエントリーを表示しています'
else; "<b>#{collection.size}</b> 件のエントリーを表示しています"
end
else
%{<b>b</b>%d  〜  %d<b>/b</b> 件目 / <b>%d</b>件} % [
collection.offset + 1,
collection.offset + collection.length,
collection.total_entries
]
end
end

2008年10月21日火曜日

[Ruby on Rails] ActiveRecord以外でwill_paginateを使う方法

will_paginateはページングを行うための便利なライブラリです。
普通ActiveRecordと連携して使用することが多いと思うのですが、ActiveRecordと無関係に、普通の配列にも使えるようです。

APIを通じてデータを取得する場合などに使えそうです。

How to use will_paginate with non-ActiveRecord collection/array
(http://www.sharingb.com)


1. コレクションを取得する

ActiveRecordの場合

@posts = Post.paginate(:page => params[:page], :per_page => 10)

(@postsはWillPaginate::Collectionクラスのインスタンスになります)

非ActiveRecordの場合
@posts = Post.perform_search_and_obtain_collection(params[:criteria])

(@postsはデータの中味とデータの総数を参照できるオブジェクトを想定)


2. WillPaginate::Collection クラスのインスタンスを作成する

ここがポイントです。
非ActiveRecordの場合、WillPaginate::Collectionクラスのインスタンスを作成する必要があります。
@page_results = WillPaginate::Collection.create(params[:page], 10, @posts.total_results) do |pager|
pager.replace(@posts.items.to_array)
end

引数には現在のページ、ページごとのデータ数、データの総数を渡します。

データ(@posts.items)が配列の場合はこのように書くこともできます。
@page_results = @posts.items.paginate({
:page => params[:page],
:per_page => 10,
:total_entries => @posts.total_results
})


3: View

WillPaginate::Collectionクラスのインスタンスを作成したら、あとはActiveRecordと連携した場合と一緒です。
<ol>
<% for post in @page_results -%>
<li>Render `results` in some nice way.</li>
<% end -%>
</ol>

<p>Now let's render us some pagination!</p>
<%= will_paginate @page_results %>

2008年10月20日月曜日

[Ruby on Rails] テキストフォーマット関連の便利なViewヘルパー

Module: ActionView::Helpers::TextHelper
(http://api.rubyonrails.com)

auto_link(text, link = :all, href_options = {}, &block)

テキストに含まれるURLとメールアドレスをAタグで囲えるメソッド。

パラメーター


text:
置き換えたいURLやメールアドレスが含まれるテクスト

link:
:all(default), :email_addresses, :urlsの3つから選べる。:allはURLとメールアドレスをすべて変換。

href_options:
属性をハッシュで指定できる。{:target => '_blank'}など。

&block:
置き換えの対象のURLやメールアドレスをブロックで処理できる。

auto_link("Go to http://www.rubyonrails.org and say hello to david@loudthinking.com")
# => "Go to <a href=\"http://www.rubyonrails.org\">http://www.rubyonrails.org</a> and
# say hello to <a href=\"mailto:david@loudthinking.com\">david@loudthinking.com</a>"

auto_link("Visit http://www.loudthinking.com/ or e-mail david@loudthinking.com", :urls)
# => "Visit <a href=\"http://www.loudthinking.com/\">http://www.loudthinking.com/</a>
# or e-mail david@loudthinking.com"

auto_link("Visit http://www.loudthinking.com/ or e-mail david@loudthinking.com", :email_addresses)
# => "Visit http://www.loudthinking.com/ or e-mail <a href=\"mailto:david@loudthinking.com\">david@loudthinking.com</a>"

post_body = "Welcome to my new blog at http://www.myblog.com/. Please e-mail me at me@email.com."
auto_link(post_body, :all, :target => '_blank') do |text|
truncate(text, 15)
end
# => "Welcome to my new blog at <a href=\"http://www.myblog.com/\" target=\"_blank\">http://www.m...</a>.
Please e-mail me at <a href=\"mailto:me@email.com\">me@email.com</a>."


simple_format(text)

シンプルなルールで改行をフォーマットできるメソッド
2つ以上の連続する改行コード(\n\n) => pタグ
ひとつの改行コード(\n) => brタグ
my_text = """Here is some basic text...
...with a line break."""

simple_format(my_text)
# => "<p>Here is some basic text...<br />...with a line break.</p>"

more_text = """We want to put a paragraph...

...right there."""

simple_format(more_text)
# => "<p>We want to put a paragraph...</p><p>...right there.</p>"


Pタグがうるさく感じるようなら独自ヘルパーで対応。改行コードをbrタグに置き換え。
application_helper.rb
module ApplicationHelper
def linebreaksbr(text)
return text.gsub(/\r\n|\r|\n/, "<br />")
end
end



textilize(text)

Textile
記法をHTMLに変換できるメソッド。
Textileのシンタックスについて詳しくはこちら
このメソッドを使用するにはRedClothモジュールが必要なので注意。
textilize("*This is Textile!*  Rejoice!")
# => "<p><strong>This is Textile!</strong> Rejoice!</p>"

textilize("I _love_ ROR(Ruby on Rails)!")
# => "<p>I <em>love</em> <acronym title="Ruby on Rails">ROR</acronym>!</p>"

textilize("h2. Textile makes markup -easy- simple!")
# => "<h2>Textile makes markup <del>easy</del> simple!</h2>"

textilize("Visit the Rails website "here":http://www.rubyonrails.org/.)
# => "<p>Visit the Rails website <a href="http://www.rubyonrails.org/">here</a>.</p>"


textilize_without_paragraph(text)

textilizeとほとんど同じだけど、こちらはPタグを付加しない。


truncate(text, length = 30, truncate_string = "...")

テキストをX文字以内に切り詰めるメソッド。
truncate("Once upon a time in a world far far away", 14)
# => Once upon a...

truncate("Once upon a time in a world far far away")
# => Once upon a time in a world f...

truncate("And they found that many people were sleeping better.", 25, "(clipped)")
# => And they found that many (clipped)

truncate("And they found that many people were sleeping better.", 15, "... (continued)")
# => And they found... (continued)

[iGoogle] "ブログで話題のキーワード” をコンパクトにまとめたガジェット

Yahooブログ検索kizashi.jpテクノラティジャパンが提供しているフィードを利用して、ブログで話題になっているキーワードを手軽にチェックできるガジェットを作りました。



「検索」
気になるキーワードをみつけたらワンクリックで検索できます

G => Googleウェブ検索
Y => Yahoo!ウェブ検索
N => Googleニュース検索

iGoogleに追加する場合はこちらからどうぞ Add to Google
ブログやWebページに埋め込む場合はこちらからどうぞ

関連ガジェット
[iGoogle] ソーシャルブックマークの人気ページをまとめてチェックできるガジェット

2008年10月19日日曜日

[iGoogle] "amazon.co.jpベストセラーズ" ガジェト

アマゾンで売れてる商品をチェックできるガジェットです。
Googleガジェットを利用しています。

本、音楽、DVDなどの主要カテゴリーと、それぞれの子カテゴリー(本 => 文学,ノンフィクション,コンピュータなど)までを細かく表示できるのが特徴です。

詳細リンクにカーソルをのせると詳しい情報を見ることができます。
表示する商品数は1〜10件まで設定することができます。



iGoogleに追加する場合はこちらからどうぞ Add to Google

自分のブログやWebページに掲載する場合はこちらからどうぞ。

関連ガジェット
[iGoogle] 新刊本情報取得ガジェット
[iGoogle] CD新発売情報取得ガジェット
[iGoogle] DVD新発売情報取得ガジェット

2008年10月17日金曜日

Rubyのhpricotを使ってページのタイトルと説明を取得してみる

Rubyのhpricotを使ってページのtitleとmetaのdescriptionをスクレイピングするメモ。

require 'hpricot'
require 'open-uri'
require 'kconv'
require "resolv-replace"
require 'timeout'

begin
doc = timeout(10){ Hpricot( open(url).read ) }
rescue URI::InvalidURIError
rescue OpenURI::HTTPError
rescue SocketError
rescue Errno::ENOENT
rescue RuntimeError
rescue TimeoutError
#各種エラー
end

title = doc.search('title').first.innerText.strip.toutf8
desc_elm = doc.search('meta[@name=description]').first
desc = desc_elm ? desc_elm.get_attribute('content').strip.toutf8 : ""

open-uriはタイムアウトの時間を設定するすることができないので別途処理。


参考サイト:
RubyのHpricotも便利さでは負けていないの巻 (CodeZine)
RubyでHTMLとWebを操作するためのライブラリ、HpricotとWWW::Mechanize
open-uriにtimeoutを設定する方法

2008年10月14日火曜日

Javascriptで小数点以下X桁を四捨五入する

例えば

3.14159265

という数字があって、これを小数点以下3桁を四捨五入して

3.14

にしたい場合。

Javascriptの Math.round をそのまま使っても上手くいかないし、小数点以下うんぬんという引数も指定できない。

Math.round(3.14159265); // => 3


ちょこっと小細工(?)する必要があるようです。

3.14159265 を100倍して
var i = 3.14159265 * 100; // => 314.159265

小数点以下を四捨五入する。
i = Math.round(i); // => 314

それを100で割ると
i / 100; // => 3.14

期待どおりの値が求められました。

四捨五入以外はこっち
Math.floor(n) 小数点以下 切り捨て Math.floor(1234.56); // => 1234
Math.ceil(n) 小数点以下 切り上げ Math.ceil(1234.56) // => 1235

2008年10月12日日曜日

LibroSpot: オンラインで本を管理するサイト

新しくWebサービスを作ったのでご紹介。



LibroSpot
(http://jp.librospot.com)

本のソーシャルブックマークのような感じで使ってもらうのを想定して作りました。

オンライン本棚
読書記録
これから読む本のリスト

として利用できると思います。


特徴
本ごとにコメント、タグを付けられます。
「未読」「既読」「読書中」のステータス管理ができます。


必要なもの
Googleのアカウント

もちろん無料でご利用いただけます。


このサイトを作るのに利用したもの

Google App Engine
インフラ

Amazon Associates Web Service
本のデータはアマゾンのWebサービスを利用して取得しています。
Python用のライブラリが見つからなかったので自分で書きました。とても公開できるレベルじゃありませんが。。。

Google Book Search API
Embedded Viewer APIを使って本の内容をプレビューすることができるのですが、日本語の書籍はまだまだ対応している数が少ないようで。ほとんどプレビューすることができません。

Django
Google App Engine Django Helperもあわせて利用しています。

jQuery
Javascript関係

2008年10月7日火曜日

[iGoogle] 「2ちゃんねるまとめのまとめ」ガジェット

Webサイト版「2ちゃんねるまとめのまとめ」リリースしました。
http://2chfeed.appspot.com/

各まとめブログさんの過去記事をたどれるようになっているので(少しですが)
お暇な時に一気読みでもどうぞ

--------

戯れにGoogleガジェットでこんなものを作ってしまいました。



下のまとめブログさんをまとめています。

痛いニュース(ノ∀`)
【2ch】ニュー速クオリティ
ハムスター速報 2ろぐ
日刊スレッドガイド
ベア速
カナ速
ワラノート

編集できる設定
最大何件表示するか
サマリーを表示するかどうか
投稿日時を表示するかどうか

iGoogleに追加するには上のGoogleのロゴからどうぞ。
自分のブログやWebサイトに張りたい方はこちらからどうぞ。

Google App EngineのDjangoヘルパーでユーザーのプロフィールを利用しやすくしてみる

この前の記事(Google App EngineのDjangoヘルパーで認証してみる)からDjangoヘルパーを利用したApp Engine用のアプリをしこしこと作ってるのですが、もともとDjangoにうといもので、ソースコードを汗書いて読んだりしながら格闘している感じです。

そんな中で、Userモデルの get_profile というメソッドの使いどころがちょっと分からなかったので、調べたところをメモ。

django_appengine.auth.models

def get_profile(self):
"""
Returns site-specific profile for this user. Raises
SiteProfileNotAvailable if this site does not allow profiles.

When using the App Engine authentication framework, users are created
automatically.
"""
from django.contrib.auth.models import SiteProfileNotAvailable
if not hasattr(self, '_profile_cache'):
from django.conf import settings
if not hasattr(settings, "AUTH_PROFILE_MODULE"):
raise SiteProfileNotAvailable
try:
app_label, model_name = settings.AUTH_PROFILE_MODULE.split('.')
model = models.get_model(app_label, model_name)
self._profile_cache = model.all().filter("user =", self).get()
if not self._profile_cache:
raise model.DoesNotExist
except (ImportError, ImproperlyConfigured):
raise SiteProfileNotAvailable
return self._profile_cache

get_profileは名前のとおりユーザーと関連づけられたプロフィールを取得するためのメソッドです。

Djangoヘルパーを利用すると、初回ログイン時にUserモデルにユーザーのデータが自動で保存されますが、プロフィールを格納するモデルは用意されていません。
なので、プロフィール用のモデルを各自定義する必要があります。
from appengine_django.auth.models import User

class Profile(BaseModel):
user = db.ReferenceProperty(User) #Userモデルを参照
address = db.StringProperty() #住所
bio = db.TextProperty() #自己紹介

def __str__(self):
return self.user.username

こんな感じで住所と自己紹介を保存するモデルを定義しました。

さらに、setting.py に下のように記述
AUTH_PROFILE_MODULE = ‘app.Profile’ #app名.モデル名

これでget_profileを使う準備ができました。

view.py
def index(request):
if request.user.is_authenticated():
try:
address = request.user.get_profile().address
bio = request.user.get_profile().bio
except DoesNotExist:
#ログインしていても
#プロフィールが登録されていないとDoesNotExistが飛んでくる

プロフィールの作成や削除については特別なことはなにもないので割愛。

2008年10月5日日曜日

[Zend Framework] Zend_Db_Profiler_Firebugでデータベースをプロファイリングしてみる


Zend Framework1.6には Zend_Db_Profiler_Firebug というちょっと興味深いコンポネントが追加されたようです。

Firebug によるプロファイリング
(http://framework.zend.com/manual/ja)

これは Zend_Db_Profiler を拡張したクラスなのですが、
そもそも Zend_Db_Profiler というのは...

Zend_Db_Profiler を使用すると、クエリの情報を取得することができます。 アダプタが実際に実行したクエリの内容や実行所要時間などが取得でき、 余計なデバッグコードをクラスに追加しなくてもクエリを調べられるようになります。 さらに、条件を指定して特定のクエリだけの情報を取得することもできます。

Zend_Db_Profiler_Firebugは、プロファイルした情報をログに保存したり、echoやprintで出力する代わりに、Firebugのコンソールで監視することができます。

Zend_Db_Profiler_Firebugに必要な環境:
Firefox
Firebug (https://addons.mozilla.org/en-US/firefox/addon/1843)
FirePHP (https://addons.mozilla.org/en-US/firefox/addon/6149)


使用法は非常にシンプルで起動ファイルに次のように書くだけです。
// 起動ファイル

$profiler = new Zend_Db_Profiler_Firebug('All DB Queries');
$profiler->setEnabled(true);

// プロファイラを db アダプタにアタッチします
$db->setProfiler($profiler)

// フロントコントローラをディスパッチします

// モデル、ビューそしてコントローラファイル内で発行されたすべての
// DB クエリのプロファイル結果が Firebug に送信されます

これだけで、全クエリをFirebugで監視することができるようになります。

SELECTクエリだけ調べたいとかDELETE/UPDATEだけ調べたい、という使い方もできます。詳しくはZend_Db_Profilerのマニュアルをご覧ください。

2008年9月30日火曜日

seekAttention: ページ内の特定要素をハイライトするjQueryプラグイン

「ほら、ここを見てください」と指をさして知らせるように、ページ内の特定部分をハイライトできるjQueryのプラグインです。

seekAttention
(http://enhance.qd-creative.co.uk)

HTMLでマークアップできる要素なら、たいていはハイライト表示できるようです。

リンク


パラグラフ


INPUTフィールド


画像


とても魅力的なプラグインなのですが、いくつか問題を含んでいるとホームページで注意を喚起しています。
実際に使用する際は十分にテストするのをお忘れなく。

2008年9月29日月曜日

あなたのコードでもぜひ使うべきRubyの21の小技

知っていると非常に便利そうなRubyの小技集

21 Ruby Tricks You Should Be Using In Your Own Code
(http://www.rubyinside.com/21-ruby-tricks-902.html)

Rubyビギナーには目がクラクラしそうなコードが並んでるけど、こういうのを自然に使いこなせたらできる人に見えるかも。

サンプルとしてふたつほど抜粋

and と or を使って処理をグループ化する

queue = []
%w{hello x world}.each do |word|
queue << word and puts "Added to queue" unless word.length < 2
end
puts queue.inspect

# Output:
# Added to queue
# Added to queue
# ["hello", "world"]

今まではこんな風に書いてました...
queue = []
%w{hello x world}.each do |word|
unless word.length < 2
queue << word
puts "Added to queue"
end


文字列やシンボル以外をハッシュのキーに使う
does = is = { true => 'Yes', false => 'No' }
does[10 == 50] # => "No"
is[10 > 5] # => "Yes"

今まではこんな風に書いてました...とうか真偽値をキーに使えるなんて知りませんでしたよ。
does = is = { true => 'Yes', false => 'No' }
bool1 = 10 == 50
does[bool1] # => "No"
bool2 = 10 > 5
is[bool2] # => "Yes"


可読性とのかねあいもあるけど、短くワンラインで書けるならそっちの方がいいように個人的には思います。

2008年9月27日土曜日

jQuery Context Menu Plugin: コンテキストメニュー(右クリックメニュー)を操作するプラグイン


特定の要素の上で右クリックすると、準備しておいたメニューが現れるというjQueryのプラグイン。
方法によっては非常に強力な使い方ができそうです。

jQuery Context Menu Plugin
(http://abeautifulsite.net)
デモ

デモのコンテクストメニューは Edit, Cut, Copyなどが用意されています。
HTMLは下のような感じ。

<ul id="myMenu" class="contextMenu">
<li class="edit">
<a href="#edit">Edit</a>
</li>
<li class="cut separator">
<a href="#cut">Cut</a>
</li>
<li class="copy">
<a href="#copy">Copy</a>
</li>
<li class="paste">
<a href="#paste">Paste</a>
</li>
<li class="delete">
<a href="#delete">Delete</a>
</li>
<li class="quit separator">
<a href="#quit">Quit</a>
</li>
</ul>

Editの場合、Aタグのhref属性に #edit と指定されていますが、#をのぞいた edit がメニューの選択時にactionとして引数に渡されてきます。
Aタグにclassを指定することもできますが、class名とaction名がかぶるとうまく動かないようなので注意。


$(document).ready( function() {
$("#selector").contextMenu({
menu: 'myMenu'
},
function(action, el, pos) {
alert(
'Action: ' + action + 'nn' +
'Element ID: ' + $(el).attr('id') + 'nn' +
'X: ' + pos.x + ' Y: ' + pos.y + ' (relative to element)nn' +
'X: ' + pos.docX + ' Y: ' + pos.docY+ ' (relative to document)'
);
});
});

第1引数はプラグインのオプション。
menu は使用するメニューのID名です。

ドキュメントには書かれていませんが
inSpeed, outSpeed というオプションも指定できるようです。
これはメニューの出現/消滅時の fadeIn/fadeOutの引数に渡されています。
(指定しない場合は inSpeed=150, outSpeed=75)


第2引数はコールバック関数。
メニューが選択された時に呼び出されます。
actionはメニューで指定したAタグのhref属性です。 (href="#[action]")



メソッドが5つ用意されています。

disableContextMenu() / enableContextMenu()
コンテクストメニューの解除/適用
$('#selector').disableContextMenu(); //#selectorのメニューを解除
$('#selector').enableContextMenu(); //#selectorにメニューを再適用


disableContextMenuItems(expr) / enableContextMenuItems(expr)
$('#myMenu').disableContextMenuItems('#cut,#copy'); //cutとcopyだけメニューから解除
$('#myMenu').enableContextMenuItems('#cut,#copy'); //cutとcopyを再適用


destroyContextMenu
マッチする要素をプラグインから外します。

jQueryでJSONP

jQuryだとJSONPを行うのに余計なライブラリを読み込んだり、DOM操作でSCRIPTタグをああだこうだする必要ないので簡単。
普通にAJAXの処理を書く延長で対応できます。


jQuery.getJSON( url, [data], [callback] )

一番シンプルな書き方。

$.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=?",
function(data){
$.each(data.items, function(i,item){
$("").attr("src", item.media.m).appendTo("#images");
if ( i == 3 ) return false;
});
});

コールバック関数を jsoncallback=? のように書くのがポイント。
こうすると引数の関数がコールバックで呼び出されます。

jQuery.getJSONのドキュメント
http://docs.jquery.com/Ajax/jQuery.getJSON



jQuery.ajax( options )

ちょっと複雑な処理 (例えばJSONPの 開始と終了時(註1) 終了時に何かを行うとか) をしたい時には jQuery.ajax を使うのが無難です。
$.ajax({
url : 'http://api.flickr.com/services/feeds/photos_public.gne',
data : {
tags : 'cat',
tagmode : 'any',
format : 'json'
},
dataType : 'jsonp',
jsonp : 'jsoncallback',
complete : function(){
//通信終了時の処理

},
success : function(data, status){
//通信が成功した場合の処理 (JSONPのコールバック関数はこれが呼ばれます)

},
beforeSend : function(){
//通信開始時の処理

},

error : function(){
//通信が失敗した場合の処理

}

});

基本的にはAJAXの処理と書き方は同じです。

特徴的なのは dataType に jsonp を指定すること。
これだけでクロスドメインの通信が可能に。

そして、jsonpオプションでコールバック関数のパラメーター名を指定しています
これはどういうことなのかというと、jQueryはデフォルトでコールバック関数名をcallback というパラメーター名で補完します。
http://api.flickr.com…&callback=?

ただ、Flickrがそうであるようにパラメーター名は普通独自の名前を持っています。(Flickrの場合はjsoncallback)
jsonpオプションはこのパラメーター名を指定するためのオプションです。
{jsonp : 'jsoncallback'}
http://api.flickr.com…&jsoncallback=?


jQuery.ajaxのドキュメント
http://docs.jquery.com/Ajax/jQuery.ajax

※ 註1

Note: All remote (not on the same domain) requests should be specified as GET when 'script' or 'jsonp' is the dataType (because it loads script using a DOM script tag). Ajax options that require an XMLHttpRequest object are not available for these requests. The complete and success functions are called on completion, but do not receive an XHR object; the beforeSend and dataFilter functions are not called.

$.ajax では jsonpで beforeSend などコールバック関数もコールされると思っていましたが、勘違いでした。
実際にコールされるのはsuccess complete だけですのでご注意を。


追記:

上記の制限を解決してくれるプラグインがあるようです。

Google Code: jquery-jsonp
http://code.google.com/p/jquery-jsonp/

エラーハンドリング、キャッシング、タイムアウトなど、デフォルトでは対応できない機能が使えるようになるみたいなので、必要な方は使ってみてはどうでしょうか。

2008年9月25日木曜日

Google App EngineのDjangoヘルパーで認証してみる

Djangoヘルパーを使えばApp Engine上でも簡単に独自の認証システムを導入できると思ってたら、どうやらそうじゃないみたい。
あくまでUsers API前提の仕様みたいです。

それでもデコレーターとかタグとか色々便利そうなので使ってみることにしました。


モデル

user という UserProperty が入っているのがDjangoオリジナルと違う所。
もうひとつ違う点は get_djangouser_for_user というクラスメソッドが追加されています。

appengine_django.auth.models

class User(BaseModel):
user = db.UserProperty(required=True)
username = db.StringProperty(required=True)
first_name = db.StringProperty()
last_name = db.StringProperty()
email = db.EmailProperty()
password = db.StringProperty()
is_staff = db.BooleanProperty(default=False, required=True)
is_active = db.BooleanProperty(default=True, required=True)
is_superuser = db.BooleanProperty(default=False, required=True)
last_login = db.DateTimeProperty(auto_now_add=True, required=True)
date_joined = db.DateTimeProperty(auto_now_add=True, required=True)
groups = EmptyManager()
user_permissions = EmptyManager()

@classmethod
def get_djangouser_for_user(cls, user):
query = cls.all().filter("user =", user)
if query.count() == 0:
django_user = cls(user=user, email=user.email(), username=user.nickname())
django_user.save()
else:
django_user = query.get()
return django_user


初回ログイン時に自動的にDatastoreにユーザー情報が放り込まれるようです。

あとは普通のDjangoの認証システムとあまり変わりません。
viewで request.user.is_authenticated() のようなメソッドが使えます。


デコレーター
from appengine_django.auth.decorators import login_required

@login_required
def index(request):
・・・

これだけでログインしていないユーザーを弾くことができます。


テンプレート

{% auth_login_url %} => ログインのURL
{% auth_logout_url %} => ログアウトのURL


Google App Engine Helper for Django
(http://code.google.com/p/google-app-engine-django/)

jQuery Autocomplete: 入力値をAjaxで補完するjQueryプラグイン


フォームに文字の一部を入力するとマッチする結果をAjaxで返してくれるオートコンプリート。
例えば、appleのホームページの検索ボックスは、"ip" と入力するとiphoneやipodを自動で表示してくれます。

jQuery Autocompleteはオートコンプリート機能を手軽に実装できるjQueryのプラグインです。

jQuery Autocomplete Mod
(http://www.pengoworks.com)

使い方はいたってシンプルです。
まずはjQuery Autocompleteからjavascriptファイルとcssファイルをダウンロード。

<script type="text/javascript" src="/javascripts/jquery.autocomplete.js"></script>
<link rel="stylesheet" type="text/css" href="/stylesheets/jquery.autocomplete.css" />
パスは自分の環境に合わせてください


id_name というidを持つinput要素にjQuery Autocompleteを適用します。(もちろんid名はなんでもかまいません)
<input type="text" name="name" value="" id="id_name" />

<script type="text/javascript">
$(document).ready(function(){
$('#id_name').autocomplete('autocomplete_ajax.php');
});
</script>

オートコンプリートはAjaxで通信しますので、サーバー側で検索処理などを行うスクリプトを置いておく必要があります。(上の例では autocomplete_ajax.php)

では、jQuery Autocompleteは具体的にどうやって通信しているのでしょうか?

Ajax云々の処理は、プラグインが内部的にやってくれるので特に気にする必要はありません。

例えば、id_nameというフィールドが国名を期待するものであるなら、
"A" と一文字入力すると Afghanistan, Argentina, Australia などの国名のリストをサーバーが返してくるようにスクリプトを書くだけです。

"A"が入力されると...

クライアント -> サーバー
autocomplete_ajax.php?q=A というリクエストが送信されます

サーバー
qというキーを持つGETパラメータを利用して、データベースなどから目的のリストを取得します。
取得したリストを\n区切りにしてクライアントに返します。
Afghanistan\nArgentina\nAustralia...

あとはjQuery Autocompleteが\n区切りを解析してULタグの中に放り込んでくれます。



jQuery Autocompleteは第2引数でオプションを指定することができます。
くわしくはドキュメントを参照してください。

ここでは jQuery Autocompleteのデモを参考に、コールバック関係のオプションのサンプルをまとめておきます。
<script type="text/javascript">
function findValue(li) {
if( li == null ) return alert("No match!");

// if coming from an AJAX call, let's use the CityId as the value
if( !!li.extra ) var sValue = li.extra[0];

// otherwise, let's just display the value in the text box
else var sValue = li.selectValue;

alert("The value you selected was: " + sValue);
}

function selectItem(li) {
findValue(li);
}

function formatItem(row) {
return row[0] + " (id: " + row[1] + ")";
}

$(document).ready(function(){
$('#id_name').autocomplete('autocomplete_ajax.php', {
onItemSelect : selectItem,
onFindValue : findValue,
formatItem : formatItem
});
});
</script>

2008年9月21日日曜日

Timer: 繰り返し処理を行うためのjQueryプラグイン

javascriptで決まった処理を繰り返し行いたい時に便利なjQueryのプラグイン。

Timer
(http://plugins.jquery.com/project/Timer)

Prototype.jsには繰り返し処理用に PeriodicalExecuter という大変便利な機能があって、jQueryにも似たようなのがあるんだろう思ってドキュメントを探していたのですが、どうやらないようなのでプラグインを探しました。

このTImerはコードが30行ほどと非常にシンプル!
setIntervalとsetIntervalを駆使してタイマーを実装しています。

コードに付属しているサンプルを見れば使い方は一目瞭然。

var second = false;
$.timer(1000, function (timer) {
if (!second) {
alert('First time!');
second = true;
timer.reset(3000);
} else {
alert('Second time');
timer.stop();
}
});

上のサンプルではページを表示した1秒後に "Fist time!" というアラートが出て、その3秒後に "Second time"というアラーが出ます。さらに、その時点でタイマーをストップしています。

この例を応用すれば繰り返しに関するある程度の処理はOKなのではないでしょうか。
とても便利です。

2008年8月29日金曜日

Thumbnail Generator: 好きなサイズのサムネイルを生成するジェネレーター



Thumbnail Generator
(igen.appspot.com)

画像の一部(例えば顔のみ)を切り出して(crop)、サイズを変更する(resize)ジェネレーターです。

登録不要かつ無料でご利用いただけますが、Googleのアカウントをお持ちの方はログイン(sign in)していただくと画像がサーバーにストックされますので、後からもう一度サムネイルを作り直しやすくなっています。アップロードされた画像は他人に見られることはありません。

日本人はあんまり自分の素顔をネットにさらしたりしないけど、アメリカ人はブログとかSNSとかtwitterでバンバンさらしてますよね。そういう人たちに使ってもらえるかなあと淡い期待を込めて…、というのは建前で、Google App Engineimages APIを使ってみたくて習作的に作りました。
ちなみに、Mac & Firefoxでしか動作確認をしていないという超強気仕様です。

参考というかネタ元はこちら
PHP & jQuery image upload and crop

Javascript部分はjQueryを使っています。

使用しているjQueryのプラグイン

jQuery Form Plugin
Ajaxで画像をアップロードするのに使用

imgAreaSelect
画像の一部を選択するのに使用

恥ずかしながらファイルのアップロードをAjaxで実行するのがこんなに面倒だとは思いませんでした。(プラグインだとラクチン)
jQuery Form Pluginのソースをざっと見ると、iframeを使ってたりけっこう無茶をしてるみたいです。

2008年8月7日木曜日

[Ruby on Rails] 数字を整形する便利なViewヘルパー

意外と知られていない(?)便利なヘルパーです。
うっかり車輪の再発明をしそうになったのでメモ。

Module ActionView::Helpers::NumberHelper
(http://api.rubyonrails.org)

number_to_currency(number, options = {})
通貨のフォーマットに変換。($13.65)

オプション
:precision - 小数点以下何桁まで表示するか (デフォルト 2)
:unit - 通貨の単位 (デフォルトは"$")。ちなみに円マーク(¥)を半角にすると色々面倒なので全角にするが吉。
:separator - ユニットのセパレーター (デフォルト ".")
:delimiter - 桁が3つ繰り上がるごとの区切り文字(デフォルト ",")
:format - 出力される文字のフォーマット (デフォルト "%u%n") %uは通貨の単位 %nは数字部分


number_to_currency(1234567890.50)                    # => $1,234,567,890.50
number_to_currency(1234567890.506) # => $1,234,567,890.51
number_to_currency(1234567890.506, :precision => 3) # => $1,234,567,890.506
number_to_currency(1234567890.50, :unit => "£", :separator => ",", :delimiter => "")
# => £1234567890,50
number_to_currency(1234567890.50, :unit => "£", :separator => ",", :delimiter => "", :format => "%n %u")
# => 1234567890,50 £


number_to_human_size(size, precision=1)
バイトサイズを人間に理解しやすい形式にフォーマットを変換します。(例えば、1500 -> 1.5KB)
ファイルのサイズをユーザーに知らせる時などに便利なメソッドです。数字に変換できない場合はnilを返します。precisionパラメーターで小数点以下何桁まで表示するか指定できます(デフォルトは1)。


number_to_human_size(123)           # => 123 Bytes
number_to_human_size(1234) # => 1.2 KB
number_to_human_size(12345) # => 12.1 KB
number_to_human_size(1234567) # => 1.2 MB
number_to_human_size(1234567890) # => 1.1 GB
number_to_human_size(1234567890123) # => 1.1 TB
number_to_human_size(1234567, 2) # => 1.18 MB
number_to_human_size(483989, 0) # => 4 MB


number_to_percentage(number, options = {})
数字をパーセンテージのフォーマットに変換します(例 65%)。

オプション
:precision -小数点以下何桁まで表示するか (デフォルト 3)
:separator - ユニットのセパレーター (デフォルト ".")


number_to_percentage(100)                         # => 100.000%
number_to_percentage(100, :precision => 0) # => 100%
number_to_percentage(302.24398923423, :precision => 5)
# => 302.24399%


number_to_phone(number, options = {})
アメリカの電話番号のフォーマットに変換します。
詳細は割愛。

number_with_delimiter(number, delimiter=",", separator=".")
3桁ごとに区切り文字を挿入します(例 12,324)

オプション
delimiter - 区切り文字(デフォルト ",").
separator - ユニットのセパレーター (defaults to ".").


number_with_delimiter(12345678)       # => 12,345,678
number_with_delimiter(12345678.05) # => 12,345,678.05
number_with_delimiter(12345678, ".") # => 12.345.678
number_with_delimiter(98765432.98, " ", ",")
# => 98 765 432,98


number_with_precision(number, precision=3)
小数点以下何桁まで表示するか。


number_with_precision(111.2345)     # => 111.235
number_with_precision(111.2345, 2) # => 111.23
number_with_precision(13, 5) # => 13.00000
number_with_precision(389.32314, 0) # => 389

2008年8月4日月曜日

猿真似から入る人にはApp Galleryみたいなサイトがあると刺激になるよね

せっかくGoogle App Engineで作ったんだからApp Galleryで公開してみようってことで、ListCampをApp Galleryに登録してみました
(App GalleryというのはGoogle App Engineで作られたアプリのギャラリーです。)
登録といってもわずらわしいことは何もなくて、フォームに項目を記入して送信すれば審査もなくそのまま掲載してくれます。

このApp Garelley、眺めるだけでもけっこう刺激になります。
個人の手作り感がダイレクトに伝わってくるサイトが多いので「これなら自分でも作れそう」と変な自信が湧いてきたり。
トップページがエラー丸見え(!)になってるサイトがちらほらあるのはご愛嬌。
個人が作ったwebアプリをこうしてまとめて見ることができるサイトって他にないですかね?

Googleでちょろっと調べたらSimple Sparkというサイトを見つけました。
発見した時点で1万点弱のwebアプリが登録されていました。
ざっと見た所、個人が作ったサイトは少なくて、企業が金と手間をかけて作ったようなサイトが多い印象。
webアプリケーションであるなら誰でも登録できるようですが、掲載には審査があるみたいです。

2008年8月2日土曜日

ListCamp: リストを作って情報を共有するwebサービス


新しくWebサービスを作ったのでご紹介。

ListCamp
(listcamp.com)

「これははずせないFirefoxのアドオン」
「ロック史上の隠れた名盤」
のようなリストを作って情報を共有できるサービスです。
投票機能があってコメントも付けられるので
「好きな曜日は?」
「オバマとマケインどっちに投票する?」
のようなアンケートぽい使い方もできます。

ちなみにGoogle App Engine(GAE)で作った初めてのアプリです。
実はGAEどころかDjangoをいじるのも初めて(!)、Pythonを書くのも初めて(!!)、というわけでけっこう四苦八苦しましたが、一気呵成に仕上げた感じです。

2008年8月1日金曜日

Ruby on Rails + jQuery + Ajax で動的にページの一部を更新する

例えばTwitterでブラウザからつぶやきを投稿すると、ページを再読み込みしないで投稿したつぶやきだけが動的に追加されます。
あんな感じの処理をRails + jQueryで書いてみたので、そのメモをば。
Twitterのようなブログ系のアプリを想定しています。

大まかな流れ

1. フォームに記入された入力値をAjaxでサーバーに送信。
2. 入力値を検証。問題がなければ成功フラグを、問題があればエラーフラグをJSONでクライアントに返す。
3. 問題がなければJavascriptで新しい項目を追加。

Ajaxでページの一部を動的に更新する場合は普通こんな流れになると思います。1と3がクライアント(ブラウザー)サイド、2がサーバーサイドの処理です。

1. フォームに記入された入力値をAjaxでサーバーに送信

index.html.erb (railsのview)

<% form_for @post, :html => {:onsubmit => "return save(this);"} do |f| %>
<%= f.text_area :body, 'cols' => 40, 'rows' => 5 %>
<%= f.submit "投稿" %>
<div id="post_status" style="display:none;"></div>
<% end %>

<%div id="posts"%>
<%= render :partial => "post", :collection => @posts %>
<%/div%>

new.html.erbのような投稿専用のviewを用意しないで、ブログの一覧を表示するviewにフォームを設置します。なぜって?そうしなきゃAjaxで投稿するメリットがありませんから。

まずformのonsubmitを指定します。
もちろんjQueryの$(document).ready()で設定することも可能です。
また、送信のステータスを表示するDIV要素を仕込んでいます。

render :partialで_post.html.erb(記事部分)をレンダリングします。:collectionを指定することで@postsの中身をループ処理することができます。この部分はこの一連の処理の隠れたキモになるので注意。

_post.html.erb
<div class="post">
<%=h post.body %>
</div>

partialのviewには記事ひとつ分の記述をします。

Javascript
function save(f){
$.ajax({
url: $(f).attr('action'),
type: 'POST',
dataType: 'json',
timeout: 1000,
data : $(f).serialize(),
beforeSend : function(){ $('#post_status').html('送信中...').fadeIn(200); },
error: function(){alert('Error Occured');},
success: function(obj){
//通信が成功した場合の処理
}
});
return false;
}

saveはform要素を引数にとる関数です。
jQueryのserialize()を使ってフォームのデータをシリアライズ(a=1&b=2の形式)しています。
ちなみにserializeArray()という似たようなメソッドがありますが、こちらはフォームの入力値をハッシュ({a:1, b:2}の形式)にしてくれます。

2. サーバーサイド(Rails)の処理
モデルのバリデーション等はここでは省略します。

posts_controller.rb
def create
return redirect_to '/404.html' unless request.xhr?
post = Post.new(params[:post])
if post.save
html = render_to_string :partial => "post", :collection => [post]
render :json => {:success => 1, :html => html}
else
render :json => {:error => post.errors}
end
end

とりあえずAjax以外のアクセスは弾くという前提で。
return redirect_to '/404.html' unless request.xhr?
と書くと、Ajax以外のアクセスを404.htmlにリダイレクトしてくれます。

render_to_stringがこの一連の処理のキモかもしれません。というかこのメソッドを使わないとJavascirptで一生懸命DOMを書いたりしなければならなくなるでしょう。
さきほど作ったindex.html.erb内のrender :partialで指定したのと同じpartialテンプレート(_post.html.erb)をここで指定していることに注目してください。
記事の中身をpartialでレンダリングすることで、viewを使い回すことができます。
:collectionにpostを配列に入れて渡していることも注意。

3. 新たに投稿された記事部分を更新する

Javascript
function save(f){
$.ajax({
[中略]
success: function(obj){
//通信が成功した場合の処理
if(obj.error){
var html = '';
$(obj.error).each(function(){ html += this[1] + '<br />'; });
$('#post_status').text(html).css(color, 'red');
}else if(obj.success){
$('#post_status').text('正常に登録しました').css(color, 'green');
$('#posts').append(obj.html);
}
}
});
return false;
}

通信や入力値に問題がなければ、htmlを描画します。obj.htmlにはrender_to_stringでレンダリングしたhtmlが丸ごと格納されているので、後はそれをしかるべき場所に挿入するだけです。

2008年7月29日火曜日

[Google App Engine]Bulk Data Uploaderでデータをまとめてインポートする

まあ基本的にはマニュアルのとおりなんだけど、一カ所つまづいたのでメモしておきます。ちなみに開発環境の話です。

Loaderクラスを継承したクラスを書いてapp.yamlにエンドポイントを追加してCSVを用意した後
さあデータをアップロードするぞというところで。

./bulkload_client.py --filename people.csv \
--kind Person \
--url http://localhost:8080/load
[中略]
INFO 2008-07-29 10:23:56,365 bulkload_client.py] Importing 6 entities in 101 bytes
ERROR 2008-07-29 10:23:56,461 bulkload_client.py] An error occurred while importing: Received code 302: Requires login
ERROR 2008-07-29 10:23:56,462 bulkload_client.py] Import failed

ログインしてないよというエラーが発生します。

このエラーはbulkload_client.pyにcookieオプションをつけると解決するようです。
(aml.yamlの login: admin を削除すると上手く動くようですが、これは推奨できませんよね。)

./bulkload_client.py --filename people.csv \
--kind Person \
--url http://localhost:8080/load \
--cookie dev_appserver_login="test@example.com:True"
[中略]
INFO 2008-07-29 10:31:49,206 bulkload_client.py] Importing 6 entities in 101 bytes
INFO 2008-07-29 10:31:49,507 bulkload_client.py] Import succcessful


アプリ上でログインした後もtest@example.com:False になっている場合でも、test@example.com:Trueと手動で書き換えれば問題なく動作するようです。

[7/ 30追記]
本番環境にアップロードするのも基本的には同じです。
Googleにログインした状態で下のURLにアクセスすると
http://<yourapp>.appspot.com/load
The bulk load endpoint is: http://<yourapp>.appspot.com/load
Pass this flag to the client: --cookie='ACSID=AJKiYcFGvAqWeiQBFIeybzvHdi-NzXwSCEHHCFBpupSdRbzxamvzdR7qfYma0VZjm6i23Ujea2T...

という画面を見ることができるはずです。
そこに記載されているcookieをコピペして、ローカルのマシンでコマンドを叩くだけ
./bulkload_client.py --filename people.csv \
--kind Person \
--url http://<yourapp>.appspot.com/load \
--cookie ACSID=AJKiYcGf8BeBcd[中略]
INFO 2008-07-30 16:59:58,015 bulkload_client.py] Importing 9 entities in 234 bytes
INFO 2008-07-30 16:59:59,055 bulkload_client.py] Import succcessful



Porting legacy databases to Google App Engine
(http://thomas.broxrost.com/)

2008年7月27日日曜日

rubyでキャッシュ: 例えばrailsのActiveRecordクエリの結果をキャッシュするとか

例えば外部のAPIを叩いたり、データベースの重たい処理をする時など、キャッシュを上手く使った方がいいよねってことで、PHPでモノを作る時にはPEARのCache_LiteとかZend FrameworkのZend_Cacheなどを駆使してきました。Cache_LiteもZend_Cacheもserialize関数,unserialize関数を使って、シリアライズされた配列やオブジェクトをファイルに書き出したり読み戻しています。

ruby、というかrailsでキャッシュしたい時には、これまでrails付属のキャッシュシステム(主にfragmentキャッシュ)を利用してきましたが、railsのキャッシュは出力されるHTMLなどを保存するものですよね。
rubyで文字列やハッシュをキャッシュしたい時にはどうすればいいんだろうと調べていたら、Marshalというモジュールが使えるようです。

Marshal - Rubyリファレンスマニュアル

具体的な例としてActiveRecordクエリの結果をキャッシュするコード

Marshalize (Cache) ActiveRecord Query Results
(http://snippets.dzone.com)

class MyCachedModel < ActiveRecord::Base
class << self
alias_method :rails_original_find_by_sql, :find_by_sql
def find_by_sql(sql)
cache_filename = Base64.encode64(sql)
if File.exists? cache_filename
Marshal.load(File.open(cache_filename))
else
Marshal.dump(records = rails_original_find_by_sql(sql), File.open(cache_filename, 'w'))
return records
end
end
end
end


ファイルがあればMarshal.loadで読み戻し、なければMarshal.dumpで書き出しています。

Spacegallery: 珍しいタイプの画像ギャラリーを作れるjQueryプラグイン


Spacegallery
(http://eyecon.ro/spacegallery)

手前から奥に画像がずらっと並んでいて、画像をクリックすると手前の画像が前にズームアップしながら消えてひとつ奥の画像が現れるという画像ギャラリーを簡単に作れます。
口で言っても分かりにくいと思いますが、デモを見れば一目瞭然。
なんとなくappleが採用しそうなインターフェースではないでしょうか?

2008年7月23日水曜日

Facebox: facebook風のモーダルダイアログを簡単に導入できるjQueryプラグイン


Facebox
(http://famspam.com/facebox)

ダイアログ系のプラグインはたくさんありますが、これはfacebook風の角丸デザインでかわいらしい感じです。

jQuery:bind/triggerの使い方メモ

こういうモーダルダイアログというのは、ダイアログが開いている間はダイアログの周りの部分にオーバーレイがかけられて、その部分を操作することができなくなります。
「close」「閉じる」ボタンを押したり、オーバーレイの部分をクリックするとダイアログが閉じてオーバーレイも消えるようになっているのが普通です。
このFaceboxではその「閉じる」処理をどうやっているのか気になったので、ソースをちょっと見てみました。

基本的に「閉じる」処理を行う時は、document に登録されている close.facebox というイベントをtriggerで実行しているようです。

$(document).trigger('close.facebox')

例: オーバーレを表示する関数。オーバーレイの要素をクリックすると close.faceboxイベントを実行するようにclickイベントを登録しています。
function showOverlay() {
if (skipOverlay()) return

if ($('facebox_overlay').length == 0)
$("body").append('<div id="facebox_overlay" class="facebox_hide"></div>')

$('#facebox_overlay').hide().addClass("facebox_overlayBG")
.css('opacity', $.facebox.settings.opacity)
.click(function() { $(document).trigger('close.facebox') })
.fadeIn(200)
return false
}

肝心のclose.facebox
$(document).bind('close.facebox', function() {
$(document).unbind('keydown.facebox')
$('#facebox').fadeOut(function() {
$('#facebox .content').removeClass().addClass('content')
hideOverlay()
$('#facebox .loading').remove()
})
})


気になったのは close っていうイベントをtriggerで実行できるの?というかそんなイベント登録できるの?ということ。(.facebookの部分はこの前話題にした名前空間ですよね)

jQueryのドキュメントを読んでみると、冒頭にこんな記述があります。
Binds a handler to one or more events (like click) for each matched element. Can also bind custom events.
この「カスタムイベントも登録できるよ」という部分はこれまで完全に無視していましたが、つまりこういうことなんですね。勉強になります。

2008年7月22日火曜日

jGrowl: クールな通知機能を実装できるjQueryプラグイン


jGrowl
(http://stanlemon.net/projects/jgrowl.html)

Mac OS XのGrowl風の通知機能をWebアプリに組み込めるjQueryのプラグインです。
よくあるモーダルダイアログやポップアップとはひと味違ったインターフェースで、思わず使ってみたくなる魅力を持っています。
MOONGIFTさんが詳しく紹介されているので、参考までに。

実は、あまりにも気に入ってしまったので、半分勢いにまかせてdiscvoxxにも組み込んでしまいました。

2008年7月21日月曜日

timeago: 何日前?を教えてくれるjQueryプラグイン


timeago
(http://timeago.yarp.com/)

日付の表示で、日時ではなくX日前を表示しいているサイトはYouTubeのコメント欄などいろいろみかけますが、このtimeagoは日時からX日前(X時間前、X分前)を教えてくれるjQueryプラグインです。

jQuery.timeago(new Date());             //=> "less than a minute ago"
jQuery.timeago("2008-07-17"); //=> "4 days ago"
jQuery.timeago(jQuery("abbr#some_id")); //=> "a day ago" // [title="2008-07-20"]

ご覧のように、作成者が英語圏の方(?)なので、a minute ago、4 days agoという表現になっています。
日本語サイトに導入する場合はソースの該当部分を翻訳する必要があるかもしれませんが、とても分かりやすいので迷うことはないはずです。

jQuery Star Rating Plugin: 簡単に星形投票システムを実現できるjQueryプラグイン


jQuery Star Rating Plugin
(http://www.fyneworks.com/jquery/star-rating/)

YouTubeなどで見かける星形の投票システムを簡単に実装できるプラグインです。
原則的にradioボタンを星画像に自動変換してくれるので

<input name="star1" type="radio" class="star"/> 
<input name="star1" type="radio" class="star"/>
・・・

とclassにstarを指定するだけで導入できます。

ただ、ruby on railsのアプリケーション上でちょっと試してみたのですが、上手く使えませんでした。
原因はどうやら input の name要素で profile[name] のように[]を使用しているため内部的に不具合が発生しているようです。
Google Groupでもこの問題が挙っていたので対応したようですが、いまだに直っていないような(!?)

2008年7月18日金曜日

ruby初心者に参考になる7つの文例集

Ruby Snippets
(http://bendiken.net/snippets/ruby)

rubyではこんな感じで簡単にカッコよく書けるよという7つ文例集です。
それぞれ10行程度の短いコードなのですが、こんな書き方があるんだと感心してしまいました。

例えばRSSをパースするコード

def fetch_rss_items(url, max_items = nil)
%w{open-uri rss/0.9 rss/1.0 rss/2.0 rss/parser}.each do |lib|
require(lib)
end
rss = RSS::Parser.parse(open(url).read)
rss.items[0...(max_items ? max_items : rss.items.length)]
end

items = fetch_rss_items('http://www.digg.com/rss/index.xml', 5)
items.collect { |item| item.title }
=> ["Understanding AJAX - A Beginner's Guide",
"Anti-cancer Compound In Beer", ...]

こんなふうにrequireを書くことができるんですね。不勉強で知りませんでした。

この他に以下のコードが紹介されてるので気になる方はチェックしてみてください。

配列の中身を足し算/かけ算する
ランダムなパスワードを生成する
便利な正規表現
画像のサイズを計測する
階乗を計算する
あらゆる数字を序数化する

[jQuery] 名前空間(namespace)でイベントを管理する

使えそうなのでメモメモ。

jQuery namespaced event binding/unbinding
(http://codesnippets.joyent.com/posts/show/1345)

jQueryを使ってイベントを追加する場合は大抵こんな感じで書く:

jQuery('.class').click(function(){//whatever});

上のコードは下のように書くこともできるのはみんな知ってるよね:
jQuery('.class').bind('click', function(){//whatever});

でも時々イベントを削除したくなる場合がある:
jQuery('.class').unbind('click', function(){//});

で、問題なんだけど、こうやってイベントを削除すると、その要素に登録されている全部のイベントが削除されちゃうってこと。(無名関数を特定する手段がないからね)

でも、jQueryは賢いから、これを制御する方法がある。イベントに名前空間を指定してあげればいいんだ。
jQuery('.class').bind('click.namespace', function(){//}); 
jQuery('.class').unbind('click.namespace');

AJAXによって登録されたイベントを再初期化する場合はこんな感じ:
jQuery('.class').unbind('click.namespace').bind('click.namespace', function(){//});

Color Picker: Adobe Photoshopと同じ感覚で色選択ができるjQueryプラグイン


Color Picker (http://eyecon.ro/colorpicker/)

「Adobe Photoshopと同じように色を選択できるシンプルなコンポネント」らしいです。Photoshopは使ったことがないので使用感の違いが分かりませんが、クォリティは非常に高いのではないでしょうか。
色選択が必要になるシチュエーションというのは限られているものの、この品質の機能をプラグインでサクっと導入できるのはうれしいです。

jQuery Image Cube: 画像をキューブ状に見せるプラグイン


jQuery Image Cube (http://keith-wood.name/imageCube.html)

複数の画像を組み合わせて立体的に見せることができます。
なかなか印象的なプラグインです。
動きのストップ/スタートや、スピードやストップのタイミングの調整などもできるようです。
画像だけでなくテキストもキューブ化できるようなのでいろいろ使えそうですね。

2008年7月17日木曜日

Column Navigation: Mac OS X風のナビゲーションを実装するjQueryプラグイン


Column Navigation (http://plugins.jquery.com/)
デモ
ナビゲーションのインターフェースというとタブ、WindowsのExplore風のツリー形式、アコーディオンなど色々あるけれど、Mac OS X風のこのインターフェース(何て呼んだらいいんだろう?)もなかなかだと思います。
階層の深い形式を扱う時に選択肢のひとつになるはず。
ただ、ソースの例を見ると、HTMLがULタグの入れ子になってて、階層が深くなればなるほど頭がこんがらがりそうです…

jQuery Sparklines: グラフを描画するJQueryプラグイン


jQuery Sparklines (http://www.omnipotent.net/)

折れ線グラフと棒グラフをインラインで表示するシンプルなプラグインです。

<span id="ticker">Loading..</span>
$('#ticker').sparkline([1,2,3,4,5,4,3,2,1]);


オプションで幅・高さ・グラフや背景の色などを指定できます。

シンプルで使いやすいので、ちょっとしたグラフを入れたいという時に役に立ちそうです。

[Ruby on Rails] viewヘルパー::content_tag_for

content_tag_forという便利そうなヘルパーを見つけたのでメモ。ちなみに使えるのはrails2.xから。

<% content_tag_for(:tr, @person) do %>
<%=h @person.first_name %>
<%=h @person.last_name %>
<% end %>

と書くと
<tr id="person_123" class="person">....</tr>

というHTMLが生成されます。
ActiveRecordオブジェクトを展開してリスト表示したい、というのはよくあることなので色々使えそうです。

もちろんidやclassを指定できるし
<% content_tag_for(:li, @person, :class => "bar") %>...

と書くと
<li id="person_123" class="person bar">...

というHTMLが生成されます。

[参考] Rails API ドキュメント

jQuery File Tree: WindowsのExplorer風にメニューをツリー状に表現できるjQueryのプラグイン

エクスプローラ風のツリー表示は個人的にけっこう使いやすい/見やすいと思うのですが、自分で作ろうと思うと意外と面倒だったりするので、こういうライブラリの存在はありがたいです。

jQuery File Tree (http://abeautifulsite.net/)
デモページ

ツリーの情報をAJAXで取得するのが前提になっています。デモページのHTMLソースを見るととてもシンプルですっきりしています。
サーバーサイドのスクリプトもライブラリの中にバンドルされていて
PHP
ASP (VBS)
ASP.NET (C#)
ColdFusion
JSP
Lasso
Python/Django
Ruby
といった言語にあらかじめ対応しています。

2008年7月16日水曜日

Web開発者がすべからく知っておくべき7つのAjax & Javascriptライブラリ

おおげさなタイトルをつけてしまいましたが、The Top 30 Free Ajax & Javascript Code for Web Designersを参考に、知っておくと便利だと思うライブラリをピックアップしてみました。
いくつかはprototype.jsに依存しているのでご注意を。

Lightbox2(http://www.lokeshdhakar.com/projects/lightbox2/)


画像をクールに見せることができるライブラリ。
prototype.js, script.aculo.usに依存しています。
フレームワークに依存しないshadowbox.jsという類似のライブラリもあります。

Timeline (http://simile.mit.edu/timeline/)


出来事を時系列(タイムライン)に沿ってみせることができるライブラリ。Google Mapsのようにドラッグ&ドラッグで操作できるのが特徴です。

Reflection.js (http://cow.neondragon.net/stuff/reflection/)


画像をweb2.0風に鏡面加工できるライブラリ。

Plotr (http://solutoire.com/plotr/)


グラフを作成できるライブラリ。円グラフ、棒グラフ、折れ線グラフに対応しています。
prototype.jsに依存。

Starbox (http://www.nickstakenburg.com/projects/starbox/)


アマゾン等で見かける評価(レーティング)の星付け機能を設置できるライブラリ。
prototype.jsとscript.aculo.usに依存。

Ajax Tabs Content (http://www.dynamicdrive.com/)


AJAXに対応したタブを実装できるライブラリ。

Create Flickr Like Fields (http://dbachrach.com)


テキスト部分をクリックするとinputフィールドに変換するライブラリ。デモ

Appleのサイトで使われてるようなアコーディオン・メニューを実装したい

Appleのサイト(apple.com)で使われてるような折りたたみするメニュー - iPod + iTunesのページ(http://www.apple.com/itunes)で使われているやつ - がカッコいいなあと思ってたら簡単にマネできる方法があるみたいです。


Apple style Accordion Menu

上のサイトにjQueryとddaccordion.jsを使った実装方法の説明がありました。

jQueryとddaccordion.jsを読み込んだ後、ちょっとしたHTMLとJavascriptとCSSを記述するだけ!簡単です。
メニューの背景となる画像をあらかじめアップロードしておくのをお忘れなく。

jqDock: Mac OS X のDock風のメニューを実装するjQueryプラグイン

カーソルをあわせるとぐわっと拡大するあのMacのメニュー(Dock)をWebアプリに組み込めるjQueryのプラグイン。



使い方はいたってシンプル。

<script type='text/javascript' src='jquery-1.2.3.min.js'></script>
<script type='text/javascript' src='jquery.jqDock.js'></script>
<script type="text/javascript">
jQuery(document).ready(function(){
jQuery('#menu').jqDock(options);
});
</script>

<div id='menu'>
<img src='image1.gif' alt='image1.png' title='' />
...
<a href='page.html' title=''>
<img src='imageN.png' alt='' title='' />
</a>
...
</div>

オプションを指定すると横だけでなく縦にも表示できるようです。

jqDock v1.2 ... a jQuery plugin
http://www.wizzud.com/jqDock/index.php


このためだけにjQueryを使うのもなあ、というかたはこちらをチェックしてみてはいかがでしょう。

A Mac OS X-style Dock in Javascript
(http://safalra.com/web-design/javascript/mac-style-dock/)

AJAXアプリケーションで「戻るボタン」「ブックマーク」を実装する

AJAXを使ったサイトでネックになるのが「ブラウザの戻るボタンが使えない」「ブックマークができない」という点。
「そんなの別に気にしないよ」という人もいるかもしれないけど、作り手としてはその辺もきっちり作り込みたいですよね。
というわけで、AJAXを使ったアプリでも「戻るボタン」「ブックマーク」を実装できるライブラリをチェック。

Really Simple History

Google Code のプロジェクトページ
http://code.google.com/p/reallysimplehistory/

他のフレームワークを使わずに単体で動作するタイプです。

英語でちょっと古いけど下のサイトが一番詳しいのかな。
AJAX: How to Handle Bookmarks and Back Buttons
サンプルコードが充実しているので、コードを眺めてるだけでも使い方が分かると思います。


jQuery history プラグイン

jQuery history プラグイン

こちらはjQueryのplugin

デモ
http://www.mikage.to/jquery/jquery_history.html

どちらも、IEの場合のみiframeを使い,そのほかの場合はlocation.hashを参照しているようです。

PHPのコードを最適化するための42のTIPS

42 tips for optimizing your php code
http://mfw-php.blogspot.com/2008/07/42-tips-for-optimizing-your-php-code.html

中には些細なものもありますが、気になるものをいくつかピックアップ


  • __get, __set, __autoload のようなマジックメソッドを避けよう。

  • require_once() はコストがかかる。

  • includes と requires はフルパスを指定すべし。

  • regex(正規表現) の代わりに strncasecmp, strpbrk, stripos等が使えないか見直すべし。

  • if, elseif, elseif... と書くよりもswitch文を用いたほうがいい。

  • @を使ったエラー制御は遅い。

  • for ($x=0; $x < count($array); $x) のように書くと count() がループ毎に呼ばれるのでforループの中で使ってはいけない。

2008年7月14日月曜日

discvoxx: 盤(ディスク)でつながるソーシャルCDラックサービス


discvoxxという新しいwebサービスをはじめました。
discvoxx
http://discvoxx.com

どんなサービス?
好きなCDを登録して自分専用のオンラインCDラックを作成できるサービスです。
持っているCDをひたすら登録したり購入予定のCDのリストを作ったり。ブログをやっている方はレビューブログとしてもご利用いただけます。

ソーシャルってどういうこと?
discvoxx内で同じCDを登録している人をチェックしやすくなっています。
また、Twitterのように他の人のCDラックを「フォロー」する機能があります。フォローするとその人のラックを受信するようになります。


discvoxx
http://discvoxx.com

discvoxxブログ
http://discvoxx.blogspot.com

2008年7月6日日曜日

RubyとPythonとPHPで暗号化を行うためのメモ

Google App Engineでアプリケーションを開発中に、MD5で暗号化したURLをDatasotreに格納しようとしたら"UnicodeDecodeError / 'ascii' codec can't decode byte 0xe7 in position 3: ordinal not in range(128)"と怒られたのでちょっと調べてみました。

せっかくだからPythonとRubyとPHPで暗号化に関する関数/メソッド(MD5とかSHA-1)の使い方を比較。
MD5もSHA-1も言語ごとの使い方は基本的に同じですね。

Python
マニュアル:
md5 -- MD5 メッセージダイジェストアルゴリズム
SHA-1 メッセージダイジェストアルゴリズム

import md5
print md5.new("some text").digest()


上記のエラーはこのdigestメソッドの返り値を格納しようとして発生しました。
マニュアルにもあるようにdigest()メソッドは「nullバイトを含む非 ASCII 文字が入っているかもしれません。」ということなので、非ASCIIが混入していたのでしょう。
digest()メソッドをhexdigest()メソッドに変更したらエラーはなくなりました。
実はdigest()とhexdigest()の違いなんて意識したことなかったので(!)最初は何のことか分かりませんでした。


Ruby
マニュアル:
Digest::Base

require 'digest/md5'
p Digest::MD5.hexdigest(File.open('ruby-1.8.5.tar.gz','rb').read)

# => "3fbb02294a8ca33d4684055adba5ed6f"


Rubyにもdigest()メソッドとhexdigest()メソッドがあります。


PHP
md5
sha1

使い方は一番シンプル。関数を呼び出すだけ。
$str = 'apple';

if (md5($str) === '1f3870be274f6c49b3e31a0c6728957f') {
echo "Would you like a green or red apple?";
exit;
}
?>


python,rubyのhexdigest()メソッドと同等の関数なのでしょうか。
第二引数にTrueを指定するとバイナリ形式で返ってくるようです。(digestと同等?)

2008年7月1日火曜日

Mac OS X Leopard にApache,MySQL, PHPをインストール

Leoparad には標準でApche, PHP, Ruby, Ruby on Rails, Pythonなどがインストールされているので、買ったら即日開発に着手できるぞ〜なんて思ってたけど、そうは甘くありませんでした。

例えば、標準でインストールされているPHPにはPDOのMySQLドライバが入ってませんでした。
で、MySQLをPDOで使えるようにしようと思ったんだけど、これがけっこう大変なことに・・・

MySQL

MySQL5.0をdmg版をダウンロードしてサクっとインストール
/usr/local の下にインストールされます。
MacPortでインストールするとパスが違うようなので注意。(/opt/の下だったかな?)

~/.bash_profile にパスを追加しておく

PATH=/usr/local/mysql/bin:$PATH
export PATH


よーし、これでMySQLが入ったから、あとはPDOのMySQLドライバを入れれば動くのかな?と思ってMySQLドライバをインストールしたものの動かない・・・
php.iniとにらめっこしたものの、よく分からないが、どうやらpdo_mysql.soをうまく読み込んでくれないらしい(?)。
せっかくデフォルトでインストールされているんだから、あらためてPHPをインストールし直すのはなんだかなあ、と思いつつもPHPを再インストールするのが一番近道なようだ。

PHP
ソースからインストール
オプションは下のサイトなどを参考
LAMP in Leopard OSX 10.5 (PHP5 and Apache 2.2)
How to enable PDO_MYSQL in 5.2.4 PHP included into Leopard

./configure
--prefix=/usr
--mandir=/usr/share/man
--infodir=/usr/share/info
--with-apxs2=/usr/sbin/apxs
--enable-cli --with-zlib-dir=/usr
--enable-mbstring
--enable-mbregex
--enable-sockets
--with-curl=/usr
--with-config-file-path=/etc
--sysconfdir=/private/etc
--with-mysql-sock=/tmp/mysqld.sock
--with-mysqli=/usr/local/mysql/bin/mysql_config
--with-pear=/Library/PHP
--without-iconv
--without-openssl
--with-pdo-mysql=/usr/local/mysql/bin/mysql_config


上に書いたように、MySQL関連のパスはdmgでインストールした場合です。

php.iniの編集

/etc/pho.ini
extension=pdo.so
extension=pdo_mysql.so
を追加

mysql.default_socket = /tmp/mysqld.sock
を指定

これで大丈夫... のはずが
apacheがlibphp5.soを読み込めないとエラーを吐きだす始末。

Apache

Leopard で PHP5 を再構築できなかった話
Custom MAMP on Mac OS 10.5 Leopard

こちらのサイトを参考にapacheも再インストール
ソースをダウンロードして解凍した後apacheのディレクトリに移動してインストールを実行

./configure --enable-layout=Darwin --enable-mods-shared=all
make
sudo make install 


apacheを起動した後phpinfo();で確認して
PDO drivers sqlite2, sqlite, mysqlとなっていればOK