アスペクト指向エディタ

投稿者 nanki 2006-01-23 06:33:00 GMT

アスペクト指向という言葉が世に出て久しい。

ある程度大きいシステムはファイルやクラス階層といったような一次元的な分け方では分類することのできない、多次元的な構造を持っている。

最近では、Eclipseなどがでてきて、Javaでは持ち前のきっちりさを生かして、コード中を縦横無尽に多次元的に歩き回るということが可能になっている。

Rubyじゃ言語仕様的にほぼ無理と絶望視されているので、これは非常に羨ましい。

代わりといっては何だけれども、grep のお世話になっている。

しかし、grepの結果は見るだけ。 結果のうちこれとこれは変更したいとなれば、ファイルを一個一個編集するしかない。

これは面倒だ。

というのでgrepのラッパみたいなのをrubyで書いてみた。

$ ./grepedit class app/models/* -r

とかやると、該当するコードの周辺を各ファイルから切り取ってエディタが起動する。 変更して保存すると、各ファイルに変更が適用されるというもの。 上記の場合は、association の設定をまとめて書ける。

まだ使う場面に出会ってないので、どれほど役に立つのかわからないが、悪くはないはず。

マジシャンが投げたカードのAだけを剣で貫くように、コードを編集してやる。フッフォッフォッ。

というか、手当たりしだいにファイルを書き換えるので、誤動作が怖くて使えない & 公開できないぞ?・・・


vim/rubyのための部分最適化

投稿者 nanki 2006-01-21 19:06:00 GMT

この辺 を読んで思い出した。

数年前、Javaコードのメトリクス(というか、文字別タイプ量)を調べた時、もっとも多かったのは;と()だった。

考えてみれば、このセミコロン、ほとんどすべての行末に現れて、しかも、ほぼ100% ;+Enter の形で出現、右小指を二回連続消耗するというあり得ないほど無駄にタイピングの苦痛を増やしている奴なのだ。いくらStrong Typingと言ったって・・・

当時はvimでJavaのコードを書いていたので、早速;を;+Enter に置き換え、なんとか快適な環境を作ることに成功したのだった。

その時の経験からか、あまりタイピングが苦痛にならないruby でも、次のような部分的な最適化をしている。

  • ; で改行
  • 文字列中の;では反応しない
  • end も自動で改行
  • begin,else,then,ensureなどの予約語で改行
  • rails 向けに、Ctrl+=,Ctrl+eでerbのタグ
" ~/.vimrc
au BufNewFile,BufRead *.rhtml setf eruby

autocmd FileType html imap <buffer> <C-_> <%=  %><Esc>2hi
autocmd FileType html imap <buffer> <C-E> <%  %><Esc>2hi
autocmd FileType ruby imap <buffer> <C-L> RAILS_DEFAULT_LOGGER.debug()<Esc>i

function SmartSemicolon()
  let s = synIDattr(synID(line("."),col("."),0),"name")
  if s == "rubyString"
    execute "normal a \<Esc>vr;"
  else
    execute "normal a\<Enter> \<BS>"
  endif
endfunction

function SmartEnd()
  let s = synIDattr(synID(line("."),col("."),0),"name")
  if s == "" || s == "rubyNoDoBlock"
    execute "normal ae\<Esc>and\<Enter> \<BS>"
  else
    execute "normal ae\<Esc>and"
  endif
endfunction

autocmd FileType ruby imap <buffer> begin begin<Enter>
autocmd FileType ruby imap <buffer> end  <Esc>:call SmartEnd()<CR>a
autocmd FileType ruby imap <buffer> then then<Enter>
autocmd FileType ruby imap <buffer> ensure ensure<Enter>
autocmd FileType ruby imap <buffer> else else<Enter>
autocmd FileType ruby inoremap <buffer> ; <Esc>:call SmartSemicolon()<CR>a

コード補完も含めコーディング時の最適化というのは、タイプ量当たりの情報量をいかに増やすかというところにある。

コード中に頻出するパターンを見つけ出して、一つずつつぶしていくのが、部分最適化が好きな人間にはたまらない。

次にやるとしたら「閉じるキー」。 begin-end,(),{},||,”“,” などを区別せず、閉じるキーを押すと一番近くの括弧を閉じてくれる、というやつ。 スペース近くの使わないキーに割り当ててやりたい。

誰か作りませんか?or既にある奴をご存知ないですか?


DRUM

投稿者 nanki 2006-01-19 05:58:00 GMT

ちょっと前から注目のプロジェクト、DRUM が徐々にその姿を現し始めた。

DRUMは、現在、Ruby/Java/C#での開発が進められている、多言語対応の分散オブジェクトブローカー。 ネットワークの向こうのオブジェクトに透過的にアクセスできる仕組み。

個人的には、3Dに凝ってた時代があるので、LookingGlassのAPIをたたくデモが興味深い。

全く本質的じゃないところに興味を持ってしまって後ろめたいのだが。

irbで「光あれ」とかやると光源ができたりするんだろうな。いいなぁそれ。

今度のRuby勉強会でデモが見られそう!

なんだかうれしくなって、気がついたらドラムができてた・・・。

drum

参考:

航海日誌


Rails Plugins...

投稿者 nanki 2006-01-14 22:10:00 GMT

ユーザ認証をプラグインを使って作ろうと思ったんだけど、

$ script/plugin list

すると、たくさんでてきてどれが何やらさっぱり。 そこでまとめてみた。

認証系

account_location
  • アカウント毎にサブドメインがあるような、スコープ付の認証に。
acts_as_authenticated
  • script/generate authenticated user account で認証機能が作れる
  • メール認証を使ったアクティベーションも作れる
  • generator を使うので、既存のクラスに機能追加するのはできない?
login_engine
  • # in config/environment.rb
    module LoginEngine
    config :salt, "your-salt-here"
    end
    Engines.start :login
    という感じで設定を記述する
  • engines というplugin に依存している
  • rake engine_migrate ENGINE=login でDBのスキーマを変更できる。
  • メール認証も余裕で対応!
user_engine
  • login_engine をさらに拡張する形で、role ベースの認証を組み込める。
  • Engines.start :login
    Engines.start :user
    login_engineより後じゃなきゃダメ。
ssl_requirement
  • include SslRequirement
    ssl_required :signup 
    とすると、signup が実行される時は、ssl にリダイレクトされる。
security_extensions
  • verify_form_posts_have_security_token を使うと、postされた値が正当なものかどうかチェックできる。
  • secure_form_tag を使ってform の中にsession id をハッシュしたトークンを埋め込んでおいて、セッション中の値と比較する、という仕組み。
  • 元ネタはこちら
sentry
  • 指定したフィールド(主にpassword)の値を暗号化してくれる
  • 暗号化の方式は、いくつか選べるようだ。

View系

browser_filters
  • UnicodeContentType: text/html; charset=utf-8 の設定を自動で
  • SafariUnicodeFix: SafariでAjaxを使う時の問題を回避
  • LinkPrefetchingBlock: Google Web Accerator などがリンクを先読みするのをブロック
labeled_form_helper
  • <label>タグのalias
  • <% formfor :person, @person, :url => { :action => "update" } do |f| %>
    First name: <%= f.textfield :first_name %>
    <% end %>
    と書くとFirst name: をラベルに変換してくれる
restifarian
  • Rails をRESTful にしてくれるらしい
  • RailsのモデルにアクセスするためのRESTfulな?URL形式をRoutesで定義しているだけみたい
    • /models/:action -> コレクションに対する操作
    • /model -> 新規作成
    • /model/:id -> エンティティを表示
    • /model/:id/:action -> エンティティに対する操作 といった感じで、ModelsControllerにマッピングしてくれる。
scriptaculous_slider
  • <%= sliderstylesheet %>
    <%= sliderfield :object, :method, :range => 1..10 %>
    とやると、スライダーができる。
localization
  • 多言語対応用
  • <%=_ ‘yes’ %> のように参照
  • 単数/複数にも対応できる
css_graphs
  • ドキュメントは無い
  • 棒グラフが生成できる
  • 一ページに付き一個という制限
asset_timestamping
  • この画像、ブラウザにキャッシュされては困る、というときに使う
  • image_tag('smiley.jpg')
    => <img src="/images/smiley.jpg?1129811151" /> 
    と展開される。
javascript_generator_templates
  • RJS Templates として知られるものと同じ
  • サーバ側でJavascriptを動的に生成、ブラウザに実行させることができる
us_states
  • アメリカ51州のセレクトボックス。
  • 残念ながら日本は含まれていないので、あまり用途はない。
wiki_engine
  • rails_engineでこんなこともできるんだぞ!という例。
  • production品質ではありません、と書かれている
date_slider
  • Flashを使ったデータ表示コンポーネント
  • かっこいいデモムービー
  • Flash/JavaScript間の通信ライブラリを使っているので、Railsから動作をいじれる
head-helper
  • doctype,stylesheet,script,metaなど、<head>の中で使いそうなものを集めました。
enhanced-form-tag-helper
  • formのinput系のタグに、id,class属性が自動的に付加されるようになる
liquid
  • template engineをerbからliquidに変更
  • .rhtml -> .liquid
  • .rhtml と混在可能
  • {{ item.name }} みたいな記法
  • {{ item.name | upcase }} のように、パイプのような表現で出力フィルタをかけられるのが特徴的
  • フォーマット付きテキストを多様するような場合は、記述がシンプルになってよさそう
rails_pdf
  • PDFWriterを使ってPDFが出力できるようになる。
  • テンプレートは.rpdf 中身はrubyのコード
upload_progress
  • アップロードの進み具合を表すバーを作る。
  • requirements
  • コントローラに
    uploadstatusfor  :create
    という感じの記述を加えると、:createアクションでプログレスバーが使えるようになる。

開発系

continuous_builder
  • 最新のリビジョンでのテストの結果をメールで送信してくれる
  • 時間がかかるようなものや、複数のアプリケーションにまたがるような変更をしたときなどに便利そう?
  • Continuous integrationを実現するためのものらしい
exception_notification
  • include ExceptionNotifiable すると、例外が発生したときに然るべき所にメールを送信してくれる
ar_fixtures
  • テスト用のfixturesを今あるデータベースから生成してくれる?
engines
  • ほにゃらら_engine の親分
refactor
  • model,controllerのpublic methodに対するtest stubを自動生成してくれる。
  • rake findunusedviews
    で使われてないview 見つけてくれる。
assert_accessible
javascript-packaging
  • 複数のJavaScriptのソースファイルを実行時にひとつにまとめてくれる
  • 開発時はばらばらなので、見通しがよくなる
  • まだあんまりテストされてない
migrate_ext
  • rake migrate に機能を付加
    • rake current_schema # 現在のバージョン番号を表示
    • rake migrate_ext VERSION=-1 # 一つ前に戻す

ActiveRecord 拡張

acts_as_taggable
  • モデルがタグ漬けに。
  • taggable.tag_with(“frog animal”)
acts_as_versioned
  • モデルがバージョニングに対応しちゃう
  • page = Page.create(:title => 'hello world!')
    page.version       # => 1
    page.title = 'hello world'
    page.save
    page.version       # => 2
    page.title         # => 'hello world'
    page.revert_to(1)
    page.title         # => 'hello world!'
    こんな感じ。
deadlock_retry
  • ActiveRecordが、デッドロックで失敗したトランザクションを自動的にリトライするようになる
  • コードの変更は必要ない
  • 今のところMySQLでのみテスト
acts_as_paranoid
  • paranoid とは偏執狂のこと
  • 削除する時に削除フラグ(ちょと違うけど)を使うようになる
  • 忘れてしまいがちなフラグの指定も、普通にfind するだけで勝手に付く
  • find_with_deleted で削除されたものも検索対象に
calculations
  • group by を使った構文が書ける
  • User.calculate(:count) といった感じ
  • たぶん、:max, :min などもあるだろうな。
  • Order.calculate(:sum, :cost).group_by(:country).having { |sum| sum > 50 }
    SELECT country, SUM(cost) FROM orders GROUP BY country HAVING SUM(cost) > 50
    になる!?
guid
  • class MyModel < ActiveRecord::Base
    usesguid
    ...
    とすると、ID(デフォルト)フィールドに22文字の、URLに使っても大丈夫なGUIDが生成されるようになる。
  • システムの中でuniqueってことだよな。
where
  • findの検索条件をキレイに書ける
  • Model.findwithconditions(:all) do
    year '>', 2005
    name 'like', 'Foo%'
    end
    こんな感じ。
  • 条件をCondクラスのインスタンスに保存しておけば、cond.where をActiveRecord::Base#find の条件として使える。
count_limit_associations
  • Model.count にて、:include を指定した場合でも、Modelの数が数えられる(普通はjoinによって行が増える)
  • paginate でも:include が使えるように
  • Rails本体に取り込まれるかも(pending patch)
  • 1.13.2には取り込まれてない。

その他

numeric_spell
  • 23.spell => ‘twenty-three’ とできるようになる
  • 当たり前のように単数/複数に対応
referenced_page_caching
  • Railsのページキャッシングを拡張して、1:Post といった名前で参照できるようになっている
  • 削除するときにスコープがわかりやすい?
foo_with_install
  • 騙された!?中身ないじゃん

宿題

とりあえず、script/plugin list のは無くなった。ふぅ。

参考:

Plugins in Ruby on Rails え、まだこんなにあるの!?

こっちも。 rails2u SVN Nowhere Near SVN

actsasferret

datebox_engine


コード自動生成

投稿者 nanki 2006-01-02 18:55:00 GMT

ごくまれに、クリックしてみたくなるGoogle広告があって、クリックしてみると、結構面白かったりする。

今回は、Excel で定義したデータファイルをD&Dするだけで、JavaのWebアプリケーションができあがってしまうというソフト。

デモムービーなんて、ステータスバーが進んでいくのを見るだけ。

暇をみて、Rails版を作ってみようか。

参考:

JasmineSoft Harvest


Hough変換

投稿者 nanki 2005-12-30 07:11:00 GMT

画像から直線っぽいところを検出する手法。

画像上のある点(x,y)を通る直線は無数にあり、

y = a * x + b

を満たす a,b の集合が得られるが、この(x,y)→(a,b)への変換がHough変換。(他にもsin,cosを使った表記法はあるけど本質は同じだろう)

xy平面上の一点はHough変換により、a,b上では直線となる。 この変換を、全ての点(直線の候補点)について行い、a,b平面上で積算する。

ところで、Hough平面(ていうのかな?)上の一点はxy平面ではある直線を表すので、ある直線上の点が多ければ、Hough平面上のある点における積算値は高い値を示すはず。

なので、Hough平面上の積算値の高い点を、直線っぽい、とみなしてxy平面上の直線に戻してあげる、という仕組み。

円の場合も同様に処理できるが、こちらはパラメータの数が多いので、積算する空間が三次元になってしまう。

参考:

CodeZine:Hough変換による画像からの直線や円の検出


MSNP

投稿者 nanki 2005-12-30 06:55:00 GMT

IMをフロントエンドにして何かできないか、と思ったのでJabber,Gaimあたりを調べてみた。 その途中で、rubyでMSNPを実装したものを発見。 これが太い脇道だった。

最近、検索によくひっかかる、ゼロベース有限会社の人が書いたもののようだ。

使ってみたが、なかなか使いやすい。

require 'msnm'

#class TestSessionHandler
#...(snip)...
#class TestSessionHandlerFactory
#...(snip)...

begin
  msnm = Net::InstantMessaging::MSNMessenger.new(
           '***@hotmail.com','***', 
           TestSessionHandlerFactory.new )
  msnm.ns.synchronize
  msnm.listen
ensure
  msnm.ns.offline
  msnm.logout
end

SessionHandler と、それを生成するFactory をセットで実装して、MSNMessenger.new するだけでよい。

肝心の応用の方だけど、ピンとくる使い方はまだ思いつかない。

参考:

IMボット用Rubyスクリプト

MSNPiki


svk

投稿者 nanki 2005-12-27 00:22:00 GMT

先日、subversion で外部リポジトリのプロジェクトをローカルで管理する方法として、svn merge を使った無理矢理な方法で解決してみたが、やはり無理があるらしく、svn://とhttps:// のような違うスキーマに対応できなかったり、追加されたファイルの扱いで面倒なことになったり、とにかく大変だった。

そこへ、直球そのままのソフトウェアを発見。

$ apt-cache search svk
svk - A Distributed Version Control System

Subversion ファイルシステムを使って、リモートのリポジトリをローカルにミラーしたり、それに修正を加えたり、おまけに、svn log とかも高速になるとか。

使ってみようかな。

svk


flex2 & actionscript3(2)

投稿者 nanki 2005-12-05 18:07:00 GMT
particle = new Particle();
particle.mixin(Grabbable);

とやると、掴んで動かせるような再利用可能なライブラリを書いてみた。

まともにECMAScriptを触るのは初めてだが、ActionScript はclass{} 記法も使えるし、動的に拡張できるので、ruby のような言語を使ってれば、悩むことはあまりない。(と思う)


flex2 & actionscript3

投稿者 nanki 2005-12-03 12:10:00 GMT

ActionScript で全てを記述する世界はどんなものなのかと、ちょっと触ってみた。

Eclipse3.1 にプラグインが入らなかったのでスタンドアロン版を起動する。

簡単なテストコードみたいなのを書いて実行する。

package {
  import flash.display.MovieClip;
  import flash.display.Sprite;

  public class actionscript extends MovieClip {
    public function actionscript() {
      for(var i = 2;i < 10; i++){
        var particle:Particle = new Particle();
        addChild(particle);
      }
    }
  }

  private class Particle extends Sprite{
    public function Particle(){
      x = Math.random() * 100;
      y = Math.random() * 100;
      this.graphics.beginFill(0xffffff,0.5);
      this.graphics.drawCircle(0,0,8);
      this.graphics.endFill();
    }
  }
}

こんな感じで、半透明の丸がちらほら表示される。

ちょっとはまったのは、Particle Classをpublic にすると、自動でインスタンスが生成されてしまい、意図した動作にならなかったこと。

自分で生成をコントロールする場合はprivate にしましょう、ということらしい。ふーん。