読者です 読者をやめる 読者になる 読者になる

ダメでしょ!

プログラミングとか怒られた話とか…

sqale がサービス終了するので、Heroku に移行した

sqale からの移行推奨先は Heroku

info.sqale.jp

公式にそのような案内がありました。
ただ、正直な話、レイテンシが発生するということ、ドル払いになってしまうことから最初は他のサービスに移行したいと考えていました。

移行先調査した

ということで、移行先を検討してみたんですが、国内サービスは(私の観測範囲では)見当たらなかったんですよね。
で、結局
AWS
GCP
・Azure
・Heroku
という形になってしまいました。
この内、
AWS
はIaaSしかなさそう、
GCP
はPaaSがあったが、rubyはベータ版?っぽい、
・Azure
はよくわからんかった。
となり、結局Herokuになってしまった。
もう少し調査に時間がかけられたら・移行に時間がかけられたら、というたらればはあるのですが、いかんせんあまり時間ばかりもかけていられなかったので。

Heroku に移行すると大半の人はコストアップになりそう

というのが、Heroku のデータベースに起因してきます。
デフォルトでは、DBの容量がたったの5MB。(ClearDB MySQLの場合)

Sqaleでは2GB使えていた(ハズ)なので、移行を検討している殆どの人が引っか

elements.heroku.com

かるのではないかと。
で、これを1GBにしようとすると、9.99ドル/月が必要になります。

Heroku サーバ自体が、24時間無停止にしようとすると7ドル/月 かかるため、併せて16.99ドル/月 が最低料金になるかと。

Heroku くらいしか同じように使えるところがないからしょうがない・・・

月額が約2倍となってしまい、更に東京リージョンではないためにレイテンシが発生するという全然嬉しくない結果なのですが、他が見当たらないのでしょうがないです。

sqale のサービス終了、痛いです。

移行してみて

で、実際 Heroku に移行してどうなのか、ですが、レイテンシはもちろんありますが、それ以外の部分は結構使いやすいです。
一つつまずいたのが、crontab です。
今までは whenever という gem で crontab の設定を管理していたのですが、Heroku ではcrontab が使えないようです。
代わりに Heroku scheduler というものでバッチ系の処理を管理するみたいです。

Heroku Scheduler | Heroku Dev Center

そのあたりがわかっていなかったので、対応に時間がかかりました。

Rails5 でバッチ処理を利用する際に知らないとハマるかもしれないポイント!

前提

Rails 5.0.2
Ruby 2.4.0

なににハマったのか?

Rails5 で新規アプリを作成していて、バッチ処理を作成しました。
処理は .\lib\tasks\ 配下に格納し、 .\config\application.rb に以下の設定を行いました。

class Application < Rails::Application
  ・・・
  config.autoload_paths += Dir["#{config.root}/lib"]
  ・・・
end

これで lib ディレクトリ配下は自動的に読み込まれる設定になっていると思っていました。
Rails4 時代はこれでよかったんです。。。
さらに、開発環境では問題なくバッチ処理を呼び出すことができます。
これによって問題の解消がますます困難になりました。。。

Rails5 の本番環境では autoload が無効化された

A Guide for Upgrading Ruby on Rails — Ruby on Rails Guides

上記に記載されていますが、Rails5から本番環境では、autoload が無効になっています。
これは、、、知らないと絶対ハマる。

どのように問題に対応するか

上記のURLには解決策として、.\config\application.rb

class Application < Rails::Application
  ・・・
  config.enable_dependency_loading = true
  ・・・
end

と記載することで、autoload するように変更することがあげられています。
しかし、autoload が無効化されたということは、今後使えなくなることが想定されます。
ですので、今回は eager_load を利用することにしました。 .\config\application.rb

class Application < Rails::Application
  ・・・
  config.paths.add 'lib', eager_load: true
  ・・・
end

と指定し、lib ディレクトリ配下を eager_load されるように指定することで問題を解消しました。
app ディレクトリ配下の読み込みはこの eager_load で行われているようなので、これで問題ないはずです。

Rails のルーティングに使用する id を別の内容に変更する方法

通常、edit 等に使用する URI に設定される id を、別のキー等で置き換えたい場合があります。

$ be rake routes
             Prefix Verb   URI Pattern                                        password_resets POST   /password_resets(.:format)              password_resets#create
 new_password_reset GET    /password_resets/new(.:format)          password_resets#new
edit_password_reset GET    /password_resets/:id/edit(.:format)     password_resets#edit
     password_reset PATCH  /password_resets/:id(.:format)          password_resets#update
                    PUT    /password_resets/:id(.:format)          password_resets#update

この id を code に置き換えたい場合、.\config\routes.rbに以下のようにparam: codeを設定することで、置き換えることができます。

  resources :password_resets, param: :employee_code, only: [:new, :create, :edit, :update]

上記のようにすることで、ルーティング情報は以下のようになります。

$ be rake routes
             Prefix Verb   URI Pattern                                    Controller#Action        password_resets POST   /password_resets(.:format)                     password_resets#create
 new_password_reset GET    /password_resets/new(.:format)                 password_resets#new
edit_password_reset GET    /password_resets/:code/edit(.:format) password_resets#edit
     password_reset PATCH  /password_resets/:code(.:format)      password_resets#update
                    PUT    /password_resets/:code(.:format)      password_resets#update

id とは別のキーを主キーのような形で使う際に重宝します。

Perl でパスワードZipを求められた際の対応方法

前提

Perl は初めて触りました。
対応を求められたサーバの環境は古いです。

$ perl -v
This is perl, v5.10.1 (*) built for x86_64-linux-thread-multi

QBK (急にボールが来たので)

他にヘルプできそうな人間がいなかったということで、触ったことのない Perlソースコード修正を求められました。

内容は、Webフォームに添付されたデータをメールで送信するシステムの添付ファイルをパスワードZipで圧縮すること。

Perl 触ったこともないので、極力他に影響を与えたくない一心で対応しました。
調べてみると、Perl の標準モジュールに「Archive::Zip」というものがあるのですが、これはパスワードZipに対応していませんでした。。。
どうしようかなー、と悩んだのですが、Perl からコマンドが呼び出せるらしいので、コマンドでパスワードZipを作成し、それを添付することにしました。
ということで対応したコードが以下。

#-----------------------------------------------------------
#  パスワードzip生成
#  引数: ファイル名
#  備考: $cf{upldir} には、ファイルの保管場所ディレクトリパスが入っている
#-----------------------------------------------------------
sub zip {
    my $ZIP_CMD = "/usr/bin/zip";
    my $ZIP_PASSWD = "************";
    
    my ($origin_name) = @_;
    my $zip_name = "$origin_name.zip";

    my $cmd = "$ZIP_CMD -jP $ZIP_PASSWD $cf{upldir}/$zip_name $cf{upldir}/$origin_name"; # パスワードzipの生成コマンド
    system($cmd); # コマンドの実行
}

で、これをメール送信処理中の添付ファイルをセットする前に

&zip($fname); # $fname には対象となるファイル名が格納されている

と呼び出して、生成したファイルを添付することで対応しました。

今回はパスワード自体をランダム化する必要が無いという要件だったので、ソースコード内にパスワードを埋め込んでいますが、あまりよろしくないという認識はあります。
また、system関数は便利な半面、セキュリティリスクになりそうなので、使い所を見極めて使う必要がありますね。

初めて Perl に触りましたが、デバッグ方法もよくわからないし、辛かった。。。

ActiveRecord に対する scope は条件に一致するレコードが存在しない場合 .all の結果を返却する

scope を利用していたところ、思わぬところでハマってしまいました。。 指定の条件で検索を行い、返却された結果が nil かどうかで条件分岐させようと思っていたのですが、scope を利用すると常に nil ではなく、.all の結果が返却されてきます。

scope :search_with_user, -> (user_id) { where('user_id = ?', user_id) }

よくよく調べて見たところ、 scope はメソッドチェーンを実現するために、nil を返すことはなく、.all を返すんだとか。

要は scope の利用方法に関する認識不足だったのですが、他の人も同じような勘違いをする可能性もあるかも、と思ったのでブログに残しておきます。

Sqaleがサービス終了するとのことです

PaaSとして柔軟に利用していたGMOペパボのサービスであるSqaleですが、終了するとのこと。

【サービス終了のお知らせ】 | Sqale Information

安価であったため、結構使い勝手がよく、ちょこちょこ利用させてもらっていたんですが、rubyのバージョンアップに追従してなかったんで心配していたのですが。。。 代替サービスとしてはHerokuが推奨されています。

www.heroku.com

Herokuはドル建ての請求になるだろうから、それが経理からいやがられるんだよな。。

iBatis で LIKE 文を使うときの注意点

はじめに…SQLインジェクション発生!

現在対応中の案件で、なぜか iBtais の利用が指定されている案件があるのですが、ここでSQLインジェクションを発生させてしまったので、自戒として記載します。

iBatis の動的パラメータ受け渡し

iBtaisには # と \$ が用意されていますが、# で囲まれたパラメータはエスケープされ、\$ で囲まれたパラメータはそのまま出力されます。
で、LIKE分を記述する際は、%を渡したかったので、

WHERE column1 LIKE $%value%$ 

と記述していたのですが、そうしたところ、'などを検索文字として渡した際にエラーが発生しました。
つまり、SQLインジェクションが発生してしまったわけです。

対応策

で、どうしたかというと、

WHERE column1 LIKE CONCAT('%', #value#, '%')

という風に、文字列連結を行うことで対応しました。
一部RDBではCONCATに対応していないみたいですが、MySQLOracleMSSQL等は問題なく動作するようです。
PostgreSQLはちょっとだけ微妙。
%を含んだ検索がうまくいかないようです。
実害はないようですが。