2012/07/15

ActiveResourceかActiveRecordか

Redmineで番組録画チケット管理するために、まず放送番組を自動でチケット化する処理を書かねばならない。RedmineはRubyOnRailsのシステムなので、RailsのActiveResourceでやればいいんだよねって気軽に考えていた。

require 'rubygems'
require 'active_resource'
class Redmine < ActiveResource::Base
    self.site = 'http://localhost'
    self.user = '[login-id]'
self.password = '[password]'
end
class Project < Redmine
end
class Issue < Redmine
end

これだけでチケット(Issue)レコードへ簡単にアクセスできるようになる。
self.site、self.user、self.passwordはRedmine上のアカウント。普通にアクセスして操作するのと同じ事をスクリプトで出来るってことだね。
SQLコマンドを知らなくても変換してくれる便利機能だなので使わない手はないだろうとやってみたが。

project = Project.find(:all)  プロジェクト一覧取得

エラーだよ
/var/lib/gems/1.9.1/gems/activeresource-3.2.6/lib/active_resource/base.rb:929:in `instantiate_collection': undefined method `collect!' for # (NoMethodError)
        from /var/lib/gems/1.9.1/gems/activeresource-3.2.6/lib/active_resource/base.rb:901:in `find_every'
        from /var/lib/gems/1.9.1/gems/activeresource-3.2.6/lib/active_resource/base.rb:813:in `find'
        from project.rb:24:in `
'

ん?なんじゃこれは?
色々調べてみたが、Railsの不具合でもなければRedmineの不具合でもないらしい。
お互いの整合性がちゃんと取れていないのでは?というのが自分の結論だ。

Collection-resources-and-pagination
こちらの記事を読んで、何となくだけど納得した。

回避策?
IssueもProjectと同じエラーがでるので、Issueで説明すると

app/views/issues/index.api.srb ファイルの最初の
api.array :issues, api_meta(:total_count => @issue_count, :offset => @offset, :limit => @limit) do
を
api.array :issues do
に変更してすることで、エラーがなくなった。Projectも同じ対処で回避できた。
collect!を作ればいいんだよとか、Hashの問題だとか、色々あったけど・・・


検索〜
  issues = Issue.find(:all, :conditions => {:project_id => 1})
ん?全然検索できない・・・
issues = Issue.find(:all, :params => {:project_id => 1})
ActiveResourceだと:paramsなんだと。


この辺で、もういいや。ActiveResourceは、使わない事にした。

Railsからちゃんと習得していれば問題ないかもしれないけど、redmineがRailsだったから使ってみようと思ったんで、その辺の基礎知識が乏しい。
ネット検索してみると、ActiveResourceより、ActiveRecordの方が情報が豊富だし。
なにより、redmineのモデル部分はActiveRecordで記述されているんで参考にしやすい。

ということで、DB周りの自動処理はActiveRecordでやることにしたよ。


require 'rubygems'
require 'active_record'

ActiveRecord::Base.establish_connection(
:adapter => 'mysql2',
:host => 'localhost',
:username => 'redmine',
:password => 'redmine',
:database => 'redmine'
)

class Issue < ActiveRecord::Base
end

ActiveRecordだとこんな感じでredmineDBにアクセスできるようになる。
establish_connectionの中は、redmineのconfig/database.ymlに記述したのと同じ内容を書けばいい。

チケット検索は、Issue.find。作成は、Issue.new で簡単に操作できるね。
こっちの方がDBレコードのイメージそのままな感じなんでフィーリングが合ってる。
初心者の私が色々書いてもしょうがないので、この辺の詳しい事は他を参照してね。

まだ初歩的な使い方しか出来ないけど、それでも目的のものは構築できそうだ。
次回からは、構築関係を書いてみる予定。

2012/07/10

Ubuntu12.04LTSにRedmine2.0.3を入れる

地デジ録画システムとしてRedmineを使ってみる(予定)

wavecastやepgrecと同様の構成ではわざわざ自分でやる意味が無い。と言っても、他に頼らずにガリガリ作る時間もない。既存システムを応用してササッと構築できないかな?って感じで進めてみる。

Redmine
いわゆるプロジェクトタスク管理システムなわけですが、チケット使って録画番組管理できないかな?と思ってるわけです。

自分にとってこれを使ってみる別の理由
  • 日頃仕事で使ってるんで馴染んでる(本職じゃないんで詳しくはないけど)
  • RailsやREST-APIの勉強になるかな
  • チケット以外の機能(Wiki/Forumやファイルとか)を便利に使えるかも
Redmineインストール
今のRedmineバージョンは1.4.xと2.0.xに分かれてます。仕事では安定している1.3.xを使っているけど個人なので最新の2.0.3を入れることに。単に新しいの使ってみたいっていうだけ。
詳しいインストール手順は本家「Redmineのインストール」にお任せするとして、ここではポイントだけ書き残しておきます。

ruby1.8.x環境が入っているとじゃまなので、綺麗にパージしておこう。
redmine2.0.3をダウンロードして/opt/redmineに展開(どこでもいいんだけど)。そして、
$ sudo apt-get install ruby1.9.3
$ sudo gem install bundler --no-rdoc --no-ri
$ sudo apt-get install libmysqlclient-dev
$ cd /opt/redmine (インストールした場所に移動)
$ sudo bundle install --without development test postgresql sqlite rmagick
bundleがredmine/Gemfileを読んで必要なパッケージを一気にインストールしてくれる(楽~)

新しすぎるgemパッケージとかが混在してると動かない場合があるんで注意です。
以下が自分のgemパッケージ環境です
actionmailer (3.2.6)
actionpack (3.2.6)
activemodel (3.2.6)
activerecord (3.2.6)
activeresource (3.2.6)
activesupport (3.2.6)
arel (3.0.2)
builder (3.0.0)
bundler (1.1.4)
coderay (1.0.7)
daemon_controller (1.0.0)
erubis (2.7.0)
fastthread (1.0.7)
hike (1.2.1)
i18n (0.6.0)
journey (1.0.4)
json (1.7.3)
mail (2.4.4)
mime-types (1.19)
multi_json (1.3.6)
mysql2 (0.3.11)
net-ldap (0.3.1)
passenger (3.0.13)
polyglot (0.3.3)
prototype-rails (3.2.1)
rack (1.4.1)
rack-cache (1.2)
rack-openid (1.3.1)
rack-ssl (1.3.2)
rack-test (0.6.1)
rails (3.2.6)
railties (3.2.6)
rake (0.9.2.2)
rdoc (3.12)
ruby-openid (2.1.8)
rubyzip (0.9.9)
sprockets (2.4.3, 2.1.3)
thor (0.15.3)
tilt (1.3.3)
treetop (1.4.10)
tzinfo (0.3.33)
sprockets だけ2つのバージョンが入っていますが、2.1.3が入っていればOKなはず。
新しいバージョンの方は、確か後のPassengerを入れた際に入れたような気がする・・・

mysqlのredmineデータベースとアクセスユーザを作成
$ mysql -uroot -p
create database redmine default character set utf8;
grant all on redmine.* to 'redmine'@'localhost' identified by 'redmine';
flush privileges;
exit;

面倒なんで、DB名=ユーザ名=パスワードで作ってしまう。
(仕事だったらちゃんとセキュリティ考えるよ)

conf/database.yml を編集
ruby1.9なんで adapter : mysql2 です。username,passwordはmysqlで作ったやつを設定。

conf/configuration.yml は編集しない。
メールを今回の目的にどう活用できるか思案中なのでまだ用意しない。しなくても動くし。

秘密鍵作成とDBマイグレーション
$ rake generate_secret_token
$ rake db:migrate RAILS_ENV=production
この辺も以前のバージョンに比べたら楽になりました。

$ RAILS_ENV=production rake redmine:load_default_data
でデフォルトデータの登録というステップがありますが、一般的な開発用として使用しないので、読みません。

webrickサーバー起動して動作確認
$ sudo RAILS_ENV=production ruby script/rails server
書き方がドキュメントとちょっと違うかな。でもこれで動く。


Passenger
apache2経由で動かす方が自然というか便利なのでRailsアプリを起動するPassengerモジュールを入れる。
$ apt-get install libapache2-mod-passenger
だと色々古い環境が入ってしまうので、gemで入れることにした。
$ sudo gem install passenger --no-rdoc --no-ri
$ sudo passenger-install-apache2-module
すると親切に色々足りないものを、こうしてインストールしなさいと教えてくれる。
(色々あるけど教えるから安心してっていうメッセージが面白い)
* To install Curl development headers with SSL support:
Please run apt-get install libcurl4-openssl-dev or libcurl4-gnutls-dev, whichever you prefer.
* To install Apache 2 development headers:
Please run apt-get install apache2-prefork-dev as root.
(あとで、preforkじゃなくてworkerにするよ)
* To install Apache Portable Runtime (APR) development headers:
Please run apt-get install libapr1-dev as root.
* To install Apache Portable Runtime Utility (APU) development headers:
Please run apt-get install libaprutil1-dev as root.
みたいな感じで。言うとおりに色々やって
passenger-install-apache2-module を何度か繰り返して環境が整えば、めでたくビルドが開始される

ubuntuのapacheモジュール構成に従って、confとloadファイルを作成する
/etc/apache2/apache2.confに直接書いてもいいだろうけど、ちょっと御行儀よくしてみる。

[/etc/apache2/mods-avilable/passenger.conf]
PassengerRoot /var/lib/gems/1.9.1/gems/passenger-3.0.13
PassengerRuby /usr/bin/ruby1.9.1

(以下の様な最適化設定もあるようだけど、ちゃんと調べてないんで自分はまだ入れない)
# Passengerが追加するHTTPヘッダを削除するための設定(任意)。
#
Header always unset "X-Powered-By"
Header always unset "X-Rack-Cache"
Header always unset "X-Content-Digest"
Header always unset "X-Runtime"
# 必要に応じてPassengerのチューニングのための設定を追加(任意)。
#
PassengerMaxPoolSize 20
PassengerMaxInstancesPerApp 4
PassengerPoolIdleTime 3600
PassengerUseGlobalQueue on
PassengerHighPerformance on
PassengerStatThrottleRate 10
RailsSpawnMethod smart
RailsAppSpawnerIdleTime 86400
RailsFrameworkSpawnerIdleTime 0
[/etc/apache2/mods-avilable/passenger.load]
LoadModule passenger_module /var/lib/gems/1.9.1/gems/passenger-3.0.13/ext/apache2/mod_passenger.so

具体的なパスは自分のビルドされた状態に合わせるべし。

passengerを有効にする
$ sudo a2enmod passenger

ruby1.9.3入れたのに何で1.9.1なんだ?と疑問が残るが今はそういうことらしい。

apache2-mpm-worker
redmineはRonRアプリだし、多分PHP使わないんで、preforkからworkerに切り替え。
$ sudo apt-get install apache2-mpm-worker
ってやるとpreforkとphp5捨てられて、mpm-workerでアパッチが勝手に動く。
みなさんはここから、php5が動くようにするために、色々やるようですが、自分はここまで。

ドキュメントルートをRedmineにする(方法1)
$ sudo cp /etc/apache2/sites-available/default /etc/apache2/sites-available/redmine
デフォルトをコピーして、
DocumentRoot /opt/redmine/public (自分がredmineインストールした場所/public)
と書き換える

$ sudo a2dissite default(デフォルトを外す)
$ sudo a2ensite redmine (redmineを有効にする)

これでファイルの中身を書き換えずに、コマンド操作で切り替えることができて便利。切り替えないけど・・
http://localhost/ でRedmineがドキュメントルートとして稼働する。
今回はこっち。

RailsBaseURIを使う(方法2)
$ sudo ln -s /opt/redmine/public /var/www/redmine
(/var/wwwにredmine/publicへのリンクを貼る)

/etc/apache2/sites-enabled/現在有効なサイトファイルのVirtualHostタグ内に
RailsBaseURI /redmine
って書く。http://localhost/redmine でアクセス出来るようになる。
会社の方では複数のサーバーやアプリが稼働してるのでこっちタイプです。


こんなことを色々やって自分専用の小さいRedmineシステムが稼働。

実際の運用では、ロードするapacheモジュールを最低限にしたり、apache2のworker設定を最適化したり、mysqld設定を最適化したりとSEな作業が延々と続くと思いますが、今必要なことじゃないので次のステップへ。

次は、「番組情報をチケットにする」です。これは大変そうだ。

2012/07/03

Google Driveとgriveとgitリポジトリ

突然「Google-Drive」の話です

サーバーアプリ開発は何処でも出来る。Linux(Ubuntu)、Mac、Windowsどれも使ってるんでクラウドで環境を共有化したくなるのが自然かなと。ということで実際やってみたものの・・・というお話。

Google Drive
DropBoxでも良かったんですが、こちらは妻と別用途で利用中なので怪しいものは入れられないのです。それで、このためにGoogleDriveを利用することにしたわけです。
(GoogleDriveについては、色々親切ページがあるので、そちらを参照してくださいな)

grive
MacとWindowsのクライアントソフトは本家からダウンロードすれば済みましたが、Linux環境がね・・・
で見つけたのが、「grive」です。griveについては、google-drive CLI 'grive'を参考にされるとよいでしょう。自分と同じUbuntu12.04LTSへインストールしておられます。

だけどね・・・
Windows/Macクライアントは今同期して!っていうのが出来ない。行ったり来たりがスピーディに出来ない。まあそういう用途向きじゃないのはわかるけど。逆にgriveは「今!」しかないんで、ついその感覚になってしまう。

バックアップファイル問題
どこでもだいたいEmacsで編集してるんだけれど、Emacsで変更するとバックアップファイルが作られる。というか、今までのものが'~'付きにリネームされるといったほうが正しいか。これのためか、'~'付きのファイルが同期対象になってしまって、最新ファイルが更新されないとか紛失したりとか。ついにはUbuntuからのgriveがパニック起こしたりとか。そうなったら諦めて新しいフォルダで再構築。orz.

Linuxファイルパーミッション問題
Ubuntuでパーミッション設定していても、Windowsで編集して更新してしまうとパーミションが普通のファイルになってしまう。パーミッション情報は保存されないってことなのでしょうね。そういうものなのかな。別のツール使えば大丈夫?

とにかくこのために、#!/usr/bin/pythonって書いてもパーミション設定が保証されないので、スクリプトコマンドではなく、ただのスクリプトファイルとして扱うことにしたわけです。
(最初にこの記事を読まれると、さっぱり意味不明だと思うので、前記事を参照されたし)

griveの操作感覚は自分好みだけど、その他のクライアント環境がイージー過ぎて、思い通りじゃないっす。自分とそういう環境の相性が悪いだけかもしれないけどね。

GoogleDriveはSDKもあるらしいから、不満だったら自分でクライアント作ればいいんだよ。と遠くの方から聞こえてきそうだけど、それはそれ。きっと賢い方が作ってくれているはずさ。自分は世界中の「それ」を探して活用するスキルを高めるのさ。

探してみたところ
Linuxのfuseラッパーとして使えるfuse-google-driveがありました。
https://github.com/jcline/fuse-google-drive

rubyでアクセスするgemパッケージもありますね。
https://github.com/gimite/google-drive-ruby

うーん。どっちも便利だけど開発ソース共有には向かないなぁ。

やっぱりバージョン管理リポジトリでやるか
今回のような目的には、svnやgitでバージョン管理の方が適してる。仕事でなら日頃使っているけど、プライベートだとリポジトリの置き場に困る。
https://sites.google.com/site/repositorylist/ こちらよると、無料で使えるサイトが幾つかあるらしい。
また共有フォルダでイラっときたら、考えようかなと思ったけど、まてよ?
せっかくGoogleDrive使ってるんだったら、そこにリポジトリ構成できないのかな?

「google drive git」で調べてみると、おやおや、できそうじゃないですか。
参照サイトページ
using-google-drive-with-git
how-use-google-drive-or-dropbox-host-your-private-git-repositories
こういう情報が豊富なのが(多少不満があれど)メジャー環境を使うメリット。

手順はだいたいこんな感じ
  • ローカルリポジトリを適当に構築
  • GoogleDriveフォルダ上で共有マスターリポジトリ作成
    • $ git init [repos.dir] --bare
  • ローカルリポジトリへ戻ってリモート設定
    • $ git remote add origin file:///[repos.fullpath]
  • ローカル編集したらコミット ・・・◎
  • 共有リポジトリへプッシュ
  • (Linuxのgriveを実行してサーバー同期)
  • 別環境からのクローン
    • git clone file:///[GoogleDrive.repos.fullpath]
    • git pull
  • 後は◎からと同じ
要はgithubに公開リポジトリ作成するのと大体同じで分散リポジトリでやればいいってことかな。だけどね。grive同期なら即時反映でいけるんだけど、Mac/WindowsのGoogleDriveからだと、マスターリポジトリへプッシュした変更がちゃんとサーバーへ伝わらないっす。

結局
手順が増えた分確実性が増すならいいんだけれど、不確実なところは変わらなかったので、今のところ普通にGoogleDriveのファイル管理のまま使用しております。
もっと、確実性のある即時同期型のシェアフォルダないっすかね。

grive の mac/windows版があれば一番いいんだけれど。