コード日進月歩

しんくうの技術的な小話、メモ、つれづれ、など

jq を使って平文のJSONをシェルコマンドだけでいい感じにエスケープする

vegeta の Readme 見てたらこんな使い方あるんだ的なメモ

環境

$ jq --version
jq-1.5

※jqの説明は参考リンク参照のこと

使い方

特定のJSONの値をちゃんとエスケープを書けたURIにしたいときがあったとする。

例えば

{
  "url": "https://example.com/search?q=テスト"
}

{
  "url": "https%3A%2F%2Fexample.com%2Fsearch%3Fq%3D%E3%83%86%E3%82%B9%E3%83%88"
}

としたい場合。

やり方

jqの –null-input のオプションと パイプ( | ) 、そして @エスケープを使って実現する。

上記を実現したい場合は以下の様に書く

$jq -n '{"url": "https://example.com/search?q=テスト"| @uri}'

そうすると以下のように結果が帰ってくる

{
  "url": "https%3A%2F%2Fexample.com%2Fsearch%3Fq%3D%E3%83%86%E3%82%B9%E3%83%88"
}

仕組み

-n オプション

-n こと –null-input のオプションはインプットをnullとして、引数に指定したフィルタのみを実行する。オプションを使わずに表現すると以下のようになる。

$ echo 'null' | jq '"hoge"'

そのため。フィルタにただの文字列があると、それがそのまま出力される、上記の場合実行結果は以下のようになる。

$ echo 'null' | jq '"hoge"'
"hoge"

パイプ

シェルのパイプ同様にjqでもパイプすることができる。たとえば以下のような場合

$ echo '{"key": {"key2": "value"} }' | jq '.key'
{
  "key2": "value"
}

key2の値を取り出したければ更にパイプでつなげると良い。

$ echo '{"key": {"key2": "value"} }' | jq '.key | .key2'
"value"

@によるエスケープ

jqでは @uri@base64 のような@から始まるものを記述するとその形式に変換する。パイプの例を使うと以下。

$ echo '{"key": {"key2": "value"} }' | jq '.key | @base64'
"eyJrZXkyIjoidmFsdWUifQ=="

3つを掛け合わせる

$jq -n '{"url": "https://example.com/search?q=テスト"| @uri}'

{"url": "https://example.com/search?q=テスト"| @uri} という形のフィルタを作って、 "https://example.com/search?q=テスト"| @uri に対してはパイプによるエスケープをかけることで、htmlの部分だけを変換することをしている。

参考サイト

シェルでただ使いたい人のためのgo言語での外部ライブラリの入れ方

GoLangをちゃんとやろうと思い始めたんだけど、俺はパッケージだけ使いたいねん…というときにどれもイマイチしっくりこなかったのでメモ

環境

$ go version
go version go1.8 darwin/amd64

入れ方例

A Tour of Go で上げられている gotour を例に説明する

GO_PATHの確認

$ go env GOPATH
/Users/UserName/go

1.8以降だと環境変数 $GO_PATH が何もない場合は ~/go がデフォルトで指定される

パスを通す

$GO_PATH/bin 配下を加えておかないと毎度binまでのパスを指定しないといけないので以下のような感じでパスを通しておく

# 今回は~/go/bin が相当するので以下の感じに
export PATH=$PATH:$HOME/go/bin

go get でパッケージを入れる

go get github.com/atotto/go-tour-jp/gotour

これでめでたく

gotour

で実行されるようになります。

参考リンク

jquery で 要素の確認に length を使うのであればちゃんと比較演算子を使って欲しいという気持ち

コードレビューしてるとときたま見かけて、すごくなんとも言えない気持ちになったのでそれに対する叫び的な雑記

よくあるコード

<div id="xxx">
    <div class="sample">
        サンプル
    </div>
</div>
$(function(){
    if($('#xxx').children('.sample').length) {
      console.log("class sample has");
    }
});

みたいな形で もってないと length が 0になるので、 ifの結果がfalseになるというもの。

よくあるコードのつらさ

  • jqueryの知見がない場合、要素の確認ではなく要素数の確認をしていると誤認する
  • lengthって数値を返すものでbooleanを返すものじゃないのに、jsが0をfalseと受け取る性質を使っているので非常にグレーゾーン
  • ifの判定はなるべくbooleanとなるような値を利用すべき

よくあるコードの改善案

  • ちゃんと比較演算子で表現する
  • わかりにくいのでコメントに書く
$(function(){
    // lengthが0のときは要素として存在しないとみなす
    if($('#xxx').children('.sample').length > 0) {
      console.log("class sample has");
    }
});

参考サイト

Railsでprimary key がid ではない場合 find_each はできない

Model名.all.eachModel名.find_each にしろというのはRubocopでも怒られるド定番な修正対象ですが、できない場合があるのを知らなかったのでメモ

環境

Rails 5.2.1

できないパターン

これができない場合はそもそもRailsのfind系機能が使えないので気づくんですが、ケースとしては…

  • primary_keyが存在しない/設定されていない
  • primary_keyが複合キー

みたいな状態が合致します。

なぜ上記2つの場合できないかというと、実際に範囲指定をしているコードが以下のような内容で、primary_keyを元にとっているからっぽい

def apply_limits(relation, start, finish)
  relation = apply_start_limit(relation, start) if start
  relation = apply_finish_limit(relation, finish) if finish
  relation
end

def apply_start_limit(relation, start)
  relation.where(bind_attribute(primary_key, start) { |attr, bind| attr.gteq(bind) })
end

def apply_finish_limit(relation, finish)
  relation.where(bind_attribute(primary_key, finish) { |attr, bind| attr.lteq(bind) })
end

activerecord/lib/active_record/relation/batches.rb#L262

でprimary_keyは以下みたいな感じ

def primary_key
  options[:primary_key] || default_primary_key
end

def default_primary_key
  "id"
end

rails/schema_definitions.rb at master · rails/rails

そのためRails然としているprimary_key設定であれば勝手にidで引くし、primary_keyが別名設定されていればそれで範囲指定してとっていくはず(ただ取り方を鑑みると整数値しか許容できない気もしますが)

参考リンク

良かったスライドをメモがてら貼って感想を書いていくのもいいのでは

日曜日なのでゆるやか日記です。

以下の記事を読んだ。

razokulover.hateblo.jp

割とすがる上司も先輩もいなく自分で切り開くほかない時代を長く過ごしてきたので、人のスライドやブログによる知見には非常に助けられてきた。

ただ、久しぶりに見返そうとするとアレ、どこにあったっけ?みたいになることがおおくネット上にすら残ってるのか不確かなことがある。

なのでたまには(というか正確にはネタ起こしができないときには)回顧録的にスライドへのリンクと感想を貼ってもいいのかなと思ったりした。

なぜ、UTCにおける1970年1月1日0時0分0秒がUNIXTIMEの始点なのかをざっと調べてみた

気になったのを調べてみた系雑記です。

『UNIXTIMEの0って1970年の元旦0時でしょ?』という知ってる人は知っている、知らない人は覚えてね的なネタ。なんでその日なのか…と思ってしっかりとした出典調べたんですが、ざっと見た限りだと何故かを説明したものはなく、ただただ仕様という感じ。

その中で日本語の記事だとWIREDでデニス・リッチー2000年問題に関してインタビューした記事の和訳があり

UNIXのエポックは、1970年1月1日の午前0時。ただし、この日がUNIXの誕生日というわけではない。UNIXのOSは、まだ荒削りだったとはいえ、1960年代には存在していた。70年代の初めの日付をシステムにプログラムしたのは、ひとえに、そうするのが都合がよかったからだと、デニス・リッチー氏は説明する。リッチー氏は、UNIXの黎明期にベル研究所UNIXの開発に取り組んだ技術者の1人だ。 「当時は、テープもなかったし。複数のファイルシステムが稼動していて、われわれは、元となる時間を常に変更していた」とリッチー氏は言う。「とうとう、『当分オーバーフローしないような起点を設定しよう』ということになった。1970年1月1日が一番よさそうに見えた」

2000年問題は「問題なし」 1970年1月1日午前0時から10億秒目を刻むUNIX|WIRED.jp

ということで当時の時代背景 + ビットあふれのバグこわいよねーから1970年が設定されている様子だった。(UTC策定もだいたい1970年代あたり)

たまに1969年とか設定して意図しないことが起きたりする(CookieのExpireとかであった)ので、こんなトリビアエピソードも含めて、頭にしっかり残すようにしたい。

RSpecでテストをpendingしたい場合はxから始まるメソッドにリネームするといい

こんな機能があるんだという気持ちになったのでメモ

環境

rspec (3.7.0)

使いかた

example_spec.rb として以下のスペックを書いてみる

実行すれば以下の結果

require "rspec"

describe "DummyTest" do
  describe "Target" do
    context "Case1" do
      it "SuccessA" do
        expect(true).to be true
      end

      it "SuccessB" do
        expect(true).to be true
      end
    end

    context "Case2" do
      it "FailedA" do
        expect(false).to be false
      end

      it "FailedB" do
        expect(false).to be false
      end
    end
  end
end
$ bundle exec rspec example_spec.rb 
....

Finished in 0.0161 seconds (files took 0.16465 seconds to load)
4 examples, 0 failures

このときCase2のテストをスキップしたい場合は以下のように context から xcontext に書き換えるとスキップする。

xcontext "Case2" do

書き換え後の結果は以下

$ bundle exec rspec example_spec.rb 
..**

Pending: (Failures listed here are expected and do not affect your suite's status)

  1) DummyTest Target Case2 FailedA
     # Temporarily skipped with xcontext
     # ./example_spec.rb:16

  2) DummyTest Target Case2 FailedB
     # Temporarily skipped with xcontext
     # ./example_spec.rb:20


Finished in 0.00591 seconds (files took 0.09567 seconds to load)
4 examples, 0 failures, 2 pending

この x をつけたメソッド、 xdescribexit も用意されているので、spec書いていて特定のものだけ抜き出しでみたいなとかそういう時に便利。

参考リンク