Browse Tag: ruby

OSX で mysql5.6 環境下で mysql/mysql2 gem のインストールエラーがでた

OSX で mysql5.6 環境下で mysql/mysql2 gem のインストールエラーがでた。


Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension.

/Users/.../bin/ruby extconf.rb --with-mysql-config=/usr/lo
cal/mysql/bin/mysql_config
checking for mysql_ssl_set()... no
checking for rb_str_set_len()... no
checking for rb_thread_start_timer()... no
checking for mysql.h... no
checking for mysql/mysql.h... no
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers. Check the mkmf.log file for more
details. You may need configuration options.

Provided configuration options:
--with-opt-dir
--without-opt-dir
--with-opt-include
--without-opt-include=${opt-dir}/include
--with-opt-lib
--without-opt-lib=${opt-dir}/lib
--with-make-prog
--without-make-prog
--srcdir=.
--curdir
--ruby=/Users/.../bin/ruby
--with-mysql-config

Gem files will remain installed in /Users/.../gems/mysql-2.9.1 for i
nspection.
Results logged to /Users/.../gems/mysql-2.9.1/ext/mysql_api/gem_make
.out

もちろん、事前に mysql_config はちゃんと設定している。

$ bundle config build.mysql --with-mysql-config=/usr/local/mysql/bin/mysql_config
$ bundle config build.mysql2 --with-mysql-config=/usr/local/mysql/bin/mysql_config

結論とすると、/usr/local/mysql/bin/mysql_config を次のように直せば良い。

--- /usr/local/mysql/bin/mysql_config-org 2013-08-13 11:52:25.000000000 +0900
+++ /usr/local/mysql/bin/mysql_config 2013-08-13 11:52:57.000000000 +0900
@@ -116,8 +116,8 @@
embedded_libs=" $ldflags -L$pkglibdir -lmysqld "
embedded_libs="$embedded_libs "

-cflags="-I$pkgincludedir -Wall -Wno-null-conversion -Wno-unused-private-field -Os -g -fno-strict-aliasing -DDBUG_OFF -arch x86_64 " #note: end space!
-cxxflags="-I$pkgincludedir -Wall -Wno-null-conversion -Wno-unused-private-field -Os -g -fno-strict-aliasing -DDBUG_OFF -arch x86_64 " #note: end space!
+cflags="-I$pkgincludedir -Wall -Os -g -fno-strict-aliasing -DDBUG_OFF -arch x86_64 " #note: end space!
+cxxflags="-I$pkgincludedir -Wall -Os -g -fno-strict-aliasing -DDBUG_OFF -arch x86_64 " #note: end space!
include="-I$pkgincludedir"

-Wno-null-conversion -Wno-unused-private-field というフラグを削除する必要があるみたい。

これは、mysql をアップデートしたときには、しばらく忘れずにやらにといけない。

これで mysql/mysql2 gem は無事インストールすることができるが、実際にアプリを実行してみると次のようエラーが出る。。。

dlopen(/Users/.../gems/mysql2-0.3.11/lib/mysql2/mysql2.bundle, 9): Library not loaded: /usr/local/mysql-5.5.28-osx10.6-x86_64/lib/libmysqlclient.18.dylib Referenced from: /Users/.../gems/mysql2-0.3.11/lib/mysql2/mysql2.bundle Reason: image not found - /Users/.../gems/mysql2-0.3.11/lib/mysql2/mysql2.bundle

備忘録としてのメモ。

libmysqlclient.18.dylib が見つからないらしい。

解決方法は、環境変数 DYLD_LIBRARY_PATH を定義するといいみたいだが、定義すると次のようなの警告が表示されてしまった。

dyld: DYLD_ environment variables being ignored because main executable (/usr/bin/sudo) is setuid or setgid

ということで、次を実行して、アプリケーションサーバを再起動したら無事解決した。

$ sudo ln -s /usr/local/mysql/lib/libmysqlclient.18.dylib /usr/lib/libmysqlclient.18.dylib

Ruby 1.8.7 + Rubygem で invalid date format in specification エラーを抑制する方法

Ruby 1.8.7(REE 2012.02)+ Rubygems で、gem をインストールするときや bundle list すると、次のようなエラーが表示されることがある。


Invalid gemspec in [/var/www/app/shared/bundle/ruby/1.8/specifications/json-
1.6.1.gemspec]: invalid date format in specification: "2011-09-18 00:00:00.000000000Z"

このエラーを抑制するには、Rubygem 1.6.2 をダウングレードすると抑制される・・・。

$ sudo /opt/ruby/bin/gem update --system 1.6.2

2012/10/01 追記:
1.8.24 もアップグレードすることで解消しますね。。。
最新版の方がいいですね。Rubygems 本体の変更履歴は、こちら
ちなみに REE 1.8.7-2012.02 バージョンに同梱されている Rubygems のバージョンは、1.8.15 ですが、1.8.22 でこの現象エラーは発生しなくなりました。

Nginx + Unicorn を導入記

とある Ruby 1.9.2 + Sinatra ベースのアプリケーションがあって、当初は大人の事情で WEBrick で本番稼働していたけれど、たまにエラーが発生することがあったので、思い切って Nginx + Unicorn はいわゆるモダンな構成(死語)に切り替えてみました。

今回のアプリケーションのルートディレクトリを SINATRA_ROOT としています。

まず、$SINATRA_ROOT/config.ru を作成します。

require 'rubygems'
require 'sinatra'

require './app.rb'
run Sinatra::Application

次に $SINATRA_ROOT/app.rb を作成します。./script/app というのは、既存の Ruby 1.9.2 + Sinatra アプリケーションです。

require './script/app'

次に、Unicorn の設定ファイルを作成します。今回は、Unicorn の設定ファイルは $SINATRA_ROOT 以下におきました。
Unicorn の設定ファイルは、Unicorn 公式サイトの設定ファイルを参考にしました。preload_app を true にするとエラーが発生したので、今回は false のままにしました。変更した設定は、次のとおりです。

  • worker_process: ワーカーのプロセス数(CPU コア数と同じにしました)
  • working_directory: アプリケーションの実行ディレクトリ
  • listen: Unix Domain Socket ファイルのパス
  • pid: プロセスIDファイルのパス
  • stderr_path, stdout_path: ログファイルのパス

アプリケーション側の設定は以上になります。
あとは、Nginx のインストールと設定です。

まずは、Nginx 公式の Yum リポジトリを追加します。(公式情報は、こちら

/etc/nginx/conf.d-local に専用の設定ファイルを作成します。

upstream example {
# fail_timeout=0 means we always retry an upstream even if it failed
# to return a good HTTP response (in case the Unicorn master nukes a
# single worker for timing out).

# for UNIX domain socket setups:
server unix:/var/tmp/example.sock fail_timeout=0;
}
server {
listen 443;
server_name _;
index index.html index.htm index.php;
ssl on;
ssl_certificate /etc/nginx/nginx.pem;
ssl_certificate_key /etc/nginx/nginx.key;
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
access_log /var/log/nginx/example_access.log main;
proxy_pass http://example;
}
}

上の設定を追加して、nginx を起動します。

Unicorn 経由でアプリケーションを起動する方法ですが、これも /etc/init.d/ に専用のスクリプトを作成してみました。
Unicorn の init.d スクリプトは、この gist にあるものを参考にして作成しました。

そして、Nginx と Unicorn の init.d スクリプトを起動時に自動的に起動するように設定しました。

最後に、アプリケーションのログテーションを、logrotate.d に、次のように設定しました。

/var/log/nginx/example_access.log {
daily
missingok
rotate 30
#compress
dateext

# this is important if using "compress" since we need to call
# the "lastaction" script below before compressing:
#delaycompress

# note the lack of the evil "copytruncate" option in this
# config. Unicorn supports the USR1 signal and we send it
# as our "lastaction" action:
lastaction
pid=/var/run/example.pid
test -s $pid && kill -USR1 "$(cat $pid)"
endscript
}

Nginx + Unicorn、なかなか便利な構成だと思いますね。

MySQL 5.5 + mysql2 gems でエラーが発生する件について

CentOS 6.3 x86_64 の MySQL 5.5 の環境(MySQL 5.5 は、公式の RPM を使用)で、gem install mysql2 すると、次のエラーが発生します。

$ sudo gem install mysql2
Building native extensions. This could take a while...
ERROR: Error installing mysql2:
ERROR: Failed to build gem native extension.
/usr/bin/ruby extconf.rb
checking for rb_thread_blocking_region()... no
checking for rb_wait_for_single_fd()... no
checking for mysql.h... yes
checking for errmsg.h... yes
checking for mysqld_error.h... yes
creating Makefile
make
gcc -I. -I. -I/usr/lib64/ruby/1.8/x86_64-linux -I. -DHAVE_MYSQL_H -DHAVE_ERRMSG_H -DHAVE_MYSQLD_ERROR_H -I/usr/include/mysql -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -fPIC -g -static-libgcc -fno-omit-frame-pointer -fno-strict-aliasing -DMY_PTHREAD_FASTMUTEX=1 -fPIC -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -fno-strict-aliasing -fPIC -Wall -funroll-loops -c mysql2_ext.c
./client.h:16: warning: ‘rb_thread_blocking_region’ defined but not used
gcc -I. -I. -I/usr/lib64/ruby/1.8/x86_64-linux -I. -DHAVE_MYSQL_H -DHAVE_ERRMSG_H -DHAVE_MYSQLD_ERROR_H -I/usr/include/mysql -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -fPIC -g -static-libgcc -fno-omit-frame-pointer -fno-strict-aliasing -DMY_PTHREAD_FASTMUTEX=1 -fPIC -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -fno-strict-aliasing -fPIC -Wall -funroll-loops -c result.c
gcc -I. -I. -I/usr/lib64/ruby/1.8/x86_64-linux -I. -DHAVE_MYSQL_H -DHAVE_ERRMSG_H -DHAVE_MYSQLD_ERROR_H -I/usr/include/mysql -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -fPIC -g -static-libgcc -fno-omit-frame-pointer -fno-strict-aliasing -DMY_PTHREAD_FASTMUTEX=1 -fPIC -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -fno-strict-aliasing -fPIC -Wall -funroll-loops -c client.c
gcc -shared -o mysql2.so mysql2_ext.o result.o client.o -L. -L/usr/lib64 -L. -rdynamic -Wl,-export-dynamic -Wl,-rpath,/usr/lib64 -lruby -L/usr/lib64 -lmysqlclient_r -lpthread -lm -lrt -ldl -lpthread -lrt -ldl -lcrypt -lm -lc
/usr/bin/ld: cannot find -lmysqlclient_r
collect2: ld returned 1 exit status
make: *** [mysql2.so] Error 1

どうやら、mysqlclient_r が見つからないようです。export LD_LIBRARY_PATH=/usr/lib64/mysql/:/usr/lib64 したり、/etc/ld.so.conf.d/ に mysql.conf を作成して /usr/lib64/mysql を作成してみたのですが、同じエラーのままでした。

MySQL 5.5 から、mysqliclient_r ではなく、mysqlclient になったようで、ちょうど先月に mysql2 gem のコミットが入っていました。
このバージョンは、まだ正式リリースされておらず、現在のバージョンは 0.3.12b4 となっています。そろそろ、リリースされそうな雰囲気なのですが、正式リースでないと不安のため、/usr/bin/mysql_config を書き換えることにしました。

差分は、次のとおりです。

--- mysql_config-org 2012-09-18 17:10:53.083571150 +0900
+++ mysql_config 2012-09-18 17:13:36.359551034 +0900
@@ -83,7 +83,7 @@
bindir='/usr/bin'

# If installed, search for the compiled in directory first (might be "lib64")
-pkglibdir='/usr/lib64'
+pkglibdir='/usr/lib64/mysql'
pkglibdir_rel=`echo $pkglibdir | sed -e "s;^$basedir/;;"`
fix_path pkglibdir $pkglibdir_rel lib/mysql lib

@@ -112,7 +112,7 @@
# We intentionally add a space to the beginning and end of lib strings, simplifies replace later
libs=" $ldflags -L$pkglibdir -lmysqlclient -lpthread -lm -lrt -ldl "
libs="$libs "
-libs_r=" $ldflags -L$pkglibdir -lmysqlclient_r -lpthread -lm -lrt -ldl "
+libs_r=""
embedded_libs=" $ldflags -L$pkglibdir -lmysqld -lpthread -lm -lrt -lcrypt -ldl -laio "

if [ -r "$pkglibdir/libmygcc.a" ]; then
@@ -121,7 +121,7 @@
# automatically. We package the libmygcc.a from the build host, to provide
# definitions for those. Bugs 4921, 19561, 19817, 21158, etc.
libs="$libs -lmygcc "
- libs_r="$libs_r -lmygcc "
+ libs_r=""
embedded_libs="$embedded_libs -lmygcc "
fi

この状態にして、次のコマンドを実行すれば、取り急ぎmysql2 gem をインストールすることができます。

$ sudo gem install mysql2 -- --with-mysql-config=/usr/bin/mysql_config
Building native extensions. This could take a while...
Successfully installed mysql2-0.3.11
1 gem installed
Installing ri documentation for mysql2-0.3.11...
Installing RDoc documentation for mysql2-0.3.11...

なお、かなり無理矢理の対応のため、くれぐれも /usr/bin/mysql_config の書き換えには、他に何らかの悪影響があるかもしれないので、ぐれぐれもご注意下さい・・・。

Ruby 1.9 で ISO-2022-JP メールを送る方法

とあるプログラムが、UTF-8 の文字コードで、大人の事情で添付ファイルがあり、その添付ファイルが ShiftJIS なメールを送信プログラムがありました。
このとき、次のような警告が表示されてしまいます。


Non US-ASCII detected and no charset defined.
Defaulting to UTF-8, set your own if this is incorrect.

しかも、このとき本文にプログラム上で本文を追加しているのですが、その本文が追加されなかったりと、いろいろと都合が増えてきたので、思い切って ISO-2022-JP に変更してみました。

ISO-2022-JP メールを送信するには、mail-iso-20220-jp gem を使うと、便利です。

上のような場合、次のようなコードにすると、文字化けや警告が表示されなくなり、幸せになれます。

Mail.deliver do |mail|
mail.charset = 'ISO-2022-JP'
from "naoya@example.com"
to "naoya@example.jp"
subject %(メールタイトル)
body %(メール本文)
mail.charset = 'Shift-JIS'
add_file "/tmp/attachment.csv"
end

# 2012.08.23 追記
上のコードだと Becky! で文字化けしまう現象が発生しました。上のコードだと、マルチパートの charset が Shift-JIS になってしまうためです。。。
正しいコードは、次のようになります。
添付ファイルの文字コードは、添付ファイルの実際のデータから文字コードを判定して、Content-Type の charset に追加しています。
あと、添付ファイル名が UTF-8 以外だと、おそらく添付ファイル名が文字化けするので、その場合は別途エンコードする必要があります。
今回、僕の方では UTF-8 な Ruby プログラムの中で日本語のファイル名を設定しているため、問題なかったりします。

require 'kconv'
MAIL_DEFAULT_CHARSET = 'ISO-2022-JP'
Mail.deliver do
@charset = MAIL_DEFAULT_CHARSET
from "naoya@example.com"
to "naoya@example.jp"
subject %(メールタイトル)
text_part do |v|
v.charset = MAIL_DEFAULT_CHARSET
body %(メール本文)
end
add_file "/tmp/attachment.csv"
self.attachments.each do |attachment|
attachment.charset = Kconv.guess(attachment.body.to_s).to_s
end
end

けっこうはまりましたが、ググるより、Ruby の mail gem のソースコードを読んだ方が、ずっと解決が早いことが分かりました・・・。

[ruby/rails] オフラインドキュメントを生成する

ruby や rails を使ってウェブアプリケーションなどを開発するとき、必須なものにオフラインドキュメントがあります。その都度、インターネット検索したりするのはインターネット接続がある前提になったり、時間の浪費につながるため、できる限り必要な情報は手元に置いておくのが重要だと思います。

ruby や rails のオフラインドキュメントを生成するには、sdoc を使うと便利です。
sdoc は、gem 経由で簡単にインストールすることができます。


$ rvm 1.9.3
$ gem install sdoc

sdoc 3.0.16 だと、github を使っているときエラーが発生しているため、パッチをあてる必要があります。


$ diff $HOME/.rvm/gems/ruby-1.9.3-p194/gems/sdoc-0.3.16/lib/sdoc/github.rb
30c30
< s = Dir.chdir(File.join(basedir, File.dirname(path))) do --- > s = Dir.chdir(File.join(base_dir, File.dirname(path))) do
39c39
< s = Dir.chdir(File.join(basedir, File.dirname(path))) do --- > s = Dir.chdir(File.join(base_dir, File.dirname(path))) do
47c47
< absolute_path = File.join(basedir, path) --- > absolute_path = File.join(base_dir, path)

まずは、rails 3.2.3 のオフラインドキュメントを生成してみます。

$ git clone https://github.com/rails/rails.git
$ cd rails
$ git checkout v3.2.3
$ sdoc --format=sdoc --github --output rails-3.2.3 --hyperlink-all rails

かなり警告がでますが、しばらくすると rails-3.2.3 ディレクトリの中に html なドキュメントが生成されています。僕の手元の Macbook Air だと 15 分くらいかかりました。

次に ruby-1.9.3 のオフラインドキュメントを生成してみます。

$ git clone https://github.com/ruby/ruby.git
$ cd ruby
$ git checkout v1_9_3_194
$ sdoc --format=sdoc --output ruby-1.9.3p194

ruby-1.9.3p194 ディレクトリの中に約 5 分くらいでオフラインドキュメントを生成することができました。

あとは、これからのドキュメントを sdoc-merge を使うとまとめることができます。たしめにまとめてみたのですが、僕は個別で参照することが多いので、使っていません。

$ sdoc-merge --title "Ruby 1.9.3-p194 and Rails 3.2.3" --op merged --names "Ruby,Rails" ruby-1.9.3p194 rails-3.2.3

sdoc かなり便利ですね。

参照
Create local Ruby on Rails documentation for offline use | Shynnergy

Pow on Lion

pow を Lion 上で使うための設定方法です。pow は、Node アプリケーションなのですが、Node バージョン 0.4 系で動作するめインストールが少々めんどくさいです。

まずは、Homebrew 経由で pow をインストールします。このとき依存関係の設定により Node バージョン 6 系がインストールされます。

$ brew install pow

次に NVM をインストールして、Node バージョン 4 系をインストールします。

$ nvm install 0.4.12

次に pow の起動コマンドを変更して Node 0.4 系を使いように変更します。環境変数は、お使いの環境にあわせて展開して下さい。

$ vi $HOMEBREW_HOME/bin/pow
...
exec "$HOME/.nvm/v0.4.12/bin/node" "$HOMEBREW_HOME/Cellar/pow/0.3.2/pow/lib/command.js" "$@"

最後に pow エージェントを動作させます。80 ポートで直接動かしたい人は、ファイアウォールの設定も変更します。

$ sudo pow --install-system
$ pow --install-local

これで pow を使うことができるはずです。

僕は、大人の事情で Apache 経由で使いかっため、Running Pow With Apache を参考にしながら、次の設定をしました。

$ vi $HOME/.powconfig
export POW_DST_PORT=8080
$ wget https://raw.github.com/gist/1058580/zzz_pow.conf
$ sudo vi /etc/hosts
127.0.0.1 pow .dev

これでさくさくと開発を進めることができる環境になりましたが、RVM + Ruby 1.9.3 で Sinatra を使いたいとき、アプリケーション側の config.rb に GEM_HOME 環境変数を設定するのはやめたかったので、次の設定を追加しました。

$ vi $HOME/.powconfig
export POW_RVM_PATH="$HOME/.rvm/scripts"
$ cd $SINATRA_APP1
$ vi .rvmrc
rvm 1.9.3
export GEM_HOME="$HOME/.rvm/gems/ruby-1.9.3-p194"

こんな感じで設定しておくと、pow を RVM に対応させることができます!

さらに powder や powify を使うと便利だと思います。僕は今のところ powder を使っています。

これで、さくさくとウェブアプリケーションの開発が進められそうです!

Ruby で当月の何週目を求める方法

Ruby には、Date クラスの中に cweek プロパティがありますが、これは年ベースでの週数として取得できます。
当月の何週目かを求めるコードを書いてみました、たった 2 行でできました。


def get_week_num_of_month(date)
wday = (date.wday == 0) ? 6 : date.wday - 1
return (date.day - wday + 13) / 7
end

get_week_num_of_month 関数に Date クラスを渡すと、その日が当月の何週目か取得することができます。
なお、この関数は月曜日〜日曜日までを 1 週間としてカウントしています。

YARD + Passenger

gems のヘルプを参照するとき、YARD server を使うと、とても便利です。

YARD server は、yard server –gems とすると、8808 ポート経由でローカルにインストールされているすべての gem のヘルプを参照することができます。
YARD server を、supervisor などで起動してもいいんですが、せっかくローカル開発環境では Passenger を使っているので YARD server を Passenger で動かしてみました。

やり方は、とても簡単で、この config.ru を使うだけです。

  1. YARD server 用の DocumentRoot を作成します(例えば、/tmp/yard/public とします)
  2. /tmp/yard/config.ru を、gist から取得します

 

YARD server 用の Apache の設定ファイルを、次のような感じにします。

<VirtualHost *>
ServerName yard
DocumentRoot /tmp/yard/public
</VirtualHost>

あとは、/etc/hosts に yard 127.0.0.1 を定義して、ブラウザで http://yard を開くだけです。

これで、かなり便利に YARD server を使うことができますね!

rails 2.3 + rubygems 1.8.7

rails 2.3 + rubygems 1.8.7 の組み合わせで使っていると、次のような警告が発生します。
毎回、コンソール画面上で警告が表示されるのはけっこううざいので、その対策方法を紹介します。

NOTE: Gem.source_index is deprecated, use Specification. It will be removed on or after 2011-11-01.
Gem.source_index called from /Users/n0ts/.rvm/gems/ree-1.8.7-2011.03/gems/rails-2.3.12/lib/rails/gem_dependency.rb:21.
NOTE: Gem.all_load_paths is deprecated with no replacement. It will be removed on or after 2011-10-01.
Gem.all_load_paths called from /Users/n0ts/.rvm/gems/ree-1.8.7-2011.03/gems/gettext-2.1.0/lib/gettext/runtime/locale_path.rb:56.
NOTE: Gem.all_partials is deprecated with no replacement. It will be removed on or after 2011-10-01.
Gem.all_partials called from /Users/n0ts/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/site_ruby/1.8/rubygems.rb:258.
NOTE: Gem.all_partials is deprecated with no replacement. It will be removed on or after 2011-10-01.
Gem.all_partials called from /Users/n0ts/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/site_ruby/1.8/rubygems.rb:258.

それぞれ、2011-10-01, 2011-11-01 以降に rubygems から、該当のものが削除されてしまうという警告です。
とても親切な警告でありがたいですが、rubygems 1.8.7 を使う明確は理由は、今のところないですから、警告を非表示にしてみます。

その方法とは、rubygems を、次のようにダウングレードすることです。

gem update --system 1.6.2

rails 3.1 系にアップデートしたら、rubygems を 1.8.7 にすればたぶん大丈夫かと思いますよね。
rubygems の進化のスピードが速すぎて、ruby のバージョンを超えてしまう事態になってしまうかもしれないとふと思いました。。。

  • 1
  • 2