2020-08-17 にっき
Deviseの話題をTwitterで見て現代的ではない名前見かけたので書き換えておいた
2020-08-10 るりまに@undefを足し
火曜、るりまの日にこれを解決してみるか〜と思ってbitclustのソースコードを読んでいた
雑なPull Requestを出した
bitclustわからないのがわかる
ruby-jpでgem-codesearchが最近csearchのインデックスが4GB越えて動かないという話をznzさんから教えてもらった
zoektを入れgem-codesearchのインデックスを作り直した
足りてるかわからないけどこの辺をやった
go get github.com/google/zoekt/ go install github.com/google/zoekt/cmd/zoekt-index cd path/to/gem-codesearch git pull env GEM_CODESEARCH_DIR=/mnt/gems/gem-codesearch bin/gem-codesearch-setup all | tee setup.log.2020-08-09-19:32
容量なかなか
du -h zoekt-index 68G zoekt-index
コマンド雑にいれて
go install github.com/google/zoekt/cmd/zoekt-webserver go install github.com/google/zoekt/cmd/zoekt
これでよいっぽい
% zoekt -index_dir ./zoekt-index '"\.to_json\}"' | grep expect
最近私はわりとプログラマ向いてないのかな〜と思ってしまう機会が多い。
例えば前にかいた記事についてginza.rbでこう言及されていたけれども
いささか危険思想 https://speakerdeck.com/toshimaru/how-to-deal-with-fat-model?slide=63
辞書をひくと「かなり」の意でもちいられていそう。つまりかなり危険思想。その提唱者が私。
いささ か [0][2] 【些▼か・聊▼か】 一 ( 副 ) ① 数量・程度が少ないさま。少し。幾らか。自己の事柄については謙遜を、他者の事柄については婉曲を表し、「かなり」の意で用いられることがある。 https://www.weblio.jp/content/%E3%81%84%E3%81%95%E3%81%95%E3%81%8B
他、最近私が書いていたコードに普通書かないという感じのコメントがついたりして、普通に書くけどなあという感じで納得がいくまでコメントを返すというプロらしからぬ反応をしてしまい色々と考えていたのでこのへんを読んでいた。
結果、私の中では大分理解が深まったしコードはよりよくなったが疲れた。たぶん普通に書くけどなあのあたりの受け止め方が微妙な感じではあったと思う。 私は主語省略された「普通」だと、この図でいうと画面全部みたいな主語デカさで受け止めてしまう感じがある。 結果、普通との違いをちゃんと認識するまではわりと延々とコメントを書くけど範囲が広くて無限に話が広がる感じ。
一方、この「普通」が限定されていれば比較的楽に受け入れられる。 例えば「私は書かない」だったり「このアプリでは書かない」だったり、業務委託ではいった先で「この会社では書かない」と言われたら、かなり範囲が狭まるので「はい」で済むこともある感じ。(済むこともある、と書いたのはなぜかというと、業務委託で入っても普通に延々と話すの稀によくあるから...) 私はコンテキストにより「普通」の主語が落とされているときにその普通は何にとっての普通なのかがうまく読み取れないんじゃないかなあ、という感じ。
「普通書かない」と言われたときに全gemからgrepをして他に書いている人がいない、みたいな場合も多分納得すると思う。 しかし、全gemからgrepできる環境が個人マシンにある自体がそもそも既に普通ではない可能性が高い。見つかったとて。
日本語難しすぎる〜〜〜
プラレールのさまざまな種類のレールを買い足したので様々なレイアウトが組めて楽しい、けど拡張しようとすると普通のレールも含めてもっと欲しくなっちゃう。まいっちんぐ。
3連休はもう1つぐらいOSSしておきたいけど特に何もできず終わりそう。引っ越しの作業が粛々と進んでいる。
会社の日報的なのによもやま話欄があってそこをこのにっきに吸い出してもいいかもしれないなあ。
敬具
2020-07-29 にっき
昨日のは2020-07-28 にっきだったのだな
冷蔵庫と洗濯機がきた。洗濯機の配管をまだつないでいない。繋がねば着る服がなくなる。 今週を凌いで週末に何か、整理整頓を進めたい。 退去からやれという話だが。
omniauthとなかよくなりつつある
今日職場で自分がgemに追加したオプションを見かけてとっても嬉しかったので私が作りました!!みたいなの出張って書いたりしていた
JSONのテストについて雑にscrapboxにまとめたがscrapboxには双方向のやりとりが無いからTweetしてもらうかブコメしてもらって流行りに流行って自分がブコメをエゴサするぐらいまでいかないとコミュニケーションが発生しないんだよな。 やはりscrapboxでメモしつつある程度のところの版をQiitaにスナップショットとしてあげてしまうのがよいのではないか。
Qiitaおじさん業をした。コメントを書いただけだけど。社のOrganizationに参加した。
今朝はn度寝してかなり破滅した感じがする。
子からうつった鼻喉の風邪、妻にうつさないように別の部屋で寝てるんだけど、もってきた唯一の寝床設備であるところのハンモックの設置をやる体力がなくフローリングに直で毛布しいて上に寝るどこでも寝れるギフテッドを発揮している
月末までこれでしのげば妻の寝具、脚付きマットレスが揃い私のマットレスが帰ってきていい感じになる予定。
環境が変わったので通う食べ物屋さんに変化が現れていい感じ。うまい。 ココイチのポークカレー(特に何も具のってないやつ)をはじめて注文してみたけど結構満足出来てしまった、とはいえ何もないので何か足したい。いいのがあれば....
2020-07-29 にっき
ここを手軽に書けるようにするのを怠っていた
最近は引っ越しをしている
4連休でRedmineパッチ会 #1に参加した
よさそうなissueを見繕ってくださっていて雑に直して3つパッチを投げた。
チケットは
時刻の表記の設定がCSV・PDFのダウンロードで効いてなくてぴえん、と https://www.redmine.org/issues/31637
前へ・次へにtitleつけるやつ https://www.redmine.org/issues/33572
後者の方、雑すぎて2クエリ増やしてしまったので直さねば。
4連休でbitclustとなかよくなったので、るりまに「編集する」のリンクを付けれるようになった。GitHubユーザーのみなさまがたにおかれましては、どのファイルをいじればいいか、どの行あたりなのかを知らなくても編集押せば編集できるのでかなり便利だと思う。
とはいえ新規でエントリ追加はできないので、やはりこれだけでは足りなくて
- rdocから未翻訳のエントリをるりまに足す
- 未翻訳のエントリをみた人が編集を押して日本語訳を追加する
の両輪かなあ。これで編集してくれる人が増えてくれると嬉しいなと思っています。
るりまでいうとbitclustのGraphQL対応を入れたいと考えている。 bitclustではHTMLを出力するまでのviewの部分も内包されているんだけど、そこが分離できるとフロントエンドが得意な人にRubyのコードを触らずにフロントエンドのほうで便利な機能を実装してもらいやすくなるかなあ、っていう。
基本的に他力本願なところがあり他人のちからを借りやすくなるような変更を入れていきたい次第
まあ「GraphQL実装したい」じゃなくて「GraphQL実装しました」報告がしたいところですが当面は引っ越しに集中しています。(まだ荷物の移動が終わっていない)
鼻水が出ていてシャワーをさぼったり耳たぶをいじっていたらピアスホールから出た汁が固まっていて「なるほど」という感じ、完成は遠い。
2020-07-14 にっき
自分はアヒルのように動けばアヒル、Arrayを拡張して回転寿司のように動くArrayは回転寿司、そういう雑な気持ちでRefinementsを使っているんだなあ。べんりなので...。
これは雑すぎですがこういう感じ
Refinementsたぶん今だけ男みたいな気持ちと相性よさそう
— はなちん (@hanachin_) 2020年7月14日
「こうでもかけるんだけど〜」とクラスを定義しだすと「クラスでいいじゃん」になるかと思いますがクラスを定義しなくていいというのが便利ポイントなのでその辺の音楽性の違いっぽい。 あとは同じことをやるならメソッドにしなくてもよくて結果を説明的な名前の変数名に入れればいいのでは、とかもありそうだけど、それもやはりすごく特定のユースケースに合わせたメソッドをその場だけで使うことが出来る、というところに価値を見出しているんですよね。 一般的なメソッドを組み合わせて呼びたいわけじゃなくて特定のユースケースに合わせて作ったメソッドが生えているのがよい。 そういう意味でいうと自分はやはり語彙を再定義しているRSpecみたいなところをRubyの書きはじめの最初にガツンとうけてしまったので文化的な背景がやはり違いそう。
色々と話していてrefine(Array)
よりも refine(sushi.singleton_class)
のほうがより範囲が狭くなって Module.new
との相性がよいことに気がついた。
これの感想にリプ返していた
雑ではない仲間
rake タスクを refinements でなんかきれいにやりたいやつは普通にクラス定義してそっちに渡せばいいのでは……
— はくどー (@HKDnet) 2020年7月14日
そうなりますよね(テストできるし)
— はなちん (@hanachin_) 2020年7月14日
一時的にしか使わないタスクを未来永劫メンテし続けたくはなく、そういう終わったクラスをどうマネージするかみたいな問題があると思うんですが、それを解決できるかもって一瞬思ったけどやっぱテストしにくいし微妙かと思いました
— はくどー (@HKDnet) 2020年7月14日
雑仲間
https://t.co/ulkFjgBv2O
— Tsuyoshi Hoshino (@hoppiestar) 2020年7月14日
> rakeタスク中の処理を読みやすくメソッドにわけたいときもRefinementsは便利
これ! これ以外は なんとかなってしまう人生だった気がする
絶妙な雑さのときに便利なんですよね
— はなちん (@hanachin_) 2020年7月14日
名前つけたくないときとか
わりと書捨てに近いときとか
アプリケーションの中でライブラリみたいなことをやるときに補助的なAPIを完全にprivateなものとしてはやせるのはやはり便利そう
アプリケーション側だと『その場でのみ呼び出せるメソッド』を定義する時に使うなーより厳密な private メソッドを定義する場合とか / Refinementsの用法用量わからない日記 - hanachin temporary - https://t.co/H0oyDzyTDs
— バンビちゃん@実際クソザコメンタル (@pink_bangbi) 2020年7月14日
よく使うのが module を定義する場合に『その module 内でしか使わないメソッド』を Refinements として定義する。普通は private メソッドにすることが多いと思うけど private メソッドは外からも呼び出せてしまうので危険
— バンビちゃん@実際クソザコメンタル (@pink_bangbi) 2020年7月14日
こういう感じ
— バンビちゃん@実際クソザコメンタル (@pink_bangbi) 2020年7月14日
module M
using Module\.new {
refine M do
# M 内でのみ呼び出したい
def bar
"refinem M#bar"
end
end
}
def foo
# OK
bar
end
end
class X
include M
def hoge
# OK
foo
# NG
bar
end
end
これの何が便利かっていうと通常 module は『mixin された側でどういうメソッドが必要なのか』を考えて書く必要がある。
— バンビちゃん@実際クソザコメンタル (@pink_bangbi) 2020年7月14日
なので雑にメソッドなどを生やす事がむずかしい
けど、Refinements を使うと本当の意味で「M でしか参照できない」メソッドを定義することができるので雑にメソッドが定義できる
このような事がこの記事に書いてあるぞ! / 【Ruby Advent Calendar 2018】あなたのしらない Refinements の世界【3日目】 - Secret Garden(Instrumental) - https://t.co/vhKChdJxWd
— バンビちゃん@実際クソザコメンタル (@pink_bangbi) 2020年7月14日
補助的なメソッドを衝突気にせずバンバンかけるの便利そう
— はなちん (@hanachin_) 2020年7月14日
モジュール関数を使えば Benri.hoge(obj, a, b) みたいに書くこともできますが、Refinements だと obj.hoge(a, b) みたいによりオブジェクト指向っぽくかけるので便利ですねー
— バンビちゃん@実際クソザコメンタル (@pink_bangbi) 2020年7月14日
これもそうかな
Refinementsの用法でふと思ったけど、concerns のモジュール内でApplicationRecordやApplicationControllerを拡張するのは便利かも?privateメソッドでメソッド名の衝突を気にしなくて済むかも。
— 神速 (@sinsoku_listy) 2020年7月14日
いい話!なので特にリプをしていなかった
アプリケーションコードでrefinementsを使うことが全然ない
— Pocke(ぽっけ) (@p_ck_) 2020年7月14日
雑仲間だ
使い捨てメソッドを Refinements を定義することはよくある
— バンビちゃん@実際クソザコメンタル (@pink_bangbi) 2020年7月14日
なんでなんだろうなあ
Refinementsはそれを使うのが目的化しやすいような?
— カルパス🦜 (@yoshi_hirano) 2020年7月14日
他の言語にはない機能なのでなくてもだいたいのことは書けるんだけど、みんな実際使っていったら気に入ったりブロックの中だけでRefinementsを有効にしたりしたくなると思うんですよね、便利なので。
— はなちん (@hanachin_) 2020年7月15日
便利というのは使わないとわからないので使うことを目的にはじめるのもよいんじゃないかな派です。
いいと思います。アプリケーションコードの文脈だと他のアプローチを提案しそうですが。
— カルパス🦜 (@yoshi_hirano) 2020年7月15日
わ、わかるが...!w
— はなちん (@hanachin_) 2020年7月15日
アプリケーションコードだとなんでそうなってしまうのかわからないのがわかる(言語化できていない)
この辺を読み直しているけど使ってみるとやっぱり削がれてしまった機能をもとめてブロック単位のRefinementsとかを作り出してしまうので使い勝手がよくないだけなんだろうか
magazine.rubyist.net rubykaigi.org github.com
組み込みを拡張したいとなるとそうですよね、という感じ
標準ライブラリを拡張するときだけ使ってる / 1件のコメント https://t.co/7iSPYgSQna “Refinementsの用法用量わからない日記 - hanachin temporary” https://t.co/jWJhJf3F7C
— 神速 (@sinsoku_listy) 2020年7月14日
それRefinementsじゃなくても出来るよ、みたいな感じになりません? (ならない場面だけで使う?)
— はなちん (@hanachin_) 2020年7月14日
StringやArrayなどを拡張するときしか私はRefinementsを使っていないですね...。他はprependで事足りることが多いです。
— 神速 (@sinsoku_listy) 2020年7月14日
はい
人生で唯一真面目に書いたRefinements、1.secondをactivesupportなしでやるやつだけだわ
— wata (@wata727_) 2020年7月14日
activesupportを依存に追加すると死ぬ病
— wata (@wata727_) 2020年7月14日
— wata (@wata727_) 2020年7月14日
Refinementsの用法用量わからない日記
自分はわりとカジュアルにRefinementsを使うけど基準はどこにあるのだろう。と今日考えていた。
RefinementsSpecを読んでみる
はい
Monkey patching is a powerful feature of Ruby.However, it affects globally in a program. Therefore, a monkey patch might break code which doesn't expect the extended behavior, and multiple monkey patches for the same class might cause conflicts.To solve these problems, Refinements provide a way to extend classes locally. https://bugs.ruby-lang.org/projects/ruby-master/wiki/RefinementsSpec
モンキーパッチはRubyの強力な機能の1つ。しかしながら、モンキーパッチはプログラムにグローバルに影響を与える。したがって、モンキーパッチはモンキーパッチにより拡張された振る舞いを予期していないコードを壊す可能性があり、また一つのクラスに対して複数のモンキーパッチを当てるとコンフリクトを引き起こすかもしれない。これらの問題を解決するため、Refinementsはクラスを局所的に拡張する方法を提供する。
みたいな感じ?
局所的に、というのがキモっぽい
クラスの動作を拡張したいが局所的にしたい、というのが大事っぽい。 具体的にはどういうときなのか判断はわりとグラデーションがあると思う。
アプリケーションコードにおいて局所的に拡張する必要性
実はほとんどないのでは、と思う。
例えばアプリケーションのコードの動作を拡張したい場合
「アプリケーションコードの動作を拡張したい!」 「じゃあアプリケーションコードを書き換えようか (完)」
はい。
「局所的にアプリケーションの動作を拡張したい!」 「じゃあそういう設計でアプリケーションコードを書き換えようか (完)」
はい。
となりますよね。
現代のモンキーパッチはオープンクラスをせずにできる
モンキーパッチをどういうときに用いるかというと
- 組み込みライブラリの動作を変更したい
- gemで導入したライブラリの動作を変更したい
などアプリケーションコードとは違う自らが書き換えできないコードをダイナミックに書き換えるときだと思う。 じゃあそれモンキーパッチじゃないとできないの?というと現代だとそんなことはない。 例えば書き換えたgemをGitHubに置いてGemfileでgitリポジトリを指定すれば済む。
だがそれだともちろん局所性はない。
オープンクラスが必要な場面
やっぱり自分の手が届かないところのコードの動作を書き換えるときかなあ。(自分が書いてるのはだいたいそう)
局所性が必要な場面とは
例えば同じ名前のメソッドが被ると困るだろう。 でも現実問題アプリケーションコードのためにモンキーパッチで拡張したときに困るのって、既にあるメソッドの名前と同じ名前で書き換えたときぐらいしかなさそう。 別の名前のメソッドを追加して動作を拡張するのはまあ、名前がかぶれば変えればいいだけなので。
多分ライブラリを書いている場合は、ライブラリが使われる場面には手が届かないのでより局所性に気を使う必要がありそう、なのでRefinementsの使いどころはアプリケーションコードよりはありそう。
局所性を求めるとやっぱりRefinements、だが真に必要な場面は
局所性を求めるとRefinements、これは多分異論ないと思う。
だけど真にRefinementsでしか実現しないような使いどころとなるとかなり限られてしまいそう。
- アプリケーションコードではないライブラリの動作を拡張している
- アプリケーションコードの方の設計を変えられない
- ライブラリの方で定義されているメソッドの動作を変えるので局所性が必要
- 自分のコードがどこで使われるか分からないので自分のコード内だけで使う動作に局所性が必要
アプリケーションからは変更出来ないコードを変更したいが影響範囲を狭めたい、そのぐらいしかなさそうで。ほかはアプリケーションコード変えればいいだけだから。
アプリケーションのコードなのかライブラリのコードなのかの境界はどこにあるのか
例えばDeviseのモジュールを例にすると、Deviseのモジュールを使っているクラスにはDeviseのモジュール由来のメソッドがいくつか生える。
このときDeviseによって生えたメソッドを利用し、アプリケーション固有のユースケースを実現するコードはアプリケーションコードだと思える。 一方「この機能はDeviseの方でも持っていてほしいなあ、わりと特殊なユースケースかもしれないけど」と思うコードや「これはDeviseと組み合わせて使えるライブラリに出来るコードかもしれないなあ」というコードもあると思う。 それはアプリケーション固有の事情を表していないので純粋に単なるアプリケーションコードとしてしまうにはもったいない。
十分一般的な目的に抽象化されたアプリケーションコードはそれはもうライブラリなのでは、と思ってしまう。
Refinementsの使いどころにアプリケーションコードとライブラリの境目も含めてしまってよいのでは
そういう本来ならこのメソッドはライブラリに置かれててくれどうぞ、みたいな気持ちとRefinementsは相性いいと思うんですよね。
特定の場面でしか発生しないようなユースケースも十分抽象化されていたら実質ライブラリなのでは
例えば大クラス主義的にArray
に色々生えてて日常生活ではことたりるんだけど、たまーに「アプリケーション固有かもしれないけど each_with_いろは
がほしい」とかあると思うんですよ。
それもわりとアプリケーション固有なのかライブラリなのか微妙な立ち位置で、Refinementsがはまると思うんですよね。
関連レコードを引くとかscope使いたいとかそういうActiveRecordの機能によるのはactive_typeのようなgemを使ってやると思うけど、 単純にこの場面でだけだけメソッド生やしたいとかならRefinementsで生やすだけでも十分みたいなの結構あると思うんですよね。
Refinements使うのを気をつけたほうがよい場合
めちゃくちゃパフォーマンス気にする場合はRefinements使わない方がいいのかなあというふわっとした感想です。(要出典、ここはFUDになりそうなので書かないほうがよかったかもしれない)
動的にメソッドの動作を切り替えたい場合にもRefinementsは便利
無名クラスでもできるかもしれませんが #to_refinements
メソッドでRefinementsのモジュールを生成するようなコードを書くと using object.to_refinements
で動的に動作を切り替えられて便利そうです。
rakeタスク中の処理を読みやすくメソッドにわけたいときもRefinementsは便利
これに関してはモデルにうつしたほうがテストしやすいのでいい派が多分いると思います
これも特定のユースケースの場合のみ機能を拡張したい場合の1つかなあ 通常のアプリケーションコードの中では使われてほしくないけどrakeタスクの中だけではメソッドであってほしい、そういう気持ち。
何かを受け流すときにもRefinementsを使うと便利
例えばRuboCopで定数のfreezeを呼びたいけどどうしてもテストではfreezeされてると都合が悪いとき、とか。
以外と真に必要そうなケースあるな
用法用量所感
どうしてもRefinementsじゃないとダメ!となる前にアプリケーションコードの変更でどうにかなってしまう場合が多い。 なのでそういうどうしようもない場合にのみRefinementsの処方を限定するとRefinementsを使う機会がかなり減ってしまうと思う。
アプリケーションコードなのかライブラリなのか曖昧な、アプリケーション固有のユースケースのようなそうでないような、ライブラリに置かれててくれどうぞ、みたいな気持ちとRefinementsは相性がいいと思う。
まとめ
ハチャメチャにRefinementsキメましょう