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

Bye Bye Moore

猫マンション建築の野望を胸に零細事業主として資本主義の荒波に漕ぎ出したアラサー男の技術メモ

ruby

(0xff - ...)みたいなことをやるなら、排他的論理和(XOR)を使うとメソッドチェインにできる

ZigBeeのチェックサム等々、結果から0xffを減算する処理があります。 とはいえ、一回の減算のためにメソッドチェインを崩すのも気が引けます。 こういう場合、排他的論理和(XOR)を使えば引き続きメソッドチェインできます。 XOR 0xff - 0x12 #=> 237 これは…

ZigBeeパケットのチェックサムを計算するRubyスクリプト

Zigbeeパケットのチェックサムはちょっとヤヤコシイです。手順としては 接頭辞0x7eとパケット長2バイトの合計3バイトを削る 末尾1バイトも削る 残った物を一バイト毎に分けて足し合わせる 0xff - さきほどの結果 ……これがチェックサムです。 死ぬほどヤヤ…

Rubyで標準出力からデータをとる

Rubyで標準出力からデータを取る場合、STDINをよみにいけば良いです。 実際のところ パイプ経由で受け取ったデータをCurlコマンドでherokuのアプリにpushする簡単なアプリを考えてみます。 STDINからデータを読むにはgetsメソッドを使えば良いので url = %Q(…

N進数リテラル混ざった文字列を配列に切り分ける場合、scanを使ってはいけない

リテラルが混在しているものから文字を一個ごとに切り出したいとします。 この場合、ぱっと思いつくのはscanですが…… "\u0012aga\x98ga987HH".scan(/.{1}/) #=> ["\x12", "a", "g", "a", "枠", "a", "9", "8", "7", "H", "H"] と、変に気を利かせて\x98gを"…

8進数リテラルや16進数リテラルが混在した文字列を元の16進数な文字列に置換する

SerialPortなどで16進数のパケットを受けると、 こんな感じの文字列が返ってくる事があります。 "~\u0000\u0018\x91\u0000\u0013\xA2\u0000@u" もとは16進数の数値がズラズラと並んでいるはずなのですが。 8以内の数値は8進数リテラル 9〜Fが含まれて…

PC版のSerialPortアプリで動いて組み込み機器で動かない場合、timeoutまわりを疑ってみる

とある案件で、組み込み機器で通信を受けて彼是するアプリを開発した事があります。 いわゆる組み込みLinux関係でしかもdebianだったので楽勝だろーとrubyのSerialPort系gemをつくってチャッチャッとつくってみました。……ところが。 いざ、本番環境の機器で…

何らかの事情でgemのリストを確認できないときは「GEMNAME::VERSION」で参照してみる

人様から譲り受けた環境で、かつ固定環境のため焼きこまれているgemのバージョンが確認し辛いときがあります。 そんなときは GEMNAME::VERSIONとやればバージョンが出てきます。 少なくとも、rubugemに公式で公開されている真っ当なgemならこれで値がでてき…

Enumerable#findにProcオブジェクト等々を渡して一致ナシの場合を楽に実装する

Enumerable#findにProcオブジェクトを渡してあげると、一致ナシの場合呼び出してくれます。 実際のところ findの引数にcallをもつオブジェクト……Procクラスとかlambdaとかを渡せばよいです。 (1..10).to_a.find( Proc.new { :none } ) {|i| i > 11} #=> :non…

Enumerable#drop_whileで、条件に一致したもの以降を捨てる

こんな配列があったとします。 buff = [2,6,7,1,2] これを、ある特定条件以降で切り捨てたい場合……drop_whileが使えます。 使い方 なんらかの都合で順番通りに処理したい場合も使えますが*1 buff.drop_while{|i| i < 5} #>> [ 6, 7, 1, 2 ] 順当な使い方から…

Mathライブラリとcase文をつかって、桁の接尾辞(kとかMとか)を出す

Math#log10について Math#log10は、その名の通り与えられた数値にlog10を適用した結果を出すメソッドです。 Math.log10(12_345_678) #>> 7.091514945509202 元の数値を3(=log10(1000))で割った結果を与えると…… (Math.log10(12_345_678) / 3) #>> 2.3638383…

Benchmark-IPSでRubyベンチマークを便利に使う

Benchmark-IPSはRuby標準添付のBenchmarkライブラリを便利に拡張してくれるGemです。 使い方 導入 $ gem install benchmark-ips 用例 普通のBenchmarkならbmメソッドを呼び出すところ、 ipsメソッドを呼び出すあたりが違います。 また、IPSならcompare!とい…

「BinData」で長さが不明の文字列を使いたい場合、count_bytes_remainingを使う

文字列の長さを指定してくれない不親切設計なパケット設計てありますよね。 そんな場合、count_bytes_remainingが使えます。 使い方 以下の例だと、末尾13文字を除いて途中の文字を:dataに放り込んでくれます # ... count_bytes_remaining :bytes_remainin…

Module#const_missingを使って、未定義な定数に対する動作を定義する

Module#const_missingは、未定義な定数を参照した際に呼び出されるメソッドです。 こんな感じで使います。 class Test1 def Test1.const_missing(name) mapping = { /^Func(\d+)$/ => :func } mapping.each_pair do |rgx, args| if rgx =~ name.to_s return …

「BinData」のArray型は連続する短いデータの取り扱い時に便利

「BinData」のArray型は連続する短いデータの取り扱い時に便利です。 使い方 16進数リテラルで渡す 16進数リテラルで渡します data = "\x03\x04\x05\x06\x07\x08\x09" これを読み込むと ary = BinData::Array.new(:type => :uint8, :read_until => :eof) ary…

Zlib::GzipReader/WriterとStringIOをつかってファイルを作らずGzip圧縮なデータを扱う

ZlibはRubyに標準添付さえている圧縮系ライブラリです。 普段はFileクラスと一緒に使ったりします。 これとStringIOと組み合わせると、ネットワーク上でも利用可能です。 実際のところ。 str = ""; (0..1000).each { str += (0x61 + rand(0x10)).chr } 0..10…

Rubyのバックスラッシュ記法8進数で0-7以外を使うと、バックスラッシュ記法16進数風にパースされる

今回の記事はかなりマニアック……というか、誤爆したときくらいしか使い道が無いですが 使い方 "\022" は8進数記法です。 比較すれば、このとおり。 "\022" == "\x12" #=> true 並べて使うこともできますし、 "\022\064" #=> "\x124" "\022" + "\064" #=> "\…

「BinData」Choice構文で、条件毎に構造を変える

BinDataのchoice構文を使うと、部分的に一致してるスクリプトも一本化できます 使い方 class EData < BinData::Record string :val_a, :length => 8 string :val_b, :length => 4 end class DData < BinData::Record uint8 :val_c rest :rest end class Pack…

「BinData」で文字列型に関するアレコレ

BinDataの文字列型は自由度が高く、うまく使いこなせば楽ができます。 つかいかた 長さを指定する 長さを指定するなら、lenghtをもたせます。 obj = BinData::String.new(:length => 6) obj.read("abcdefghij") obj #=> "abcdef" 不足はヌルうめ 文字が不足…

「BinData」で余計なデータを放り込んでおく箱が必要な場合、restを使う

流れてくるデータに対し、とりあえず放り込む箱が欲しいなんて時は、restが使えます。 つかいかた class D < BinData::Record string :a, :read_length => 10 rest :rest end という風に実装した場合 obj = D.read(Array('a'..'z').join) #>> {:a=>"abcdefgh…

「BinData」で階層構造なデータを定義する

あまりに情報がゴチャゴチャして可視性が悪くなった場合、 階層構造にするとなんとかなるケースもあります。 使い方 一つのクラスに記述 class SampleBase < BinData::Record uint8 :val_a struct :nested do uint8 :val_b uint8 :val_c end end とやれば sb…

「BinData」で可変長なフィールドを定義する際はread_lengthが使える

「BinData」で可変長なフィールドを定義する際はread_lengthやlambda式が使えます。 lambda class Hoge < BinData::Record endian :big uint8 :len, :value => lambda { data.length } string :data, :read_length => :len end と定義した場合、「data」フィ…

「BinData」でエンディアンが変わらない場合はendianオプションを使ってやれば楽ができる

エンディアンがBigかLittleかで固定されている場合、endianを設定してあげれば以降「be」だの「le」だのと付けなくてすみます。 そのため、 前回の内容は require 'bindata' class Sample < BinData::Record endian :big uint8 :val_a uint8 :val_b uint16 :…

Rubyでバイナリデータを格好良く扱うgem「BinData」が素晴らしすぎて膝から崩れ落ちた

0x1234567890abcdef とてな感じのバイナリデータがあったとします。*1 これを適正に振り分ける場合、どうしてますか? これまでの私だと、文字列のまんま val_a = "1234567890abcdef"[10].chr とやるなり、unpackで配列化して val_a = "ab".unpack("CC")[0].…

TZInfoでカントリーコードを扱う

前述のTZInfoは各種タイムゾーン情報を格納しています。 なので、カントリーコードもメソッドで一気に出力させることができます。 ap TZInfo::Country.all_codes, limit:true とやれば、 [ [ 0] "AD", [ 1] "AE", [ 2] "AF", [ 3] .. [245], [246] "ZA", [24…

「TZInfo」でタイムゾーンを扱う

メールを送ろうにも、現地が深夜だとレスが遅くてガッカリする事ありますよね。*1 Googleなら、「国名 時間」とやってあげると現地時間がでてきますが微妙に面倒です。 そんなときはタイムゾーンを使うgem、TZInfoを使ってちょっとしたスクリプトを書いてみ…

「docopt」を使えばgithubやherokuのCLIツールみたいなUIをドキュメント駆動開発で実装できる。

Julliaとか聞いたこともない珍しい言語もサポートdocopt/docopt.rb · GitHub と、Rubyも対応はしているのですが docopt has been confirmed to work with 1.8.7p370 and 1.9.3p194. If you have noticed it working (or not working) with an earlier versio…

gem「view_source_map」で、Render元のファイルをViewに表示する

view_source_mapはViewにRenderもとのContollerファイル名を記載してくれる便利Gemです 使い方 特になんの工夫もなく、rails sしてあげれば <p>test</p> てな感じで展開されます。 ソースをみると、Railtie自体に細工をする事でこの魔法が実現されているようです……

オンラインREPL「http://repl.it/」が魔界技術すぎて辛い

ちょっとJavaScriptで遊びたいなーと検索をかけたところ…… オンラインREPL「http://repl.it/」を発見しました 使えるものの一例 JavaScript以外にも、色んな言語が実装されています。 一通り遊んでみた範囲では、軽い動作検証程度であれば十分用は成すようで…

Railsのbundle installで突っ込んだgemの配置先をみる

Railsのbundle installで突っ込んだgemの配置先をみるには 「bundle show」です。 $ bundle show sass /Users/shuzo_kino/.anyenv/envs/rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/sass-3.4.13また、半端に入力しても $ bundle show sas 1 : sass 2 : s…

Rubyで状態遷移を実装できるGem「AASM」(その4_現在の状態を表示)

現在の状態を表示する場合、current_eventが使えます。例えば、指定のメソッド中で現状のイベント名を提示したい場合 class AASM_Sample include AASM aasm do #中略 event :sence, :after => :comment do transitions :from => :sleep, :to => :transmit en…

Rubyで状態遷移を実装できるGem「AASM」(その3_状態に入ったあとの動作を定義)

event :sence do after { p "sence"} transitions :from => :sleep, :to => :transmit end といった感じで、eventの中に記述します。 あるいは、 assmのブロック外に def comment puts "comment" endとしてあげた上で event :sence, :after => :comment do t…

Rubyで状態遷移を実装できるGem「AASM」(その2_未定義の動作)

AASMにて、定義していない順番で呼び出しをすると例外を返してきます。とはいえ、そのまま動作を止めたくない場合もあるわけで… そういった場合は aasm :whiny_transitions => false do # ... end とすることで、「false」を返すように指定できます。 以前の…

Rubyで状態遷移を実装できるGem「AASM」(その1_導入)

AASMはRubyで状態遷移を実装できるGemです。 導入 $ gem install aasm 使い方 クラスの中で呼び出すDSLになっています。 たとえば…次のような、シンプルな状態遷移図を実装する場合は require "aasm" class AASM_Sample include AASM aasm do state :sleep, …

SlimでHTMLエスケープをしない場合「==」

yieldなど、HTMLエスケープをしたくない場合は「==」で出力すればOKです - def hoge; '&!hoge'; end = hoge br == hoge これが、 &amp;!hoge<br />&!hoge と出力されます。 参考もと slim-template/slim · GitHub

Slimでタグを切り替えたい場合はDynamic Tagが便利

Slimでタグを切り替えたい場合はDynamic Tagが便利です。 これを使うと… たとえば特定のユーザにだけ表示したいinputタグ…なんてケースを実装するのが楽です。 実際のところ ruby: def nyu @flag ? {tag: 'p'} : {tag: 'b'} end - @flag = true *nyu NYU wit…

SlimのSplat attributes「*」で要素代入を楽にやる

Slimでタグにクラスをくっつける場合、配列やハッシュで渡す事ができます。 a.menu class="highlight" href="http://slim-lang.com/" Slim-lang.comとやれば、 <a class="menu highlight" href="http://slim-lang.com/">Slim-lang.com</a> と、よろしくコンバートしてくれます。ここで、Splat attributesという機能をつか…

slimで最初の数え上げ要素だけ特別な処理を加える

次のようなslim形式のテキストデータがあったとします。 $ cat hoge.txt ul li.first: a[href="/a"] A link - 10.times do |i| li: a[href="/#{i}"] #{i} link li.last: a[href="/B"] B linkこれをSlimのコンバータにかけると、 のように最初の要素だけA、数…

slimrbコマンドで軽くSlimを扱う

slimrbは公式が提供しているslimのパーサコマンドです。 ただ、別途redcarpetというマークダウンパーサのgemが必要なので 先に導入します。 $ gem install redcarpet つかいかた $ echo 'markdown: 123 456 * a * b ' | slimrb なんてことをやれば、 <p>123 456</p> <ul></ul>…

Ruby製OSX用通知ツールterminal-notifierが結構便利

terminal-notifierはRuby製OSX用通知ツールです。 導入 $ brew install terminal-notifierRubyの環境が入っている場合は $ gem install terminal-notifierでもいけます。 使い方 $ terminal-notifier -message 'Pop!'とやると、 のように右上に画面がポップ…

Kernel.#__method__はメソッド名自身を返す

Kernel.#__method__はメソッド名自身を返す変数です。 Kernelクラスにくっついたもので、組み込み変数ではないので注意。 def testMethod "This is " + __method__.to_s end testMethod #=> "This is testMethod" エイリアスを貼った場合、呼び出し先が優先…

pry#show-sourceは自前定義クラスやモンキーパッチの大元を見に行くことができる

…あたりまえと言えば、あたりまえなのですが… 以前記事を書いたshow-sourceはメソッド以外にも、クラスを見にくこともできます。pry上で次のようなクラスを定義したとします。 class Hoge def initialize(val) val.to_s end def method_missing(name, *args,…

Object#public_methodsに偽の値を渡すと、スーパークラス由来のメソッドを除外してくれる

class Hoge def initialize(val) val.to_s end def method_missing(name, *args, &blk) 42 end end などというクラスがあった場合、何もつけずにpublic_methodsをやると 198個(awesome_printのモンキーパッチを含む)のメソッドが出てきます。 Hoge.new(…

Hashに破壊的に要素を追加したり更新をする場合はupdateで十分

既存のhashの要素を追加したり、Hash同士をくっつけたりする場合はHash#updateがあれば大抵は事足ります。 見ての通り、破壊的メソッドなので使用には注意が必要です。 非破壊なものを望む場合は、Hash#mergeが使えます。 中身の更新 {a: 1, b:2}.update(b: …

メソッドがどのクラス|モジュールにくっついているか調べる

Rubyにおいては、メソッドはMedhodクラスという入れ物で管理されています。 こいつをつかうと、 buff = String.new.method(:upcase) #String#upcase() Awesome_printのapメソッドのようなカーネルにくっついているメソッドもこの通り。 buff = AwesomePrint.…

nilや空文字が入った配列を接続して文字を作る際のtips

Effective_Rubyによれば… 「Rubyは型判断システムの関係でnilが入り込むのだから、最初っから対策をねじ込んでおけ(意訳)」との事。 実際のところ nilが含まれている配列を"-"で繋げて一つの文にする事を考えます。 ["Shuzo", nil, "Kino", nil].join('-')…

Rubyにおける定数

あまり使う局面はないかもしれませんが、Rubyでも定数を使うことができます。 FOO = "yeah!" puts FOO #=> yeah! 一応、上書きすることもできますがエラーがおきます。 FOO = 12 #(pry):22: warning: already initialized constant FOO #(pry):19: warning: …

「,=」と出ていたら、それは多重代入です。

Rubyにも多重代入があります。 a, b = [1, 2] ap a #=> 1 ap b #=> 2 コーディング規則では大抵推奨されてない方法です。ところがドッコイ、awesome_printのようなスゴイヤバイ級Rubyistが集うgemだとそうでもないようです。 たとえば、次のような記法が… va…

awesome_printでRubyオブジェクトをさらに見やすくする(その5)

awesome_printには色を指定するオプションがあるのですが… その関係なのかなんなのか、色をつけるメソッドが付加されます。 "hoge".red #"\e[1;31mhoge\e[0m" "hoge".redish #"\e[0;31mhoge\e[0m" 公式によると、サポートしている色は次の通り :gray, :red, …

awesome_printでRubyオブジェクトをさらに見やすくする(その4)

awesome_printはrails consoleでも活用できます。 下準備 Gemfileのdevelopmentグループに、pry-railsとawesome_printを記述 group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug…

awesome_printでRubyオブジェクトをさらに見やすくする(その3)

awesome_printはObject#methodsの使い勝手もグレードアップします。例えばpでやった場合 "".methods #=> [:<=>, :==, :===, :eql?, ..., :__send__, :__id__] ppでやっても pp "".methods #[:<=>, # :==, # :===, #..., # :__send__, # :__id__] と、大して…