ふと耳にした気になる曲のタイトルが分からない。
CMであれば検索すればすぐ出てくるし、その場でスマートフォンを取り出せるのであれば
Shazamなどで判別できるかもしれない。
でも後になって、あの時かかってた曲なんだっけな、となることって意外と多いと思う。
Midomi Soundhoundでは鼻歌検索もできるけども、どうやら私は音痴らしい。。
例えばスポーツジムでかかっていた曲を知りたくなった場合、どう調べるか。
まずは有線のサイトにアクセスする。
そして「チャンネル検索」から「気分やお店から探す」をクリックする。
で、次のページの「お店や空間から探す」から「業種=スポーツ/レッスン施設」
「お店や空間を選ぶ=フィットネスクラブ」と選んで検索する。
そうするといくつか検索結果が出てくるのでそれらしいものを選ぶ。
例えば洋楽でアッパーな感じの曲がよくかかっていたので「ホットドライブ洋楽」
あたりじゃないかな、と思えばそれをクリックする。
すると今現在流れている曲が出てくるので「NOW PLAYING専用画面へ」という
リンクをクリックする。
そうすると上に「日時指定」というのがあるので、調べたい曲が流れていたであろう
日時を入力して検索する。
検索結果として指定日時に流れていた曲がずらっと出てくる。
あとは各曲をiTunesなりYouTubeなりで検索しまくるのだ。
こうして私が見つけた曲はこれでした。
2014年10月27日月曜日
2013年8月2日金曜日
RaspberryPi #10 WebカメラをWeb越しに操作してみよう
第8回にてWebカメラからのキャプチャ画像を定期的にDropboxにアップするようにした。cronで10分周期にセットしたけれども、「今のタイミングのキャプチャが欲しい!」ということもある。この場合はどうするか。
自宅のブロードバンドルータに接続したRaspberryPiには当然グローバルIPアドレスなんてセットしていない。ブロードバンドルータから割り当てられたプライベートIPアドレスにネットワーク越しにアクセスする方法は簡単には実現できそうにない。
というわけで方法としてはRaspberryPi側から「なんか指示ありませんか?」と定期的にポーリングをしかける方法しかないのだ。
ここではDropboxのフォルダを10秒周期チェックして、「shot」というフォルダがあるとそのタイミングでキャプチャをアップロードする、という仕様にした。
そのシェルが以下の通り。
#!/bin/bash
while :
do
/home/pi/Dropbox-Uploader/dropbox_uploader.sh list | grep shot
if [ $? -eq 0 ] ; then
fswebcam -d /dev/video0 -p YUYV -D 2 -S 16 -r 640x480 --jpeg 75 /home/pi/shoot.jpg
/home/pi/Dropbox-Uploader/dropbox_uploader.sh upload /home/pi/shoot.jpg /shoot.jpg
/home/pi/Dropbox-Uploader/dropbox_uploader.sh delete /shot/
fi
sleep 10
done
パスやファイル名は適宜読み替えてほしい。
ここでは10秒周期にしているが、最後のsleepを短くすればよりリアルタイムに近い形で反応できるだろう。Dropboxに怒られるかもしれないが。
で、起動時にこれを起動しておいてもらおう。
sudo vi /etc/rc.local
としてrc.localファイルに以下の記述を追加する。尚、ここでは上記作成スクリプトを「manual_shot.sh」としている。
sudo -u pi /home/pi/manual_shot.sh &
sudoでユーザpiとして実行していることに注意。
Dropbox-Uploaderのセットアップ時にDropboxのAppキーなどを設定したが、実行ユーザが異なると再設定が必要になるので、セットアップを実行したユーザで実行する必要がある。
自宅のブロードバンドルータに接続したRaspberryPiには当然グローバルIPアドレスなんてセットしていない。ブロードバンドルータから割り当てられたプライベートIPアドレスにネットワーク越しにアクセスする方法は簡単には実現できそうにない。
というわけで方法としてはRaspberryPi側から「なんか指示ありませんか?」と定期的にポーリングをしかける方法しかないのだ。
ここではDropboxのフォルダを10秒周期チェックして、「shot」というフォルダがあるとそのタイミングでキャプチャをアップロードする、という仕様にした。
そのシェルが以下の通り。
#!/bin/bash
while :
do
/home/pi/Dropbox-Uploader/dropbox_uploader.sh list | grep shot
if [ $? -eq 0 ] ; then
fswebcam -d /dev/video0 -p YUYV -D 2 -S 16 -r 640x480 --jpeg 75 /home/pi/shoot.jpg
/home/pi/Dropbox-Uploader/dropbox_uploader.sh upload /home/pi/shoot.jpg /shoot.jpg
/home/pi/Dropbox-Uploader/dropbox_uploader.sh delete /shot/
fi
sleep 10
done
パスやファイル名は適宜読み替えてほしい。
ここでは10秒周期にしているが、最後のsleepを短くすればよりリアルタイムに近い形で反応できるだろう。Dropboxに怒られるかもしれないが。
で、起動時にこれを起動しておいてもらおう。
sudo vi /etc/rc.local
としてrc.localファイルに以下の記述を追加する。尚、ここでは上記作成スクリプトを「manual_shot.sh」としている。
sudo -u pi /home/pi/manual_shot.sh &
sudoでユーザpiとして実行していることに注意。
Dropbox-Uploaderのセットアップ時にDropboxのAppキーなどを設定したが、実行ユーザが異なると再設定が必要になるので、セットアップを実行したユーザで実行する必要がある。
2013年7月25日木曜日
RaspberryPi #9 シャットダウンボタンをつくろう
RasberryPiは電源供給源のUSBに接続すれば起動する。
そして起動時にデーモンとして起動するように/etc/rc.lodalに以下のような記述を追加する(exit 0の前に追加)。
/home/pi/off_button &
とすれば起動時に先ほどのプログラムがデーモンとして起動するので
いつでもボタンを押せばシャットダウンしてくれるのだ。
終了時はコマンドからshutdownしなくちゃいけない。
イヌ用の監視カメラをこしらえて実家に設置したところで、年老いた両親に
「リモートでログインしてshutdownコマンドを、、、」
などと言えるハズもない。
というわけで押すとシャットダウンしてくれるボタンを付けてみる。
ボタンを長押しして、LEDランプが消えたら電源抜いてOK、というもの。
用意するもの。
- ブレッドボード 1つ
- ジャンパワイヤ 3本
- タクトスイッチ 1つ
- 10KΩ抵抗 1つ
配線は参考図書「RaspberryPiで遊ぼう!」に掲載されているままなので省略。
次にRaspberryPi用のGPIOプログラミングライブラリであるwiringPiをインストールする。こちらも本に掲載のままなので省略。たぶんググればある。
で、以下のようなプログラムを書く。
#include <stdio.h>
#include <wiringPi.h>
#define BTN_PORT 25
int main(void) {
int data = 0;
int cnt = 0;
if(wiringPiSetupGpio() == -1) return 1;
pinMode(BTN_PORT, INPUT);
while(1) {
data = digitalRead(BTN_PORT);
if(data == 0) cnt = 0;
else cnt++;
if(cnt >= 10) {
system("shutdown -h now");
return 0;
}
usleep(300000);
}
return 1;
}
#include <stdio.h>
#include <wiringPi.h>
#define BTN_PORT 25
int main(void) {
int data = 0;
int cnt = 0;
if(wiringPiSetupGpio() == -1) return 1;
pinMode(BTN_PORT, INPUT);
while(1) {
data = digitalRead(BTN_PORT);
if(data == 0) cnt = 0;
else cnt++;
if(cnt >= 10) {
system("shutdown -h now");
return 0;
}
usleep(300000);
}
return 1;
}
300ミリ秒(300000マイクロ秒)ごとにボタンの押下状態をチェックして
10回連続で押された状態(=3秒間の長押し)ならshutdownする、というだけのもの。
これを書いたら
cc -o off_button off_button.c -lwiringPi
としてコンパイルする。
ファイル名は適宜読み替えてください。
これを書いたら
cc -o off_button off_button.c -lwiringPi
としてコンパイルする。
ファイル名は適宜読み替えてください。
そして起動時にデーモンとして起動するように/etc/rc.lodalに以下のような記述を追加する(exit 0の前に追加)。
/home/pi/off_button &
とすれば起動時に先ほどのプログラムがデーモンとして起動するので
いつでもボタンを押せばシャットダウンしてくれるのだ。
2013年6月30日日曜日
RaspberryPi #8 Webカメラで静止画
監視カメラとしてセットして、Ustream経由で外出先からスマホで確認しよう!
と思ったのだけどスマホのUstreamが尋常じゃない重さで使えない。
というわけで静止画を定期的にキャプチャしてドロップボックスに定期的にアップロードする、という作戦にするのだ。
静止画のキャプチャにはfswebcamを使う。
設定方法など、こちらを参考にしました。
一方、DropboxはというとARM版がないのでDropbox-Uploaderというツールを使う。
こちらを参考にしました。
次にfswebcamでキャプチャして、Dropbox-Uploaderでアップロードするスクリプトを用意する。
#!/bin/bash
fswebcam -d /dev/video0 -p YUYV -D 2 -S 16 -r 640x480 --jpeg 75 ./capture.jpg
Dropbox-Uploader/dropbox_uploader.sh upload capture.jpg /capture.jpg
パスの部分は適宜読み替えてください。
このスクリプトだとDropboxにアップロードするたびにcapture.jpgを上書きすることになるので、それが嫌な場合は連番を振るとか、時刻にするとかしないといけない。
最後にcronをセットする。
*/10 * * * * /home/pi/capture.sh
capture.shというのが先ほどつくったシェルだ。
ここでは10分おきに動くようにしている。
と思ったのだけどスマホのUstreamが尋常じゃない重さで使えない。
というわけで静止画を定期的にキャプチャしてドロップボックスに定期的にアップロードする、という作戦にするのだ。
静止画のキャプチャにはfswebcamを使う。
設定方法など、こちらを参考にしました。
一方、DropboxはというとARM版がないのでDropbox-Uploaderというツールを使う。
こちらを参考にしました。
次にfswebcamでキャプチャして、Dropbox-Uploaderでアップロードするスクリプトを用意する。
#!/bin/bash
fswebcam -d /dev/video0 -p YUYV -D 2 -S 16 -r 640x480 --jpeg 75 ./capture.jpg
Dropbox-Uploader/dropbox_uploader.sh upload capture.jpg /capture.jpg
パスの部分は適宜読み替えてください。
このスクリプトだとDropboxにアップロードするたびにcapture.jpgを上書きすることになるので、それが嫌な場合は連番を振るとか、時刻にするとかしないといけない。
最後にcronをセットする。
*/10 * * * * /home/pi/capture.sh
capture.shというのが先ほどつくったシェルだ。
ここでは10分おきに動くようにしている。
2013年6月25日火曜日
RaspberryPi #7 Firefox OSの画面を大きくしてみる
昨日、RaspberryPi上でFirefoxOSが動作したものの
画面の左下にチョロッと出ているだけなので大きくしてみましょう。
起動時に
上の方、はみだしてるけど。
こちらは1366x768を指定した場合。
このサイズにするとマウスポインタがダニのような大きさで操作が困難なのだ。
昨日は参考サイトの情報をたどっただけだったので、そもそも何をしたんだ?
というところを把握していなかったので自分なりに調べてみる。
まず「b2g」というのはFirefoxOSの別名で「boot to gecko」のコト。
最初にダウンロードしたのがB2GのデスクトップクライアントをRaspberryPi向けにビルドしたもの。
たぶん。
これだけでも起動はするのだけど空のスクリーンが表示される。
なのでシステムアプリの指定やら何やら必要で(こちらの「プロファイルを生成する」を参照)、それも一緒にダウンロードして起動時に指定してました。
昨日は全て出来合いのものをダウンロードしただけだったけど、
一般的には(まだ開発中ということもあり)ソースをダウンロードして自分でコンパイルするものみたい。
いずれ、そちらもチャレンジしてみるのだ。
画面の左下にチョロッと出ているだけなので大きくしてみましょう。
起動時に
--screen=と指定してやれば画面サイズを変更できる。x
上の方、はみだしてるけど。
こちらは1366x768を指定した場合。
このサイズにするとマウスポインタがダニのような大きさで操作が困難なのだ。
昨日は参考サイトの情報をたどっただけだったので、そもそも何をしたんだ?
というところを把握していなかったので自分なりに調べてみる。
まず「b2g」というのはFirefoxOSの別名で「boot to gecko」のコト。
最初にダウンロードしたのがB2GのデスクトップクライアントをRaspberryPi向けにビルドしたもの。
たぶん。
これだけでも起動はするのだけど空のスクリーンが表示される。
なのでシステムアプリの指定やら何やら必要で(こちらの「プロファイルを生成する」を参照)、それも一緒にダウンロードして起動時に指定してました。
昨日は全て出来合いのものをダウンロードしただけだったけど、
一般的には(まだ開発中ということもあり)ソースをダウンロードして自分でコンパイルするものみたい。
いずれ、そちらもチャレンジしてみるのだ。
2013年6月24日月曜日
RaspberryPi#6 firefox osを入れてみる
下記サイトの情報を参考にRaspberryPiでFirefoxOSを動かしてみようと思ったのだ。
http://www.philipp-wagner.com/ffos-for-rpi/manual/index.html
手元のMacのディスク容量が怪しいのでコンパイルはせずにビルド済みのイメージファイルをSDカードに書き込んでみた。
んが、動かない。
電源を入れてもウンともスンとも言わない。
むむぅ
さくっと諦めてこちらの情報を参考にすることにする。
こちらの手順はまずは普通にRaspbianのSDカードで起動して、FirefoxOSをダウンロードしてきて動かそう、というもの。
こんな感じになります。
http://www.philipp-wagner.com/ffos-for-rpi/manual/index.html
手元のMacのディスク容量が怪しいのでコンパイルはせずにビルド済みのイメージファイルをSDカードに書き込んでみた。
んが、動かない。
電源を入れてもウンともスンとも言わない。
むむぅ
さくっと諦めてこちらの情報を参考にすることにする。
こちらの手順はまずは普通にRaspbianのSDカードで起動して、FirefoxOSをダウンロードしてきて動かそう、というもの。
こんな感じになります。
2013年6月21日金曜日
RaspberryPi#5 Webカメラ接続
カメラが届いたので繋いでみる。
ちなみに買ったのはELECOM UCAM-DLA200H。
RaspberryPiを起動してUSBカメラを差し込む。
/var/log/messageを見て認識していることを確認。
本の通りに「uvccapture」「uvcdynctrl」「guvcview」をインストール。
sudo apt-get install uvccapture uvcdynctrl guvcview
Xをたちあげてメニューから先ほどインストールしたguvcviewを起動する。
しばらくするとカメラの映像が表示される。
感動。
USTREAMへの配信も一瞬できたけれど、しばらくすると落ちてしまう。
消費電力の関係かもしれない。
セルフパワーのUSBハブを買わないといけないのか。。
ちなみに買ったのはELECOM UCAM-DLA200H。
RaspberryPiを起動してUSBカメラを差し込む。
/var/log/messageを見て認識していることを確認。
本の通りに「uvccapture」「uvcdynctrl」「guvcview」をインストール。
sudo apt-get install uvccapture uvcdynctrl guvcview
Xをたちあげてメニューから先ほどインストールしたguvcviewを起動する。
しばらくするとカメラの映像が表示される。
感動。
USTREAMへの配信も一瞬できたけれど、しばらくすると落ちてしまう。
消費電力の関係かもしれない。
セルフパワーのUSBハブを買わないといけないのか。。
2013年6月19日水曜日
RaspberryPi #4 DLNA
今日も本に沿って1章だけ。
DLNAサーバをRaspberryPiにインストールして、DLNAクライアントのiPhoneアプリをインストールしてアクセスする。
昨日テレビで見た動画をiPhoneで見る。
ちょっと嬉しい。
RaspberryPiでカメラを使いたいのだけど、公式のカメラはちょっと高いし、届くのに時間がかかりそうなので、書籍内で動いたと書いてある「UCAM-DLA200H」を注文。
1500円くらい。
部屋にまた新たなAmazonのダンボールが増える。。
DLNAサーバをRaspberryPiにインストールして、DLNAクライアントのiPhoneアプリをインストールしてアクセスする。
昨日テレビで見た動画をiPhoneで見る。
ちょっと嬉しい。
RaspberryPiでカメラを使いたいのだけど、公式のカメラはちょっと高いし、届くのに時間がかかりそうなので、書籍内で動いたと書いてある「UCAM-DLA200H」を注文。
1500円くらい。
部屋にまた新たなAmazonのダンボールが増える。。
2013年6月18日火曜日
RaspberryPi #3 ネットワークと動画再生
今日も本に沿ってRaspberryPiを触る。
Macからsshで入ったり、ファイル送ったり。
結局のところLinuxなので普通に出来そうなことはできてしまう。
動画はomxplayerというプレーヤが最初から入っているのでこれを使って再生する。
HDMIケーブルでテレビとつないでいるので、小さなRaspberryPiからキレイな映像をテレビで再生している姿はなかなか感動的。
今日はこれだけ。
Macからsshで入ったり、ファイル送ったり。
結局のところLinuxなので普通に出来そうなことはできてしまう。
動画はomxplayerというプレーヤが最初から入っているのでこれを使って再生する。
HDMIケーブルでテレビとつないでいるので、小さなRaspberryPiからキレイな映像をテレビで再生している姿はなかなか感動的。
今日はこれだけ。
2013年6月14日金曜日
RaspberryPi#2 起動する
SDカードリーダーが届いた。
参考書は「Raspberry Piで遊ぼう!」です。
本に書いてあるとおり下記アドレスに置いてある「RPi-sd card builder」を使って書き込む。
http://alltheware.wordpress.com/2012/12/11/easiest-way-sd-card-setup/
ちゃんとSDカード挿しているのに「挿してますか?」みたいなメッセージが出るので疑問だけれども、よく読むと「挿してなかったら挿してね」というメッセージなので「continue」を押していけば大丈夫。
書き込み先を選ぶときにPCのドライブにまでチェックがついているので気をつけて、SDカードのみにチェックが入っているようにする。
書き込みを終えたらSDカードをRasberryPiに差し込んで、HDMIケーブルをつないで、マウスとキーボードをつないで、電源をONする(コンセントに差す)。
どうやら書籍が書かれた時期とバージョンが変わっているようでメニューが違っているのでちょっと戸惑うのだけど、Overscanやsshは「8 Advanced Options」に、日本語関係は「4 Internationalisation Options」にある。
ここではSDカードの使用領域拡張、ロケールの設定、SSHを有効化(デフォルトでなっているような気がする)した。
これでリブートするとコマンドラインのLinuxが起動する。
参考書は「Raspberry Piで遊ぼう!」です。
本に書いてあるとおり下記アドレスに置いてある「RPi-sd card builder」を使って書き込む。
http://alltheware.wordpress.com/2012/12/11/easiest-way-sd-card-setup/
ちゃんとSDカード挿しているのに「挿してますか?」みたいなメッセージが出るので疑問だけれども、よく読むと「挿してなかったら挿してね」というメッセージなので「continue」を押していけば大丈夫。
書き込み先を選ぶときにPCのドライブにまでチェックがついているので気をつけて、SDカードのみにチェックが入っているようにする。
書き込みを終えたらSDカードをRasberryPiに差し込んで、HDMIケーブルをつないで、マウスとキーボードをつないで、電源をONする(コンセントに差す)。
どうやら書籍が書かれた時期とバージョンが変わっているようでメニューが違っているのでちょっと戸惑うのだけど、Overscanやsshは「8 Advanced Options」に、日本語関係は「4 Internationalisation Options」にある。
ここではSDカードの使用領域拡張、ロケールの設定、SSHを有効化(デフォルトでなっているような気がする)した。
これでリブートするとコマンドラインのLinuxが起動する。
RaspberryPiを買ったのだ
ふとRasberryPiを買ってみた。
参考書もついでに買った。
SDカードも必要だそうだから買った。
16GBのclass10。
電源はKindleに付属していたマイクロUSB経由でiPhoneの充電器に差し込めばいけるんじゃないだろうか。
とりあえずランプはついた。
HDMIケーブルはプレステにつないであるものを使おう。
USBマウスはある。
キーボードがない。
ノートPCしかない。
だから買おう。
公式サイトのダウンロードページからRasberry用のディストリビューションである
Raspbian Wheezyをダウンロードする。
http://www.raspberrypi.org/downloads
これをSDカードに書き込めばOK。
SDカードリーダーが無かった。。
参考書もついでに買った。
SDカードも必要だそうだから買った。
16GBのclass10。
電源はKindleに付属していたマイクロUSB経由でiPhoneの充電器に差し込めばいけるんじゃないだろうか。
とりあえずランプはついた。
HDMIケーブルはプレステにつないであるものを使おう。
USBマウスはある。
キーボードがない。
ノートPCしかない。
だから買おう。
公式サイトのダウンロードページからRasberry用のディストリビューションである
Raspbian Wheezyをダウンロードする。
http://www.raspberrypi.org/downloads
これをSDカードに書き込めばOK。
SDカードリーダーが無かった。。
2012年1月17日火曜日
rubyの諸々が最新になっている環境にRedmineとBacklogを入れてみる
CentOSに入っているrubyは古いのでさくっとアップデートしたのです。
railsも最新をインストールしてやりましたよ。
その後でredmineを入れたやろうと、でも困った。
redmineはもうrails3に対応する気はないらしい。
でもRedmineを動かすだけなら難しくない。
BitNamiにアクセスしてDownloadを選択してRedmineを選ぶとbitnami~.installer.binというファイルがダウンロードされる。
railsも最新をインストールしてやりましたよ。
その後でredmineを入れたやろうと、でも困った。
redmineはもうrails3に対応する気はないらしい。
でもRedmineを動かすだけなら難しくない。
BitNamiにアクセスしてDownloadを選択してRedmineを選ぶとbitnami~.installer.binというファイルがダウンロードされる。
これに実行権をあたえて動かせばOK。
/opt/redmine-x.x.x(xはバージョン)ができるので移動します。
そこで./ctlscript.sh start として「localhost:8080」にアクセスしてやれば動く。
ポート番号はインストール時に指定した値で。
で注意しなくちゃいけないのはプラグインのインストール。
ここではBacklogをインストールするケースなのだけど、まずはさきの
/opt/redmineインストール先/apps/redmine/vendor に移動します。
ここでBacklogの手順にしたがい、gitで落としてgemやrakeなど必要なコマンドを
打っていくのだけど、ここで使うgemやrakeは全てこのRedmineのパッケージの中のものを利用すること。
つまり
「/opt/redmine-x.x.x/ruby/bin/gem」を使わないと失敗します。
ハマります。
rakeも同様。
ここさせ間違えなければうまく行きます。
たぶん。
2012年1月15日日曜日
CentOSにDropboxを入れたらyumが動かない
なぜだ!?
なにをやっても
http://linux.dropbox.com/fedora/6/repodata/repomd.xml: [Errno 14] PYCURL ERROR 22 - "The requested URL returned error: 404"
なんて怒られる。
というわけで「/etc/yum.repos.d/」以下をしてみる。
-rw-r--r--. 1 root root 1926 12月 9 12:05 2011 CentOS-Base.repo
-rw-r--r--. 1 root root 637 12月 9 12:05 2011 CentOS-Debuginfo.repo
-rw-r--r--. 1 root root 626 12月 9 12:05 2011 CentOS-Media.repo
-rw-r--r--. 1 root root 145 1月 12 23:34 2012 dropbox.repo
-rw-r--r--. 1 root root 116 1月 14 09:59 2012 google-chrome.repo
-rw-r--r--. 1 root root 258 1月 14 01:03 2012 home:sawaa.repo
-rw-r--r--. 1 root root 739 11月 13 12:55 2010 mirrors-rpmforge
-rw-r--r--. 1 root root 717 11月 13 12:55 2010 mirrors-rpmforge-extras
-rw-r--r--. 1 root root 728 11月 13 12:55 2010 mirrors-rpmforge-testing
-rw-r--r--. 1 root root 1113 11月 13 12:55 2010 rpmforge.repo
ropboxが悪さしているようなので、この「dropbox.repo」をどこかに避けてやりました。
そしたらyumがちゃんと動くようになりましたとさ。。
なにをやっても
http://linux.dropbox.com/fedora/6/repodata/repomd.xml: [Errno 14] PYCURL ERROR 22 - "The requested URL returned error: 404"
なんて怒られる。
というわけで「/etc/yum.repos.d/」以下をしてみる。
-rw-r--r--. 1 root root 1926 12月 9 12:05 2011 CentOS-Base.repo
-rw-r--r--. 1 root root 637 12月 9 12:05 2011 CentOS-Debuginfo.repo
-rw-r--r--. 1 root root 626 12月 9 12:05 2011 CentOS-Media.repo
-rw-r--r--. 1 root root 145 1月 12 23:34 2012 dropbox.repo
-rw-r--r--. 1 root root 116 1月 14 09:59 2012 google-chrome.repo
-rw-r--r--. 1 root root 258 1月 14 01:03 2012 home:sawaa.repo
-rw-r--r--. 1 root root 739 11月 13 12:55 2010 mirrors-rpmforge
-rw-r--r--. 1 root root 717 11月 13 12:55 2010 mirrors-rpmforge-extras
-rw-r--r--. 1 root root 728 11月 13 12:55 2010 mirrors-rpmforge-testing
-rw-r--r--. 1 root root 1113 11月 13 12:55 2010 rpmforge.repo
ropboxが悪さしているようなので、この「dropbox.repo」をどこかに避けてやりました。
そしたらyumがちゃんと動くようになりましたとさ。。
2011年12月27日火曜日
Railsのソースを読んでみる#4 modelの生成部分
今回みるのはrailtiesの「rails/commands.rb」なのだ。
これは受け取ったコマンドに応じたcase文がつらつらと続いているのだけれど、
まずは「rails g model User name:string email:string」とした場合を想定してみましょう。
コマンドにg(generate)を指定した場合はcommands.rbの28行目の
28 require "rails/commands/#{command}"
が実行されて「rails/commands/generate」が読み込まれます。
で、そのgenerate.rbの中身が以下の通り。
1 require 'rails/generators'
2 require 'active_support/core_ext/object/inclusion'
3
4 Rails::Generators.configure!
5
6 if ARGV.first.in?([nil, "-h", "--help"])
7 Rails::Generators.help 'generate'
8 exit
9 end
10
11 name = ARGV.shift
12 Rails::Generators.invoke name, ARGV, :behavior => :invoke, :destination_root => Rails.root
これだけ。
先の例で言うと11行目で変数nameに「model」が格納された状態で
Rails::Generators.invoke が呼び出されています。
そのメソッドの在処は1つ上の階層の「rails/generators.rb」です。
164 def self.invoke(namespace, args=ARGV, config={})
165 names = namespace.to_s.split(':')
166 if klass = find_by_namespace(names.pop, names.any? && names.join(':'))
167 args << "--help" if args.empty? && klass.arguments.any? { |a| a.required? }
168 klass.start(args, config)
169 else
170 puts "Could not find generator #{namespace}."
171 end
172 end
166行目でfind_by_namespace("model")で呼び出します。
この呼び出しの結果、「Rails::Generators::ModelGenerator」が帰ってきます。
というわけで168行目にて「Rails::Generators::ModelGenerator」のstartを呼んでいます。
このstartメソッドはどこにあるのだろうか、というわけで「rails console」を立ち上げて聞いてみましょう。
require 'rails/generators'
require 'rails/generators/rails/model/model_generators'
Rails::Generators::ModelGenerator.ancestors
上記を実行するとこんな結果が返ってきます。
[Rails::Generators::ModelGenerator, Rails::Generators::NamedBase, Rails::Generators::Base, Rails::Generators::Actions, Thor::Actions, Thor::Group, Thor::Shell, Thor::Invocation, Thor::Base, Object, PP::ObjectMixin, ActiveSupport::Dependencies::Loadable, JSON::Ext::Generator::GeneratorMethods::Object, Kernel, BasicObject]
今いるrailtiesの中ではgrepしても該当のstartメソッドが無さそうなので「Thor」と呼ばれるモジュールにありそうです。
そもそも「Thor」とは何ぞや。
次回はそこら辺りを調べてみましょう。
これは受け取ったコマンドに応じたcase文がつらつらと続いているのだけれど、
まずは「rails g model User name:string email:string」とした場合を想定してみましょう。
コマンドにg(generate)を指定した場合はcommands.rbの28行目の
28 require "rails/commands/#{command}"
が実行されて「rails/commands/generate」が読み込まれます。
で、そのgenerate.rbの中身が以下の通り。
1 require 'rails/generators'
2 require 'active_support/core_ext/object/inclusion'
3
4 Rails::Generators.configure!
5
6 if ARGV.first.in?([nil, "-h", "--help"])
7 Rails::Generators.help 'generate'
8 exit
9 end
10
11 name = ARGV.shift
12 Rails::Generators.invoke name, ARGV, :behavior => :invoke, :destination_root => Rails.root
これだけ。
先の例で言うと11行目で変数nameに「model」が格納された状態で
Rails::Generators.invoke が呼び出されています。
そのメソッドの在処は1つ上の階層の「rails/generators.rb」です。
164 def self.invoke(namespace, args=ARGV, config={})
165 names = namespace.to_s.split(':')
166 if klass = find_by_namespace(names.pop, names.any? && names.join(':'))
167 args << "--help" if args.empty? && klass.arguments.any? { |a| a.required? }
168 klass.start(args, config)
169 else
170 puts "Could not find generator #{namespace}."
171 end
172 end
166行目でfind_by_namespace("model")で呼び出します。
この呼び出しの結果、「Rails::Generators::ModelGenerator」が帰ってきます。
というわけで168行目にて「Rails::Generators::ModelGenerator」のstartを呼んでいます。
このstartメソッドはどこにあるのだろうか、というわけで「rails console」を立ち上げて聞いてみましょう。
require 'rails/generators'
require 'rails/generators/rails/model/model_generators'
Rails::Generators::ModelGenerator.ancestors
上記を実行するとこんな結果が返ってきます。
[Rails::Generators::ModelGenerator, Rails::Generators::NamedBase, Rails::Generators::Base, Rails::Generators::Actions, Thor::Actions, Thor::Group, Thor::Shell, Thor::Invocation, Thor::Base, Object, PP::ObjectMixin, ActiveSupport::Dependencies::Loadable, JSON::Ext::Generator::GeneratorMethods::Object, Kernel, BasicObject]
今いるrailtiesの中ではgrepしても該当のstartメソッドが無さそうなので「Thor」と呼ばれるモジュールにありそうです。
そもそも「Thor」とは何ぞや。
次回はそこら辺りを調べてみましょう。
2011年12月17日土曜日
Railsのソースを読んでみる#3 もう1つのrails
今回は「rails new ****」として出来たディレクトリの「アプリ名/script/rails」を見て行きましょう。
ちなみちRails3.1.3です。
1 #!/usr/bin/env ruby
2 # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3 APP_PATH = File.expand_path('../../config/application', __FILE__)
4 require File.expand_path('../../config/boot', __FILE__)
5 require 'rails/commands'
3行目では「アプリ名/config/application」というパスをAPP_PATHに格納しています。
そして「アプリ名/config/boot.rb」を読み込み、「rails/commands」(こちらはrailtieの方)を読み込んでいます。
まずは「boot.rb」
1 require 'rubygems'
2
3 # Set up gems listed in the Gemfile.
4 ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
5
6 require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
ここでは環境変数「BUNDLE_GEMFILE」に「アプリ名/Gemfile」を格納しています。
そして「bundler/setup」を読み込みます。
ここでやっているのはファイル名から分かるとうりGemfileで定義した各種モジュールを読み込んでいます。
bundler/setup.rb にて「Bundler.setup」をコールします。これは1つうえの階層の「bundler.rb」にあります。
こちらを読んでいきましょう。
101 def setup(*groups)
102 # Just return if all groups are already loaded
103 return @setup if defined?(@setup)
104
105 if groups.empty?
106 # Load all groups, but only once
107 @setup = load.setup
108 else
109 @completed_groups ||= []
110 # Figure out which groups haven't been loaded yet
111 unloaded = groups - @completed_groups
112 # Record groups that are now loaded
113 @completed_groups = groups
114 # Load any groups that are not yet loaded
115 unloaded.any? ? load.setup(*unloaded) : load
116 end
117 end
この時点ではgroupsは指定しないし@setupも空なので107行目が実行されます。
loadというのはRuntimeクラスのインスタンスを返してくるメソッドで、そのsetupメソッドを呼んでいます。
そのRuntimeというのはどっから来るんだ、というと同ファイルのもっと上の方にあります。
18 autoload :Definition, 'bundler/definition'
19 autoload :Dependency, 'bundler/dependency'
20 autoload :Dsl, 'bundler/dsl'
21 autoload :Environment, 'bundler/environment'
22 autoload :GemHelper, 'bundler/gem_helper'
23 autoload :Graph, 'bundler/graph'
24 autoload :Index, 'bundler/index'
25 autoload :Installer, 'bundler/installer'
26 autoload :LazySpecification, 'bundler/lazy_specification'
27 autoload :LockfileParser, 'bundler/lockfile_parser'
28 autoload :RemoteSpecification, 'bundler/remote_specification'
29 autoload :Resolver, 'bundler/resolver'
30 autoload :Runtime, 'bundler/runtime'
31 autoload :Settings, 'bundler/settings'
32 autoload :SharedHelpers, 'bundler/shared_helpers'
33 autoload :SpecSet, 'bundler/spec_set'
34 autoload :Source, 'bundler/source'
35 autoload :Specification, 'bundler/shared_helpers'
36 autoload :UI, 'bundler/ui'
autoloadというのは最初の引数に指定した名前を参照したタイミングでrequireするメソッドです。
なので「Runtime.new」とされた時点で30行目の「bundler/runtime」が読み込まれます。
この中ではGemfileで指定しているファイルを順次ロードしているだけなので詳細はパス。
「rails/commands」の方は次回見てみるのだ。
ちなみちRails3.1.3です。
1 #!/usr/bin/env ruby
2 # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3 APP_PATH = File.expand_path('../../config/application', __FILE__)
4 require File.expand_path('../../config/boot', __FILE__)
5 require 'rails/commands'
3行目では「アプリ名/config/application」というパスをAPP_PATHに格納しています。
そして「アプリ名/config/boot.rb」を読み込み、「rails/commands」(こちらはrailtieの方)を読み込んでいます。
まずは「boot.rb」
1 require 'rubygems'
2
3 # Set up gems listed in the Gemfile.
4 ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
5
6 require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
ここでは環境変数「BUNDLE_GEMFILE」に「アプリ名/Gemfile」を格納しています。
そして「bundler/setup」を読み込みます。
ここでやっているのはファイル名から分かるとうりGemfileで定義した各種モジュールを読み込んでいます。
bundler/setup.rb にて「Bundler.setup」をコールします。これは1つうえの階層の「bundler.rb」にあります。
こちらを読んでいきましょう。
101 def setup(*groups)
102 # Just return if all groups are already loaded
103 return @setup if defined?(@setup)
104
105 if groups.empty?
106 # Load all groups, but only once
107 @setup = load.setup
108 else
109 @completed_groups ||= []
110 # Figure out which groups haven't been loaded yet
111 unloaded = groups - @completed_groups
112 # Record groups that are now loaded
113 @completed_groups = groups
114 # Load any groups that are not yet loaded
115 unloaded.any? ? load.setup(*unloaded) : load
116 end
117 end
この時点ではgroupsは指定しないし@setupも空なので107行目が実行されます。
loadというのはRuntimeクラスのインスタンスを返してくるメソッドで、そのsetupメソッドを呼んでいます。
そのRuntimeというのはどっから来るんだ、というと同ファイルのもっと上の方にあります。
18 autoload :Definition, 'bundler/definition'
19 autoload :Dependency, 'bundler/dependency'
20 autoload :Dsl, 'bundler/dsl'
21 autoload :Environment, 'bundler/environment'
22 autoload :GemHelper, 'bundler/gem_helper'
23 autoload :Graph, 'bundler/graph'
24 autoload :Index, 'bundler/index'
25 autoload :Installer, 'bundler/installer'
26 autoload :LazySpecification, 'bundler/lazy_specification'
27 autoload :LockfileParser, 'bundler/lockfile_parser'
28 autoload :RemoteSpecification, 'bundler/remote_specification'
29 autoload :Resolver, 'bundler/resolver'
30 autoload :Runtime, 'bundler/runtime'
31 autoload :Settings, 'bundler/settings'
32 autoload :SharedHelpers, 'bundler/shared_helpers'
33 autoload :SpecSet, 'bundler/spec_set'
34 autoload :Source, 'bundler/source'
35 autoload :Specification, 'bundler/shared_helpers'
36 autoload :UI, 'bundler/ui'
autoloadというのは最初の引数に指定した名前を参照したタイミングでrequireするメソッドです。
なので「Runtime.new」とされた時点で30行目の「bundler/runtime」が読み込まれます。
この中ではGemfileで指定しているファイルを順次ロードしているだけなので詳細はパス。
「rails/commands」の方は次回見てみるのだ。
2011年12月11日日曜日
Railsのソースを読んでみる#2 railtie入り口
今回からはrailsのコアである「railties」のソースを追いかけてみるのだ。
「railties-3.1.0/lib/rails/cli.rb」を追いかける。
まず「rbconfig」と「rails/script_rails_loader」を読み込んでいます。
6行目では「script/rails」が存在すれば、つまり「rails new」でアプリケーションを生成した状態で
実行した場合はそちらのrailsコマンドを実行します。
8,9行目ではrailsを動かせるrubyのバージョンであるかチェックしています。
11行目以降では「rails plugin」と指定した場合は「rails/commands/plugin_new」を、
それ以外は「application/commands/application」を読み込んでいます。
「rails plugin new Hoge」とすればプラグイン開発用の雛形が生成されるのだ。
11行目以降の部分はrailsアプリを新たに作成する場合に実行されるコードです。
そちらはちょっとパスするとして、生成したあとの「script/rails」を読んでいきましょう。
それは次回。
「railties-3.1.0/lib/rails/cli.rb」を追いかける。
1 require 'rbconfig'
2 require 'rails/script_rails_loader'
3
4 # If we are inside a Rails application this method performs an exec and thus
5 # the rest of this script is not run.
6 Rails::ScriptRailsLoader.exec_script_rails!
7
8 require 'rails/ruby_version_check'
9 Signal.trap("INT") { puts; exit(1) }
10
11 if ARGV.first == 'plugin'
12 ARGV.shift
13 require 'rails/commands/plugin_new'
14 else
15 require 'rails/commands/application'
16 end
まず「rbconfig」と「rails/script_rails_loader」を読み込んでいます。
6行目では「script/rails」が存在すれば、つまり「rails new」でアプリケーションを生成した状態で
実行した場合はそちらのrailsコマンドを実行します。
8,9行目ではrailsを動かせるrubyのバージョンであるかチェックしています。
11行目以降では「rails plugin」と指定した場合は「rails/commands/plugin_new」を、
それ以外は「application/commands/application」を読み込んでいます。
「rails plugin new Hoge」とすればプラグイン開発用の雛形が生成されるのだ。
11行目以降の部分はrailsアプリを新たに作成する場合に実行されるコードです。
そちらはちょっとパスするとして、生成したあとの「script/rails」を読んでいきましょう。
それは次回。
2011年12月9日金曜日
Railsのソースを読んでみる#1 railsコマンド
「メタプログラミングRuby」という書籍を読んだのだけど、一刻も早く実践しなければ全力で記憶から消え去りそうな気配がありすぎるので何かつくろうと思ったのだけど何も思い浮かばないのでRailsのソースでも見てみようか、と思い立ったのだ。
Linuxカーネルのソース読書を数年前に断念した前科があるけれど、いいの。
今回は最初から全部読む気ないから。
ピックアップ的に気になるところを読んでみよう。
Railsのソースは普通にインストールすれば
/usr/lib/ruby/gems/1.8/gems
にある(Macの場合)。
上記はRuby1.8の例なので適宜読み替えてください。
でもrvmなんかを使っていると場所が変わっているので、rvmで目的のverに切り替えてから「which rails」とすれば実行パスが出てくるので、その周辺にたぶんあります。
私の例では以下のパスでした。
~/.rvm/gems/ruby-1.9.2-p290/gems
でもどっから見たらいいのかよう分からん。
とりあえずrailsのはbinディレクトリしかないのでとりあえずrailsコマンドの中身を見てみる。
3行目では「gems」に「.git」があるか確認しています。
あれば「XXX/gems/railties/lib」をrailties_pathに格納します。
「$:」はロードパスを示す組み込み変数で「$LOAD_PATH」としても同じです。
5行目ではそのロードパスの先頭にrailties_pathを挿入しています。
7行目では「railities/lib/rails/cli.rb」を読み込んでいます。
要するに「railties/lib/rails/cli.rb」を読んでいるだけなんだけど、最初に「.git」の有無をチェックしているのはなぜだろう。
存在した場合だけロードパスにrailtiesのパスを先頭に追加している。
ググってみても分からん。
とりあえず課題として置いておこう。
とにもかくにもここから分かるのはRailsの一番核になっているのが
railtieだということ。
ここら辺りで予習しておくと良いでしょう。
Linuxカーネルのソース読書を数年前に断念した前科があるけれど、いいの。
今回は最初から全部読む気ないから。
ピックアップ的に気になるところを読んでみよう。
Railsのソースは普通にインストールすれば
/usr/lib/ruby/gems/1.8/gems
にある(Macの場合)。
上記はRuby1.8の例なので適宜読み替えてください。
でもrvmなんかを使っていると場所が変わっているので、rvmで目的のverに切り替えてから「which rails」とすれば実行パスが出てくるので、その周辺にたぶんあります。
私の例では以下のパスでした。
~/.rvm/gems/ruby-1.9.2-p290/gems
でもどっから見たらいいのかよう分からん。
とりあえずrailsのはbinディレクトリしかないのでとりあえずrailsコマンドの中身を見てみる。
1 #!/usr/bin/env ruby
2
3 if File.exists?(File.join(File.expand_path('../..', __FILE__), '.git'))
4 railties_path = File.expand_path('../../railties/lib', __FILE__)
5 $:.unshift(railties_path)
6 end
7 require "rails/cli"
3行目では「gems」に「.git」があるか確認しています。
あれば「XXX/gems/railties/lib」をrailties_pathに格納します。
「$:」はロードパスを示す組み込み変数で「$LOAD_PATH」としても同じです。
5行目ではそのロードパスの先頭にrailties_pathを挿入しています。
7行目では「railities/lib/rails/cli.rb」を読み込んでいます。
要するに「railties/lib/rails/cli.rb」を読んでいるだけなんだけど、最初に「.git」の有無をチェックしているのはなぜだろう。
存在した場合だけロードパスにrailtiesのパスを先頭に追加している。
ググってみても分からん。
とりあえず課題として置いておこう。
とにもかくにもここから分かるのはRailsの一番核になっているのが
railtieだということ。
ここら辺りで予習しておくと良いでしょう。
2011年12月1日木曜日
[ruby]includeとextend
Rubyにおけるincludeとextendの違いは言葉で言われてもピンと来ないので実際に試した方が早いのね。
irbで試しましょう。
とりあえずこんなモジュールを用意します。
module Adef hello"hello"endend
そして使ってみます。まずはinclude。
class Binclude Aendtest = B.newtest.hello => #"hello"B.hello => #"NoMethodError"
次にextend。
class Cextend AendC.hello => #"hello"test = C.newtest.hello => #"NoMethodError"test.extend(A)test.hello => #"hello"
つまりincludeはインスタンスメソッドを差し込むのに対して、extendは特異メソッドを挿入するかたちになります。
だからクラス定義の中でextendすると、クラスの特異メソッド=クラスメソッドになります。
2011年11月17日木曜日
[Rails]OmniAuthの使い方
RailsでOAuthを使うにはOmniAuthが簡単で便利。
というわけで使ってみよう。
gem 'omniauth'
とGemfileに追記して、bundle installします。
「config/initializers/omniauth.rb」というファイルが出来ているので
以下のように編集します。
Rails.application.config.middleware.use OmniAuth::Builder doprovider :XXX, "Consumerキー", "Consumerシークレット"end
「XXX」の部分やOAuthを使って利用したいサービスを指定します。
例):twitter, :facebook, :githubなど
Consumerキーやシークレットはそれぞれのサービスで取得したキーやシークレットの値を指定します。
これをそのままハードコーディングしてしまうのは問題なので一般的には以下のように指定します。
例)provider :twitter, ENV['TWITTER_KEY'], ENV['TWITTER_SECRET']
環境変数からとってくるようにします。
環境変数の指定は各OSの手順に従えばよいですが、heroku上で利用する場合は以下のコマンドを使います。
heroku config:add TWITTER_KEY="XXXXXX"
これで「ENV["TWITTER_KEY"]」とすれば「XXXXX」が取得できます。
2011年10月29日土曜日
[こんなん作ってみました]Otaku Yellow Page
Ruby on Railsを使って何かつくってみたいな、と思って
「Otaku Yellow Page」なるものをつくってみました。
いろいろいじってみてください。
ソースコードは全てGitHubにあげています。
Rails3.1のサンプルコードとしてチェックしてみてください。
RSpecごとぶっこんでます。
ツッコミどころがあれば教えてくださいね。
推しメンを登録して、推しカブリを検索できるサービスです。
とりあえずTwitterとmixiとAmebaに対応しました(プロフィールにリンクするのみ)。
主に使っているのは以下のものです。
・Ruby1.9.2
・Ruby on Rails 3.1.0
・Haml
・SCSS (ほとんど使えてない、、、)
・RSpec2.6.4
・Capybara
・Bootstrap, from Twitter
本当はOmniAuthを使ってTwttier, mixi, Amebaと連携したかったのだけれどmixiとAmebaのAPIではあまり思ったことがやれなさそうだったので使わずにイエローページという位置づけにしてみました。
登録:
投稿 (Atom)
