頭の中は異空間

ものづくり中心

【Rails】ファッキン黒魔術

どうも。

Black Magic

 

Rubiestには少なからずブラック・マジシャンが存在するするようです。所謂メタプログラミングのことです。CとかJavaとか、別の言語出身の人だとこのRubyという魔の言語を用いたコードを読むとき、必ずと言っていいほど1度はこの「黒魔術」に悩まされることだと思います。で、チームで開発しているにも関わらずそれを当たり前のように書く奴や書いた後コメントやドキュメント等で一切フォローしない人ってやっぱりいます。糞すぎる。

コードをgrepすりゃ見つかる、なんて考えだとRubyではドツボにはまるかもしれません。期限が近くて切羽詰まっているときにこんなコードに出くわすと、確実に殺意の波動に目覚めます。アホをdisるためにも、アーンド、多少なりともコードを改善するために長々と書きます。

 


何が問題?

grepしづらい

つまり、影響範囲が絞りにくいことです。当然、特定に時間がかかります。

今探しているメソッドが実は動的に作っているかもしれないって気づいたところで、でもどの部分が動的に、どこで作られているのかを知る必要がありますね?しかもその糞メソッドは1つとは限りません。さあすべて影響範囲内から探し出せる自信がありますか?

 

メソッド変更時にリスクがでかい

grepしづらいことに通じます。影響範囲が絞りづらいので、大規模な修正中に漏れが出やすいです。大規模サイトの修正担当箇所にこんな爆弾が埋まってたら発狂もんです。

 

これを避けるには

既存の黒魔術へ適切なコメントを振る。

既にあるものを修正するのはリスクがでかいため、なるべくいじらずに済ませたいもの。ただ今後見る人のためにコメントをそっと振っておいてやるのが上策かと。コメントは呼び出し元。これはevalで動的に定義してる、などと書く感じで。

 

使うなら場所を限定するか、特定の使い方に限る

例えば必ずmodelの頭に書く、とか動的に生成されるものはそうわかるメソッド名になっている、とか。後から見て理解しやすいようにフォローは必須です。

 

上級者以外に使わせない。

使うのが上手な人が書けばまだいいですが、テキトーな人がテキトーに書くとわけわかめです。間違いなく。本を出せるレベルの人が、非常に読みやすい使い方をお手本のようなレベルで書くのならまだ分かりますが...それと、もしチームでコーディングルールがあるなら、このことは書いてあったほうが助かります。

 

実装例

定義側

eval, class_eval, define_method, instance_variable_set

    # class_eval
    class Hoge
    end

    Hoge.class_eval {def fuga; "hogefuga"; end}
Hoge.new.fuga # ==> "hogefuga" # eval var0 = 10 var1 = 15 var2 = 20 index = 1 eval("var#{index}") # ==> 15 # define_method class Foo ["pee", "poo", "paa"].each do |word| define_method(word.to_sym) { word } end end Foo.new.poo # ==> "poo" # instance_variable_set class Bar def out @test end end bar = Bar.new bar.out # ==> nil bar.instance_variable_set(:@test, 5) bar.out # ==> 5

ザ・諸悪の根源。書いたら○されても文句は言えない。見かけたら討伐したい。

 

 

呼び出し側

send

    class Baz
      def method_1
        "method_1"
      end

      def method_2
        "method_2"
      end
    end
    # というclassに対してsend
    Baz.new.send(:method_1) # ==> "method_1"

まだましです。メソッド名が直後にわかるのですから。

 

これが全てじゃないです。ここでは非常に簡単な例を書きました。でも、初めて見た人は戦慄するのではないでしょうか。実際、この時点でかなり探しづらいです。

書き方次第でいくらでも上等な料理にハチミツをぶちまけることが出来ます。

 

考えるべきこと

便利だから使う、も大事ですが単に便利だからあ~じゃなくて便利だし使うことによるデメリットをメリットが上回っているとか、開発そのものに支障が出ないかをよく考えて問題ないなら使う。そうすれば、別の人がそのコードを触っても大した苦労はしないはずです。

 

結論、オナニーは1人でやれ

チーム開発で頻繁にこんなNBCを、さも当たり前のように用いる奴は余程の乱交マニアかオナニー依存症の糞野郎だと思ってますが、対策を練れば今後そいつの頭にカラシニコフ銃を突きつける必要はなくなります。

仮にどうしても使いたくなったとしても、一歩下がって考えてみます。すると本当にそんな危険物を取り扱う必要があるのか、検討してみたらそんなことなかったりします。仮にメソッド定義が増えて多少ファイルが長くなったとしてもそこまで悪影響するでしょうか?同じようなメソッドが数十個数百個単位で並ぶことって通常ありえますか?個人的にはNO。それでもDRYは守れるでしょ。Fat Model?純粋にModule分割すれば済む話(それもRails4からconcern使える)。黒魔術じゃないと駄目って、作ろうとしている物が元からそういうテーマのコードならまだしも、一般のシステムにこんなものを採用しなければならないなんて、そもそも設計からしておかしいに決まってます。

それでもどうしても使いたければ、迷惑だから1人でおとなしくローカルで勝手に何か作ってればいいんじゃないかな?

他の言語ではこんな危険なことをしなくても間に合っています。Rubyだとなまじ自由度が高すぎるからこその弊害というべきか。

誰かが書いてるのを見たらこっそりIOCCC(言語は違うけどな!)でも勧めてみたらどうでしょう?

今回の件にかかわらず独りよがりなコードを書いたり無駄に高度な「こんな書き方あんだぞ(ドヤア)」って見せびらかすような真似はただただ面倒で嫌われるだけなので、やらないこと推奨。如何に見やすいコードを書けるかそして分かりやすい設計にするかって超絶大事です。

 

ところで、後で思い返してみたらJavaにもリフレクションっていう機能があったことを思い出しましたが、まぁ同じことですね。使わないにこしたことはないです。

BackboneJS, AngularJS無しで外部HTML読み込みするコード

どうも。

 

HTMLの一部を動的に書き換える方法としてはappendやbefore, ajaxなどといった手段があります。HTMLを動的に書き換えるのには、BackboneJSとAngularJSを使った書き換え方法もあります。でも新たにライブラリを習得するのも面倒なのでもっと簡単にやってしまいましょう。

 


概要

仮にRailsでやるとして、動的に書き換える置き換え後のHTMLを外部HTML(partial)として用意するだけ。たったそれだけ。

非常に単純。だからいい。

 

パターン1

コード

HTML

・メインHTML
<div id="target">
  <p>ここが書き換えられる</p>
</div">

・置き換え元HTML
仮にファイル名を_result.html.erbとします。
<div id="result">
  <p>ここが置き換え後</p>
</div">

JS

$(function() {
  $("#target").load("_result.html.erb");
});

 

置き換え後

<div id="target">
  <div id="result">
    <p>ここが置き換え後</p>
  </div">
</div">

load()ではファイル名を指定します。#resultの箇所がそのまま置き換えられるのではなく、読み込んだHTMLが該当する要素直下に配置されます。そのため#targetは消えません。

ファイル内の特定の箇所だけを読み込みたい場合は、引数をスペース区切りして2つ目に要素のセレクタを指定します。

 たとえば_result.html.erbの中のid="hoge"を読み込みたいなら、$("#target").load("_result.html.erb #hoge");という風にします。

 

パターン2

コード

HTML

・メインHTML
<div id="target">
</div">

・置き換え元HTML
仮にファイル名を_result.html.erbとします。
<div id="result">
  <p>ここが置き換え後</p>
</div">

 

JS

$(function() {
  $.ajax({
    url: 'new_html',
    type: 'get',
    data: ~~(なんか渡したい渡したいデータ),
    success: function(data) {
      if (data.html) {
        $('#target').html(data.html);
        // 1度だけ置き換えたいなら$('#target').replaceWith(data.html);とする。
      }
    }
  });
});

 

Rails

・controller
def new_html
  html = {}
  html[:html] = render_to_string(
  partial: 'result', locals': {
    # ここにpartialに渡す変数
  })
  render json: html.to_json
end

 

置き換え後

<div id="result">
  <p>ここが置き換え後</p>
</div">

こちらはrender_to_stringでpartialを読み込んでajaxで置き換えるパターンです。success時に.html()か.replaceWith()で置き換えることが出来ますが、元となる#targetは消え、新しい要素に置き換わります。イベント設定とか置き換え後HTML内に変数を利用する事を考慮すると、こちらのほうが使いやすいです。

 

以上、メチャクチャ簡単な例でした。

SF好きにお勧めしたいミチオ・カクの本

どうも。

f:id:notwo:20160919123051j:plain

 

SF映画とかゲームの中に当たり前に出て来るワープ、テレポート、魔法、意思を持ったマシン、宇宙エレベーターライトセイバー、etc

これらは今でこそ架空の出来事だけど、今後テクノロジーが進化していけば実現する可能性が見えてきます。そんな絵空事に近いテーマを糞真面目に考えている人がいます。

超ひも理論の権威のミチオ・カクという人がそうで、知る人ぞ知るって感じだけど宇宙論語るなら絶対避けて通れない人じゃないかな?

 


 

主要な著作一覧

NEXT WORLD―未来を生きるためのハンドブック

 

2100年の科学ライフ

 

サイエンス・インポッシブル―SF世界は実現可能か

 

フューチャー・オブ・マインド―心の未来を科学する

 

どれもそこそこボリュームのある本です。しかし読み応えは十分で、テーマは結構似通っています。SF好きなら読んでおいて損はないどころかむしろ知らないと損とさえ思えます。

これらの他にもカク博士のSF研究室ってタイトルでニコ動にも上がっていたんですが、すでに削除されているようです。と思ったら、Youtubeで検索したらたくさん出てきますね。この人のすごいところは、思いつきでものを言ってるのではなく科学的にこういうことすれば可能っていう理論的な説明をしているので、説得力を感じるところ。

 

本当に可能かは分からない

でもずっと先の話で、今の自分らの死後、世代交代が何度も起こった後の話なので当然それを証明する手段はないと思います。だからって不可能だと決めつけるのは良くないです。江戸時代の人たちからしたら今のインターネットどころかPCや電車、便利な家具や音速を超えるジェット機の存在など予想もできなかったはず。かつ、それを予言した人がいたとしても誰も信じなかったはず。それと同じで、今の科学力と資源では実現できない問題が多すぎて現状では考えもよらない要素が多いです。だから自分たちの想像を遥かに超えた自体になっている可能性があるということ。直近では火星行きロケットと火星移住が課題になっています。マーズ・ワンとかそうです。もっと身近なところだとテスラ・モーターズGoogleの取り組んでいる自動運転車があげられます。

 

リスクもでかい

家に帰ると勝手に適切な温度にエアコンが起動して調整してくれたり、靴を脱いだら勝手に揃えてしまってくれる機能、お手伝いロボット程度であればいいですが宇宙産業はとにかくカネがかかるのと軍事目的の逆輸入(元々ロケットやPCというより計算機は戦争目的で出来たもの)もありうる話なので対策が必要だと思います。最近でもドローンがホワイトハウス敷地内に落ちたとか問題になってるしね。

 

未来が楽しみになる

危険性もあるけど、それ以上にこれらが実現したら生活が今より良くなるので、早くそうなってくれと願うばかりです。リアルに「かがくのちからってすげー」ですよ。一瞬で日本からブラジルまで行けるようになる日も来るか?

今はIoT(モノのインターネット)が話題になっていてこれのおかげでまた便利な世の中が生まれそうです。見るだけでネガティブになる事件のニュースとかどうでもいい記事を見るくらいならこういう将来を明るく見通せる情報に触れるのもいいと思います。

Gitを便利に使うためのちょっとした工夫

どうも。

 

開発時に戻しが出たとき、commit単位で戻さずファイル単位で戻すようなことをやっていると非常に効率が悪いです。そこでcommit単位でrevertしたり履歴をいじりたい場合のためのちょっとした工夫をしてみます。

 


 

特定の機能、ファイル単位ごとにcommit

例えば画像投稿の機能があるなら、その機能の分を作ってからcommitするとか。ファイル単位であれば、CSSでデザインをまとめて変える場合に、HTMLファイルと別でcommitしておけば、HTMLに戻しが要るならHTMLのcommitにだけ注目すれば良いし、逆もできますね。というわけで、戻しがしやすいことがメリットです。

 

git addするときに一工夫

git add ファイル名で1つずつ追加するのが通常です。ファイル数が増えていくとこれが辛い辛い。2桁行き始めると、効率が悪いです。そこでコマンド作っちゃいましょう。

git status | awk '{print $2}' | egrep '^app' | git add

 

特定の単位(JSだけとかmodelだけとか)の場合は上記のコマンドを頑張るのではなく、

git add ディレクトリ名/.

として、特定のディレクトリ配下のファイルのみをまとめてadd出来ます。

 

チーム開発時(1つのブランチを複数人で共有している場合を想定)

これは頻繁にconflictが起きてうぜ~ってなっちゃうんですけど、それを必要最小限に抑えようという工夫です。

自分のcommitする前にgit pull

例えば毎朝PC立ち上げたら、一旦下記のようなコマンドを実行することです。

git status
git pull origin ブランチ名:ブランチ名
# master取り込みが必要なら
git pull origin master:master
git merge origin/master

これでlocalを最新にした状態で作業を始めれば、あとでconflictすることも減ります。

conflictしたら常に最新のcommitを見てそれに合わせるか、良く分からなければ直前に同じファイルをcommitした人に変更内容を聞くのもOK。

 

などなど、ちょっとした工夫をしただけで作業に支障をきたすことが減ります。カッとなってキボクラになる前に、一歩立ち止まって考えるべし。

勇気づけられる曲、落ち込んだ時に聴くと良い曲(主にアニメ)

なんかあって落ち込んでも、そこで奮起して立ち直るには音楽の力を借りるのは中々良い手段だと思います!歌詞からして元気付ける気マンマンの何曲か、知っている限りを挙げてみます。

 


 

勝利の歌 (ダンデライオン)

www.youtube.com

 

begin the TRY (森久保祥太郎)

www.youtube.com

 

The Biggest Dreamer (和田光司)

www.youtube.com

 

Break Up (宮崎歩)

www.youtube.com


 

心のファンファーレ (奥井亜紀)

www.youtube.com

 

元気のシャワー (前田亜季)

www.youtube.com

 

GONG (JAM Project)

www.youtube.com

 

英雄 (doa)

www.youtube.com

 

ひとりじゃない (DEEN)

www.youtube.com

 

くすぶるheartに火をつけろ (影山ヒロノブ)

www.youtube.com

 

Heats (影山ヒロノブ)

www.youtube.com

 

Amazing Break (TERRASPEX)

www.youtube.com

 

ボクらの冒険 (Kids Alive)

www.youtube.com

 

Wonderful Life (酒井ミキオ)

www.youtube.com

 

Reckless Fire (井出泰彰)

www.youtube.com

 

これも上げ始めるとキリがないです。

これ書いて気付きましたが、テラフォーマーズのやつ以外みんな古いですね。俺がその世代だってことがバレバレです...

 

多くの人が気づいている通り、流行りの歌よりアニソンのほうが名曲多いっていうのはガチ。

どちらかと言うと朝より夜の方が個人的には聴いていて奮起出来るのですが、 やるぞ!って時は聴くといいかも。

こういうのをiTunesのアルバムに登録しておいて一気に聴くと燃えっぱなしになること請け合いではないかな?

他にあんまり書くことないんでこの辺で。

SF好きにお勧めするアニメ

どうも。

 

f:id:notwo:20160914210332j:plain

 

仕事一辺倒ではきついのでちょっと一息ついてアニメでも観ようと思ったので、せっかくなのでお勧めできるハイクオリティだと思うアニメを列挙してみます。

SF好きだし、SFを。

ネタバレにならない程度には解説を入れてみました。あらすじはググるべし。

エヴァとか攻殻機動隊とか、シリーズが多すぎるのとか観終わってない作品は割愛。。山ほどあるから全部観て載せるのとか無理(´・ω・`)

 


Steins;Gate(シュタインズゲート)

通称シュタゲ。ドイツ語と英語が合体した造語です。パラレルワールドとかタイムマシン関連の話が好きな人なら絶対観るべし!好きでなくてもこれ自体が名作だから観るべし!ゲームが原作で、そちらでしか観れないシーンがあると知って愕然。。それぞれのキャラの濃さというか役割というか、厨二病の主人公とかダルのオタクっぷりとかヒロインのツンデレっぷりとか、もう色々典型的すぎw

個人的にまゆしぃのトゥットゥル〜は癖になる

 

 

プラネテス

SF人間ドラマ。スペースデブリを回収する職業についた主人公とその同僚たちとのコメディから始まり宇宙空間の恐怖など大きな波乱を迎えるシーンもあり、回によっては結構ハラハラする。

 

機動戦士ガンダム00

ガンダム自体がシリーズ多すぎて追いつくの大変。。エクレアエクシアっていうガンダムが出てくる。アナザーの中では個人的に一番好きなのでpickupしました。刹那・F・セイエイの「俺はガンダムだ」のセリフの意味深さがなかなか。

 

スクライド

バトル物とか熱いアニメが観たい方にお勧め。グレンラガンの雰囲気が好きならこれも好きになるはず。世界三大兄貴の1人、ストレイト・クーガーの名台詞「お前に足りないものは、それは!〜〜 速さが足りない!」も聞ける。

OP, EDに限らず挿入歌などすべてが良曲。

 

電脳コイル

懐かしい感じがする町並みとGoogle Glassを思わせるメガネが特徴的。

ほんの少しホラー敵要素がある。あとみんな言うことだけど最後は泣ける。

 

ノエイン もうひとりの君へ

かなりマイナーな部類だと思います。知ってる人が周りにほとんどいなかった。。

これもパラレルワールド要素あり。

回が進んでいくと量子力学についての話が出てきますが全くの素人でも知識的には問題無し。絵が毎回微妙に違ったりするのは様式美。タイトルのもうひとりの君の意味がわかった時は鳥肌物でした。

あとOPのIdeaは良曲。

 

 

カウボーイビバップ

ザ・ハードボイルドアニメ。シティーハンターの空気感が好きなら合うかもしれない。というかシティーハンターと曲を入れ替えても違和感なさすぎて吹いたw

 

ぼくらの

OPのアンインストールで有名。アニメ自体より曲の一人歩きの方が目立ってるのは何故。。

とにかく鬱な世界観が漂うため、見る人を選ぶかもしれない。一応巨大ロボが出てくるけど、どう考えてもスパロボ参戦無理。規格外すぎる。。

 

ジパング

SF要素が一応入っている(タイムスリップ)ので入れました。モロ戦争物です。

物騒かもしれないが、戦艦大和とか56格好良すぎる。

イージス艦の凄さが改めてわかる。ただ作中のは日本製のはずなのにトマホーク搭載しているのは何故だろうか。突っ込むのは野暮だろうか。

アニメ版だと途中で終わっちゃうっぽくて、漫画版ではその続きまで見れる模様。

 

魔法少女まどか☆マギカ

バトル物。タイムリープパラレルワールド要素あり。

QBとか一部のセリフはもはやコピペにもなってるし名前だけどころかこのアニメ知ってる人は多い気がする。そしてマミさんがマミる瞬間は必見。

 

 

これ以上書くことが思いつかないなんて、わけがわからないよ。

Railsアプリ作成のために便利なコマンドを自作しよう

どうも。

 

複数のサービスを運用するようになったらunicornのstart, stopを毎回コマンド1つずつ打つのも面倒でしょうから、予めコマンドを登録しておいて一発ですべて起動/停止出来るようにしたほうが楽じゃね?ということで、実際に作りました。

 

下記を参考にしました。

自作のコマンドを作成した - Qiita

 

 

新コマンド一覧

UnicornをStart

# command for starting unciorn
#!/bin/sh

function startService () {
  cd $1
  bundle exec unicorn_rails -c config/unicorn.rb -D -E development
}

function startAllServices () {
  rails_root="Rails rootのパス"
  dir=( "${rails_root}/サービス名1" "${rails_root}/サービス名2" "${rails_root}/サービス名3" ... )
  for i in "${dir[@]}"
  do
    startService "${i}"
  done
}



if [ $# -eq 1 ]; then
  echo "サービス"$1"を起動"
  rails_root="Rails rootのパス"
  startService "${rails_root}/$1"
else
  echo "すべてのサービスを起動"
  startAllServices
fi
ps -ef | grep unicorn | grep -v grep

 

UnicornをStop

# command for stopping unciorn
#!/bin/sh

function stopService () {
  cd $1
  kill -9 `cat "tmp/development_unicorn.pid"`
}

function stopAllServices () {
  rails_root="Rails rootのパス"
  dir=( "${rails_root}/サービス名1" "${rails_root}/サービス名2" "${rails_root}/サービス名3" ... )
  for i in "${dir[@]}"
  do
    stopService "${i}"
  done
}

if [ $# -eq 1 ]; then
  echo "サービス"$1"を停止"
  rails_root="Rails rootのパス"
  stopService "${rails_root}/$1"
else
  echo "すべてのサービスを停止"
  stopAllServices
fi
ps -ef | grep unicorn | grep -v grep

 

サービス一覧を表示

# command for listing up services
#!/bin/sh

rails_root="Rails rootのパス"
ls -l ${rails_root} | grep -v @ | awk '{print $9}' | grep -v 'README.md'

途中grep -vしているのは、余計なシンボリックリンクを含ませたくないためです。

 

ディレクトリ一覧を表示

 

PC起動してからcd ~~とするのに便利。

# command for listing up service directories
#!/bin/sh

rails_root="Rails rootのパス"
ls -l ${rails_root} | grep -v @ | awk '{print $9}' | grep -v 'README.md' | xargs -Iargs echo ${rails_root}/args

 

配置例

俺の場合は/usr/local/bin/直下に配置しています。

 

実行方法

すべてのサービスをstartする

start_unicorn

特定のサービスをstartする

start_unicorn サービス名1

 

すべてのサービスをstopする

stop_unicorn

特定のサービスをstopする

stop_unicorn サービス名1

 

サービス一覧を表示

list_unicorn_service

 

サービスのディレクトリ一覧を表示

list_service_dir

 

といった感じ。これでいちいちkillしてbundle exec ~~ってただ面倒なコマンドを繰り返す必要がなくなりました。簡単なのでお試しあれ。