まだコミットしては無いんですが、LokkaのMac用ビルドを作ってみました。Dropboxに置いてあるので、Macをお持ちの方は記をダウンロード・解凍して起動し、http://localhost:9646/ でLokkaが動いてるかどうか試していただけるとありがたいです。

http://dl.dropbox.com/u/188423/Lokka.zip

特にXcodeをインストールしてない方の情報が知りたい!動いた!とか動かねえ!とかあったら@komagataや#lokkacmsにメッセージいただけるとうれしいです。

多分Snow Leopard、あわよくばLeopardで動くかもしれません。

rubygemsを見ていて、ubygems.rbって変なファイルがあるなと思って開いたら・・・

# This file allows for the running of rubygems with a nice
# command line look-and-feel: ruby -rubygems foo.rb

lib/ubygems.rb at from rubygems/rubygems - GitHub

ナイスハックwww

% ls
% GEM_HOME=`pwd` gem list > /dev/null
% ls
cache          doc            gems           specifications

なにそれこわい。

gem environmentとかでも同様。

Snippet

LokkaにSnippet(スニペット)を追加しました。

Snippetとはテンプレート間で共有したい部品を入れておくものです。Pageも同じ用途に使えるのでWordPressではそれが常套手段っぽいですが、@machidaさんが

「PageはURLが存在するので直接アクセスできるのが気持ち悪い」

と言っていたのでSnippetという名前で別に用意しました。

komagata [p0t]

このブログで言えば、右のプロフィールの部分でSnipetを使っています。今まではPageの機能を使っていたので、プロフィール単体がURLを持っているので妙なページが存在することになっていました。

Snippetは好きに名前を付けられるのでテンプレ内では下記のようにかけます。

<%= Snippet.first(:name => 'about').body %>

モデルのユーティリティメソッド

今回、各モデル用にユーティリティメソッドを用意しました。そのユーティリティメソッドとは"そのクラスで一番使いそうなメソッドをクラス名と同名のメソッドとして用意したもの"です。それを使えば上記は下記のように書けます。

<%= Snippet('about').body %>

要はこれです。

Ruby - クラス名と同名の関数にデフォルト動作をさせるパターン - komagata [p0t]

同じように他のモデルにも用意されています。

<h2><%= Page('inquiry').title %></h2>

DataMapperのAPIを使えば何でも取れますが、テンプレートがスッキリするかなと。

S3を触っています。S3に独自のユーザー管理の仕組みを組み込む方法がわからず困ってます。(@junyaさんや@yagi_さんに色々教えてもらいました。ありがとうございます。)

例えば、Webサービスを作ったとして、そのサービスのアカウント毎にS3に領域を作ってファイルにアクセスさせたい場合に、そのサービス経由でファイルをダウンロードしては不必要なトラフィックが発生してしまうのでS3から直接ダウンロードして欲しいハズです。

PROXY的な手法は使えないのでS3自身にユーザーを作成したり、そのユーザー毎に権限を設定したりが可能である必要があります。

S3の認証方法は色々あるんですが、Webサービスのユーザーと同期させるような大量ユーザーを想定のものは無いっぽいです。(もしあればホント教えて欲しいです・・・)

色々な認証方法:

  • Access Credentials
    • Access Keys --- 大量に発行できない
    • X.509 certificates --- エンドユーザーに使わせるのは無理
    • Key Pairs --- エンドユーザーに使わせるのは無理
  • Sign-In Credentials --- AWSユーザー登録必要
  • Multi-Factor Authentication --- セキュリティを高めるためだけ
  • Account Identifiers --- AWSユーザー登録必要。Sign-In Credentialsとどう違うんだ。
  • IAM --- 5000ユーザーまで。

今Preview Beta中のIAM(Identity and Access Management)という仕組みもユーザー数は最大5000となっていて、企業内とか開発者とかのアクセス権限を細かく設定するための仕組みっぽいです。

そこで気になっていたのがHeroku PG Backupsでdumpファイルのダウンロード方法が期限付きのS3のURLになってた仕組みです。ちょっとわかり辛いんですが、"Query String Authentication"とか"Signed URLs"とかでググると出てきます。

require 'aws/s3'

AWS::S3::Base.establish_connection!(
  :access_key_id => 'XXXXXXXXXXXXXX',
  :secret_access_key => 'XXXXXXXXXXXXXXXXXX')
puts AWS::S3::S3Object.url_for(
  'foo.jpg',
  'my-bucket-name',
  :expires_in => 60 * 10)
http://s3.amazonaws.com/my-bucket-name/foo.jpg?AWSAccessKeyId=xxxxxxxx&Expires=1293402048&Signature=xxxxxxxx

aws-s3だとurl_forというメソッドで認証済みのURLが簡単に取得できます。Signatureの生成方法はちゃんと見てないんですが、このオブジェクトだけに通用するSignatureなので前述したような"独自のユーザー管理を使いつつS3から直接ダウンロードさせたい"という場合に使えそうです。

しかし、ダウンロードはこれでいいとしてもアップロードの方はどうすればいいんでしょう。根本的な解決にはなってない気がします。せいぜい、アップロード専用の制限されたアカウントでアップロードして、別アカウントからmoveするぐらいしか思いつきません・・・。

DataMapperを教えておじいさん | Selfkleptomaniacに回答しようとしたら、既に解決されていた・・・。

require 'rubygems'
require 'dm-core'
require 'dm-migrations'

class Repo
  include DataMapper::Resource
  property :id, Serial
  property :body, String
end

DataMapper.logger.set_log STDERR, :debug, "SQL: ", true
DataMapper.setup(:default, 'sqlite::memory:')
Repo.auto_migrate!                                                                                                                                                

puts Repo.all(:body.like => '%hoge%') |
     Repo.all(:body.like => '%fuga%') |
     Repo.all(:body.like => '%piyo%')

結果:

SQL: (0.000045) SELECT sqlite_version(*)
SQL: (0.000082) DROP TABLE IF EXISTS "repos"
SQL: (0.000014) PRAGMA table_info("repos")
SQL: (0.000393) CREATE TABLE "repos" ("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "body" VARCHAR(50))
SQL: (0.000079) SELECT "id", "body" FROM "repos" WHERE ("body" LIKE '%piyo%' OR "body" LIKE '%hoge%' OR "body" LIKE '%fuga%') ORDER BY "id"

検索条件の場合、分かりやすく書くとこういう感じでしょうか。検索条件の論理演算がRubyの演算子で出来るのが面白いですね。しかし恐ろしく遅そうなSQLが。

Lokkaでもしちゃんと検索をやるならばLuceneのRuby版であるFerretdm-ferret-adapterで使うのが楽そうです。datamapperのadapterになってるということはindexの置き場所も何でもいいというフリーダムさ。検索式を解析するFerret::QueryParserが日本語対応してるかわからないので面倒かもしれません。

ロリポップ!のpaperboy&co.様!

さくらのレンタルサーバーのさくらインターネット様!

マネージド共有サーバーのファーストサーバー様!

@Next Style共有サーバーのWADAX様!

共有サーバーShared PlanのCPI様!

共有サーバーのJoe'sウェブホスティング様!


お願いがあります。


CGIではなく、RubyのRackアプリケーションに対応していただけないでしょうか!!


共有サーバーではメモリの制限が難しいなどの理由があるかもしれません。しかし、国内にそんな共有レンタルサーバーがあったらRubyやRailsの普及の大きな原動力となるに違いありません。Rubyistは使わなくてもとりあえず借りるかもしれません。何か僕に手伝えることがあれば何でもやりますので・・・なにとぞ・・・なにとぞ・・・。

月曜日にHeroku-jpの飲み会?に行くのでHerokuネタを。

Herokuを使うには必ず鍵が必要。ちょっと試したいって人には敷居が高いので、使い捨ての鍵作るサービスを作ってみました。

DISPOSABLE KEYS

DISPOSABLE KEYS

GENERATE KEYS押すと、

DISPOSABLE KEYS

鍵が表示される。それぞれ指定の場所に適当なエディタでファイルに保存すればいい。

ソースコード:komagata's disposable-keys at master - GitHub

私有鍵は私有するから安全なのであって、他人に作らせたら意味が無い。あくまで使い捨て用途にどうぞ。1024bit、RSA、パスフレーズ無しで、コード的には下記の2行です。

@private_key = OpenSSL::PKey::RSA.new(1024)
@public_key = @private_key.public_key

標準ライブラリでこんなに簡単に書けるとは知らなかったです・・・。

% irb -rrubygems
>> require 'rack'
=> true
>> Rack::Mime::MIME_TYPES['.csv']
=> "text/csv"

ここにある。

pluginの事を考えるとbeforeが複数回定義されてもちゃんとそれぞれが実行されないと意味が無い。なので試してみた。

komagata's double_before at master - GitHub

require 'rubygems'
require 'sinatra'

before do
@name = 'Masaki'
end

before do
@name += ' Komagata'
end

get '/' do
"Hello, #{@name}"
end
require 'rubygems'
require 'test/unit'
require 'rack/test'
require 'shoulda'
require './double_before'

class DoubleBeforeTest < Test::Unit::TestCase
include Rack::Test::Methods

def app
Sinatra::Application
end

context "Access pages" do
should "show index" do
get '/'
assert_equal 'Hello, Masaki Komagata', last_response.body
end
end
end
% ruby double_before_test.rb 
Loaded suite double_before_test
Started
.
Finished in 0.030489 seconds.

1 tests, 1 assertions, 0 failures, 0 errors

おお、問題無い!これは期待してなかったので嬉しいですゾ!(@ムック)