Redmine: db:migrate時のbundle pkgエラー時の対処例
先日、自鯖のRedmineを公式のUpgrade手順を参考にSubversion経由でソースをupdate後にDBのマイグレーションを実施したところ下記のエラーが発生。
先日、自鯖のRedmineを公式のUpgrade手順を参考にSubversion経由でソースをupdate後にDBのマイグレーションを実施したところ下記のエラーが発生。
2011頃にさくらVPSに構築したRedmine v1.x.xをRedmine v2.3.x系にアップグレードしようと試みたが、DBのマイグレーションが手間なのと、Subversionからのソースコードダウンロードだと今後のupdateがかなり効率化できる為、この際再インストールする事にした。対象環境はCentOS v5.9だが作業中に幾つか引っかかったところがあるので、今後の備忘録も兼ねて下記に纏めておく。尚、作業に際しては原則下記の公式ブログに記載の手法で進めていく。 参考:Redmine 2.3をCentOS 6.4にインストールする手順 | Redmine.JP Blog 以降はそれ以外の作業や作業中のエラー、留意点、対処法など。
ほったらかしにしていたとある自鯖のRedmineのアップグレードに際し、Ruby 1.9系のビルドに必要なlibyamlをyumでインストールする為にEPELリポジトリを追加しようとしたら下記のエラーが発生。尚、epel-releaseパッケージのURLは以下のページより確認。
よくよく確認したら対象OSバージョンがv5.9だった。。
# rpm -Uvh
を取得中
警告: /var/tmp/rpm-xfer.0lmNQv: ヘッダ V3 RSA/SHA256 signature: NOKEY, key ID 0608b895
エラー: 依存性の欠如:
rpmlib(FileDigests) <= 4.6.0-1 は epel-release-6-8.noarch に必要とされています
rpmlib(PayloadIsXz) <= 5.2-1 は epel-release-6-8.noarch に必要とされています
# cat /etc/redhat-release
CentOS release 5.9 (Final)
v5.x系のパッケージをインストールするのも何だし、先ずはOSをv6.x系にUpgradeするかな。いや、v5.x系からv6.x系へのアップグレードはコマンドではなくOSの再インストール推奨されていることを考えると、一先ず、v5.x系でlibyamlをインストールする。
# vi/etc/yum.repos.d/epel.repo ← v5系のリポジトリ追加
# yum install --enablerepo=epel libyaml libyaml-devel
後はRuby v1.9.3のインストール作業となる。
# curl -O ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-p448.tar.gz
# tar zxvf ruby-1.9.3-p448.tar.gz
# cd ruby-1.9.3-p448
# ./configure --disable-install-doc
# make
# make install
# ruby -v
ruby 1.9.3p448 (2013-06-27 revision 41675) [x86_64-linux]
Linux(ここではCentOS)にプロジェクト管理ソフトウェアであるRedmine 1.2.2とバージョン管理システムであるSubversionのインストール方法と設定例を以下に紹介。想定としては、WebサーバやDB以外は何も設定されていないサーバ環境を対象とした手順。すでにインストールしているものや設定済みのものは適時読み飛ばし下さい。 ※参考サイトは記事の末尾をご参照。
RubyのコードをJavaに書き直す際に注意する相違点が幾つかあったので、そのうちの一つを挙げてみます。特に文字列関係は色々やりにくいです。
a = "4321"
p a[4] #=> nil
Rubyでは文字を[]で指すとき終端文字の次の添え字を指すとnilを返します。これをCで言う文字列の終端文字'\0'のように考え、if文などの判定に用いることが出来ます。
対して、Javaで同じような書式で書こうものなら、
public class Test {
public static void main(String[] args) {
String str = "abcdef";
char[] arr = str.toCharArray(); // String型をchar型の配列に変換
System.out.println(arr);
System.out.println(str.length()+ " == " + arr.length);
try {
System.out.println(arr[6]);
} catch (java.lang.ArrayIndexOutOfBoundsException e) {
System.out.println("キャッチ:" + e);
- }
try {
System.out.println(str.charAt(6));
} catch (java.lang.StringIndexOutOfBoundsException e) {
System.out.println("キャッチ:" + e);
}
// 最後の文字を知るためには
System.out.println(str.charAt(str.length() - 1));
}
}
のように例外でキャッチしなければなりません。
6 == 6
abcdef
キャッチ:java.lang.ArrayIndexOutOfBoundsException: 6
キャッチ:java.lang.StringIndexOutOfBoundsException: String index out of range: 6
f
まぁ、str.length()を用いて文字列長でcharAtで指す文字が文字列の末尾かどうかを判定することで制御すればよいまでの話かもしれません。
今回はとあるアルゴリズムを移植上、気づきが色々あったのでこうした機会に言語仕様に対する理解を深めていきたいです。
単一のWebページから抜き出した複数の要素を配列に格納して返します。 以下の例はaタグの要素(エレメント)を抽出した場合です。
require 'net/http'
require 'kconv'
def parse_array(string, beg_tag, close_tag)
array = Array.new
string.scan(/#{beg_tag}(.*?)#{close_tag}/sm) { |matched|
#puts matched
array = array | matched
}
return array
end
Net::HTTP.version_1_2
Net::HTTP.start('b.hatena.ne.jp', 80) {|http|
response = http.get('/hotentry/')
str = Kconv.tosjis(response.body)
a_tag_array = parse_array(str, "" )
puts a_tag_array
}
Web サーバからドキュメントを得る - Rubyist Magazine - 標準添付ライブラリ紹介 【第 7 回】 net/http
ライブラリを使えば簡単ですが、正規表現の学習の為に。
def return_between(unporsed, start, termi)
unporsed =~ /#{start}(.*?)#{termi}/
return $1
end
str = "<title>Trump Code</title>"
start = "<title>"
termi = "</title>"
puts return_between(str, start, termi)
#=> Trump Code
ここで学んだことは、正規表現の規則中に変数を用いる際は#{var_str}と表記すること。
しかし、未完です。
Webの巡回などにはWWW::Mechanizeという便利なライブラリがありますが、あえてnet/httpのPOSTメソッドを使う理由は、単にPOSTそのものと正規表現の学習をするためです。
今回は正規表現で試行錯誤。
#!/usr/bin/ruby
require 'net/http'
require 'kconv'
before = "hello"
http = Net::HTTP.new('www.excite.co.jp')
response = http.post('/world/english', "before=#{before}&wb_lp=ENJA")
result = Kconv.tosjis(response.body)
result =~ /"after"[^>]*>(.*)/ism
puts $1
こんにちは
<中略>
ここで、正規表現
/"after"[^>]*>(.*)/ism
の部分を
/"after"[^>]*>(.*)< \/textarea>/ism
に変更するとマッチしなくなってしまいました。
オプション指定のmで複数行にマッチするはずなんですが・・・うーん、何を見落としているのだろう。
引数に設定値を与え、それによって挙動を変えることで、似た機能をまとめてみます。
追記(2008.2.8):正規表現のマッチを保持する変数があったことを失念していました。「$`」マッチした部分より前の文字列、「$&」マッチした文字列、「$'」マッチした部分より後ろの文字列を使えばより簡潔に書けると思いました。
EXCL = true
INCL = false
BEFORE = true
AFTER = false
#
# string 分割する文字列
# delineator 分割する場所
# desired BEFORE: delineator 文字列より前の文字列
# AFTER: delineator 文字列より後の文字列
# type INCL: 分割文字列に delineator を加える
# EXCL: 分割文字列に delineator を加えない
def split_str(string, delineator, desired, type)
low_str = string.downcase # 小文字に揃える(変換)
marker = delineator.downcase
return if (low_str.index(marker) == nil) # delineator に一致しない
if (desired == BEFORE)
if (type == EXCL)
split_pos = low_str.index(marker)
else
split_pos = low_str.index(marker) + marker.length
end
parsed_str = low_str[0, split_pos]
else
if (type == EXCL)
split_pos = low_str.index(marker)+marker.length
else
split_pos = low_str.index(marker)
end
parsed_str = low_str[split_pos, string.length]
end
return parsed_str
end
string = "I'm designing a Web crawler and a Search engine."
p split_str(string, "crawler", BEFORE, INCL);
p split_str(string, "crawler", BEFORE, EXCL);
p split_str(string, "crawler", AFTER, INCL);
p split_str(string, "crawler", AFTER, EXCL);
p split_str(string, "crauler", AFTER, EXCL);
"i'm designing a web crawler"
"i'm designing a web "
"crawler and a search engine."
" and a search engine."
nil
str = "A Web crawler"
p str[6, str.size] #=> "crawler"
ブロックの使い方を練習してみます。
def repeat(n)
n.times { yield } if block_given?
end
repeat(2) { puts "Hello." }
# Hello.
# Hello.
メソッドに渡したブロックはyieldを用いて呼び出します。 似たような例としてもう一つ。
# nからmまでの自然数の合計を求める
def sumup(n, m, sum=0)
(n..m).each { |x|
# yield でブロックを呼び出す
yield if block_given? # 引数にブロックが与えられている
puts x
sum += x
}
puts "Sum : #{sum}"
end
sumup(2, 4) { printf "Add : " }
#Add : 2
#Add : 3
#Add : 4
#Sum : 9
渡されたブロックはProcオブジェクトに変換されるのでcallを用いて呼び出すことも出来ます。下の例で確認してみます。
# nからmまでの自然数の合計を求める
def sumup(n, m, &block)
sum = 0
(n..m).each { |x|
block.call if block # ブロックを呼び出し
puts x
sum += x
}
puts "Sum : #{sum}"
end
sumup(0, 4) { printf "Add : " }
#Add : 0
#Add : 1
#Add : 2
#Add : 3
#Add : 4
#Sum : 10
最後に、渡されたブロックをまた引数として渡す場合の例を示します。 その際、ブロック変数名の前に「&」をつけます。
# 配列内の最小値を求める
def minimum(arr, &block)
block ? arr.select(&block).min : arr.min
end
arr = [20,48,15,67]
p minimum(arr) {|i| i > 30}
#=> 48