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

ブログ アーカイブ

tags