boolean_accessorというGemを書いてRubyGems.orgに公開した
boolean_accessor
たとえば、
class Item attr_reader :active def initialize @active = true end end
のような場合、
item = Item.new item.active # => true
となりますが、active
という属性がbooleanだということをもっとわかりやすくしたいところです。
かといって、is_active
という名前にするのもrubyっぽくなくてイマイチ。
ここは、
item.active? # => NoMethodError: undefined method `active?'...
で、trueが返ってきてほしいところです。
alias_method :active?, :active
とすれば、item.active?
とできるようになりますが、複数属性がある場合にひとつひとつ書くのは面倒ですし、booleanの属性にこういった動作をしてほしい場合は多々あるので、gemにしてみました。
使い方はREADME.mdに書いてある通りですが、今回の例であれば、
class Item battr_reader :active def initialize @active = true end end item = Item.new item.active? # => true
のようになります。
RubyGems.orgへの公開
今回はじめてrubygems.orgに公開してみましたので、手順を書いておきます。
gemを作るのはbundlerを使うと簡単です。
bundle gem boolean_accessor
以下のようなファイルが作成され、gitの準備もしてくれます。
create boolean_accessor/Gemfile create boolean_accessor/Rakefile create boolean_accessor/LICENSE.txt create boolean_accessor/README.md create boolean_accessor/.gitignore create boolean_accessor/boolean_accessor.gemspec create boolean_accessor/lib/boolean_accessor.rb create boolean_accessor/lib/boolean_accessor/version.rb Initializating git repo in /path/to/dir/boolean_accessor
libの中に実際のコードを書いていくわけですが、今回はとても小さなgemなので、テスト以外のコードとしては、
boolean_accessor/lib/boolean_accessor.rb
を書いただけです。
動作を確認する場合は、作成されたディレクトリに移動(cd boolean_accessor)した上で、
bundle console
とすれば、gemの内容が読み込まれ、コンソール上で動作が確認できます。
あとは boolean_accessor.gemspec のTODOや必要事項を埋めたり、README.mdなどを編集すれば、今回は完成です。
gemspecは必ず確認するので問題ないと思いますが、LICENSE.txtにも自動で名前が入っているので、必要があれば修正します。(最初は~/.gitconfig
のuser nameが入るみたいです。)
公開するgemなのでテストも書いておきます。specディレクトリを作成し、RSpecで書きました。
公開する前に、まずローカルでgemをbuildし、インストールしてみます。
rake -T
でrakeタスク一覧を見ることができます。
rake install
をすればインストールできるはずですが、権限の関係かうまくいかなかったので、
rake build
でgemを作成し、作成されたgemを、
sudo gem install pkg/boolean_accessor-0.0.1.gem
でインストールしました。
RubyGems.orgへの公開は、まずサイトにサインアップしておいた上で、
git push pkg/boolean_accessor-0.0.1.gem
のようにして、聞かれるEmailやPasswordを入力すれば、公開できました。
一度リリースすると、~/.gem/credentials
ファイルが生成されるようで、これが作成されると今後はrake -T
で一覧表示されたrake release
でリリースできるようになるのだと思います。
参考
Basic RubyGem Development - Tech.Pro
はじめてbundlerでruby gem作ってgithubとrubygemsに上げてみた - shoprevのブログ
Ruby: Boolean attribute naming convention and use - Stack Overflow
Solr 4用のMuninプラグインを書いた
Solr 3までは solrmulticore というプラグインを使っていたのですが、Solr 4.0以降動かなくなっていたので、Muninプラグインの書き方を調べて自分で書いてみました。
Rubyで書いたのですが、書き方自体は別エントリで書くことにして、このプラグインの使い方を書いておきます。
インストール
cd /usr/share/munin/plugins/
sudo wget https://raw.github.com/hiroki23/munin-solr4-multicore/master/solr4_multicore_
sudo chmod 755 solr4_multicore_
先頭のrubyパス (#!/usr/local/bin/ruby) は、環境に合わせて修正してください。
sudo vi solr4_multicore_
(Rubyのパスは、which ruby
で確認できますね。)
シンボリックリンクを作成します。
sudo ln -s /usr/share/munin/plugins/solr4_multicore_ /etc/munin/plugins/solr4_multicore_999thPcRequestTime
munin-nodeをrestartします。
sudo /etc/init.d/munin-node restart
この例では、99.9%番目のリクエスト時間のグラフが生成されます。
取得できる値
同じようにシンボリックリンクを作ることで、以下のような値が取れます。
- avgRequestsPerSecond
- 5minRateReqsPerSecond
- 15minRateReqsPerSecond
- avgTimePerRequest
- medianRequestTime
- 75thPcRequestTime
- 95thPcRequestTime
- 99thPcRequestTime
- 999thPcRequestTime
- errors
- timeouts
など。
sudo ln -s /usr/share/munin/plugins/solr4_multicore_ /etc/munin/plugins/solr4_multicore_{取りたい値}
Solr4.1までは、req/sec、time/reqは、avgRequestsPerSecondやavgTimePerRequestしか取れなかったのですが、Solr4.2以降は5分ごと、15分ごとのreq/sec、平均time/req、75%、95%、99%、99.9%番目のtime/reqが取得できるようになって、ますます便利になりました。
同様にシンボリックリンクを作成することで、以下のキャッシュのキャッシュヒット率も取ることができます。
- queryResultCache
- documentCache
- fieldValueCache
- filterCache
画面キャプチャ
設定がうまくいけば、以下のようなグラフが生成されます。
5minRateReqsPerSecond
99thPcRequestTime
documentCache
RSpecをpryで試す
RSpecではいつの間にかshouldではなくexpectが推奨されるようになっていました。
やはり実際に手を動かして覚えたいので、公式ページを見ながら pry(またはirb)で試してみます。
rspec-expectations
rspecをインストール
sudo gem install rspec
pry起動
pry
こんなふうに試せます。
require 'rspec' # => true include RSpec::Matchers # => Object expect(1).to eq(1) # => true expect(1).to be > 2 # => エラー
shouldのほうが書きやすいと思っていましたが、書いてみると意外と悪くない感じ。
エラーの検証は、
expect{ raise }.to raise_error # => true
範囲系は以下のような感じで書けます。
(ただし、includeはモジュールの読み込みと重なってしまうので単純には書けません。)
expect([1,2,3]).to start_with(1) expect([1,2,3]).to start_with(1,2) expect([1,2,3]).to end_with(3) expect([1,2,3]).to end_with(2,3) expect("this string").to start_with("this") expect("this string").to end_with("ring") # => すべてtrue